diff --git a/packages/skin-database/api/graphql/TweetsConnection.ts b/packages/skin-database/api/graphql/TweetsConnection.ts index 11993b3a..cc2ff0ae 100644 --- a/packages/skin-database/api/graphql/TweetsConnection.ts +++ b/packages/skin-database/api/graphql/TweetsConnection.ts @@ -1,7 +1,6 @@ import { Int } from "grats"; import TweetModel from "../../data/TweetModel"; import { knex } from "../../db"; -import TweetResolver from "./resolvers/TweetResolver"; /** @gqlEnum */ export type TweetsSortOption = "LIKES" | "RETWEETS"; @@ -44,13 +43,7 @@ export default class TweetsConnection { * The list of tweets * @gqlField */ - async nodes(args: never, ctx): Promise> { - const tweets = await this._getQuery() - .select() - .limit(this._first) - .offset(this._offset); - return tweets.map((tweet) => { - return new TweetResolver(new TweetModel(ctx, tweet)); - }); + async nodes(args: never, ctx): Promise> { + return this._getQuery().select().limit(this._first).offset(this._offset); } } diff --git a/packages/skin-database/api/graphql/resolvers/ClassicSkinResolver.ts b/packages/skin-database/api/graphql/resolvers/ClassicSkinResolver.ts index ae50ec97..01e7c18d 100644 --- a/packages/skin-database/api/graphql/resolvers/ClassicSkinResolver.ts +++ b/packages/skin-database/api/graphql/resolvers/ClassicSkinResolver.ts @@ -3,9 +3,9 @@ import { NodeResolver, toId } from "./NodeResolver"; import ReviewResolver from "./ReviewResolver"; import path from "path"; import { ID, Int } from "grats"; -import TweetResolver from "./TweetResolver"; import ArchiveFileResolver from "./ArchiveFileResolver"; import InternetArchiveItemResolver from "./InternetArchiveItemResolver"; +import TweetModel from "../../../data/TweetModel"; /** * A classic Winamp skin @@ -63,7 +63,7 @@ export default class ClassicSkinResolver /** * List of @winampskins tweets that mentioned the skin. * @gqlField */ - tweets(): Promise> { + tweets(): Promise> { return super.tweets(); } diff --git a/packages/skin-database/api/graphql/resolvers/CommonSkinResolver.ts b/packages/skin-database/api/graphql/resolvers/CommonSkinResolver.ts index bf885d28..84d6ec25 100644 --- a/packages/skin-database/api/graphql/resolvers/CommonSkinResolver.ts +++ b/packages/skin-database/api/graphql/resolvers/CommonSkinResolver.ts @@ -3,7 +3,7 @@ import SkinModel from "../../../data/SkinModel"; import ArchiveFileResolver from "./ArchiveFileResolver"; import InternetArchiveItemResolver from "./InternetArchiveItemResolver"; import ReviewResolver from "./ReviewResolver"; -import TweetResolver from "./TweetResolver"; +import TweetModel from "../../../data/TweetModel"; /** * A Winamp skin. Could be modern or classic. @@ -57,7 +57,7 @@ export interface ISkin { * List of @winampskins tweets that mentioned the skin. * @gqlField */ - tweets(): Promise>; + tweets(): Promise>; /** * List of files contained within the skin's .wsz archive @@ -124,9 +124,8 @@ export default abstract class CommonSkinResolver { tweeted(): Promise { return this._model.tweeted(); } - async tweets(): Promise> { - const tweets = await this._model.getTweets(); - return tweets.map((tweetModel) => new TweetResolver(tweetModel)); + async tweets(): Promise> { + return this._model.getTweets(); } async archive_files(): Promise> { const files = await this._model.getArchiveFiles(); diff --git a/packages/skin-database/api/graphql/resolvers/ModernSkinResolver.ts b/packages/skin-database/api/graphql/resolvers/ModernSkinResolver.ts index cfd40967..205f5c24 100644 --- a/packages/skin-database/api/graphql/resolvers/ModernSkinResolver.ts +++ b/packages/skin-database/api/graphql/resolvers/ModernSkinResolver.ts @@ -6,8 +6,8 @@ import { ID } from "grats"; import ReviewResolver from "./ReviewResolver"; import InternetArchiveItemResolver from "./InternetArchiveItemResolver"; import ArchiveFileResolver from "./ArchiveFileResolver"; -import TweetResolver from "./TweetResolver"; import { XMLParser } from "fast-xml-parser"; +import TweetModel from "../../../data/TweetModel"; /** * A "modern" Winamp skin. These skins use the `.wal` file extension and are free-form. @@ -71,7 +71,7 @@ export default class ModernSkinResolver /** * List of @winampskins tweets that mentioned the skin. * @gqlField */ - async tweets(): Promise> { + async tweets(): Promise> { return super.tweets(); } diff --git a/packages/skin-database/api/graphql/resolvers/RootResolver.ts b/packages/skin-database/api/graphql/resolvers/RootResolver.ts index 06bf9c50..d596925c 100644 --- a/packages/skin-database/api/graphql/resolvers/RootResolver.ts +++ b/packages/skin-database/api/graphql/resolvers/RootResolver.ts @@ -2,7 +2,6 @@ import IaItemModel from "../../../data/IaItemModel"; import SkinModel from "../../../data/SkinModel"; import TweetModel from "../../../data/TweetModel"; import SkinResolver from "../resolvers/SkinResolver"; -import TweetResolver from "../resolvers/TweetResolver"; import UserResolver from "../resolvers/UserResolver"; import SkinsConnection from "../SkinsConnection"; import TweetsConnection, { TweetsSortOption } from "../TweetsConnection"; @@ -75,12 +74,8 @@ class RootResolver extends MutationResolver { async fetch_tweet_by_url( { url }: { url: string }, { ctx } - ): Promise { - const tweet = await TweetModel.fromAnything(ctx, url); - if (tweet == null) { - return null; - } - return new TweetResolver(tweet); + ): Promise { + return TweetModel.fromAnything(ctx, url); } /** diff --git a/packages/skin-database/api/graphql/resolvers/TweetResolver.ts b/packages/skin-database/api/graphql/resolvers/TweetResolver.ts deleted file mode 100644 index ef440562..00000000 --- a/packages/skin-database/api/graphql/resolvers/TweetResolver.ts +++ /dev/null @@ -1,50 +0,0 @@ -import { Int } from "grats"; -import TweetModel from "../../../data/TweetModel"; -import { ISkin } from "./CommonSkinResolver"; -import SkinResolver from "./SkinResolver"; - -/** - * A tweet made by @winampskins mentioning a Winamp skin - * @gqlType Tweet - */ -export default class TweetResolver { - _model: TweetModel; - constructor(model: TweetModel) { - this._model = model; - } - - /** - * 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. - * @gqlField - */ - url(): string | null { - return this._model.getUrl(); - } - /** - * Number of likes the tweet has received. Updated nightly. (Note: Recent likes on older tweets may not be reflected here) - * @gqlField - */ - likes(): Int { - return this._model.getLikes(); - } - /** - * Number of retweets the tweet has received. Updated nightly. (Note: Recent retweets on older tweets may not be reflected here) - * @gqlField - */ - retweets(): Int { - return this._model.getRetweets(); - } - /** - * The skin featured in this Tweet - * @gqlField - */ - async skin(): Promise { - const skin = await this._model.getSkin(); - if (skin == null) { - return null; - } - return SkinResolver.fromModel(skin); - } -} diff --git a/packages/skin-database/api/graphql/schema.graphql b/packages/skin-database/api/graphql/schema.graphql index a4e0b660..bfddd5e8 100644 --- a/packages/skin-database/api/graphql/schema.graphql +++ b/packages/skin-database/api/graphql/schema.graphql @@ -116,9 +116,13 @@ 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 @@ -132,7 +136,9 @@ 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 } @@ -147,7 +153,9 @@ type InternetArchiveItem { last_metadata_scrape_date_UNSTABLE: 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)""" + """ + Our cached version of the metadata avaliable at \`metadata_url\` (above) + """ raw_metadata_json: String """The skin that this item contains""" skin: Skin @@ -233,7 +241,9 @@ 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 @@ -366,25 +376,6 @@ interface Skin { webamp_url: String @deprecated(reason: "Needed for migration") } -"""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.""" type SkinUpload { id: String @@ -412,12 +403,35 @@ 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)""" - likes: Int - """Number of retweets the tweet has received. Updated nightly. (Note: Recent retweets on older tweets may not be reflected here)""" - retweets: Int + """ + 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) + """ + retweets: Int @methodName(name: "getRetweets") """The skin featured in this Tweet""" skin: Skin """ @@ -425,7 +439,7 @@ type Tweet { _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 + url: String @methodName(name: "getUrl") } """A collection of tweets made by the @winampskins bot""" @@ -480,4 +494,4 @@ input UploadUrlRequest { type User { username: String -} +} \ No newline at end of file diff --git a/packages/skin-database/data/TweetModel.ts b/packages/skin-database/data/TweetModel.ts index 7aebc6a9..6f267568 100644 --- a/packages/skin-database/data/TweetModel.ts +++ b/packages/skin-database/data/TweetModel.ts @@ -4,11 +4,18 @@ import DataLoader from "dataloader"; import { knex } from "../db"; import { TWEET_SNOWFLAKE_REGEX } from "../utils"; import SkinModel from "./SkinModel"; +import { Int } from "grats"; +import { ISkin } from "../api/graphql/resolvers/CommonSkinResolver"; +import SkinResolver from "../api/graphql/resolvers/SkinResolver"; export type TweetDebugData = { row: TweetRow; }; +/** + * A tweet made by @winampskins mentioning a Winamp skin + * @gqlType Tweet + */ export default class TweetModel { constructor(readonly ctx: UserContext, readonly row: TweetRow) {} @@ -49,14 +56,29 @@ export default class TweetModel { return this.row.tweet_id || null; } + /** + * 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. + * @gqlField url + */ getUrl(): string | null { const tweetId = this.getTweetId(); return tweetId ? `https://twitter.com/winampskins/status/${tweetId}` : null; } - getLikes(): number { + /** + * Number of likes the tweet has received. Updated nightly. (Note: Recent likes on older tweets may not be reflected here) + * @gqlField likes + */ + getLikes(): Int { return this.row.likes ?? 0; } - getRetweets(): number { + + /** + * Number of retweets the tweet has received. Updated nightly. (Note: Recent retweets on older tweets may not be reflected here) + * @gqlField retweets + */ + getRetweets(): Int { return this.row.retweets ?? 0; } @@ -64,6 +86,18 @@ export default class TweetModel { return SkinModel.fromMd5Assert(this.ctx, this.getMd5()); } + /** + * The skin featured in this Tweet + * @gqlField + */ + async skin(): Promise { + const skin = await this.getSkin(); + if (skin == null) { + return null; + } + return SkinResolver.fromModel(skin); + } + async debug(): Promise { return { row: this.row, diff --git a/packages/webamp/js/media/index.ts b/packages/webamp/js/media/index.ts index 8779f6c8..84613802 100644 --- a/packages/webamp/js/media/index.ts +++ b/packages/webamp/js/media/index.ts @@ -37,14 +37,20 @@ export default class Media { // Via: https://stackoverflow.com/a/43395068/1263117 // TODO #leak if (this._context.state === "suspended") { - const resume = async () => { + console.log("Suspended on init"); + const resume = async (e) => { + console.log("Resuming", e); await this._context.resume(); + console.log("Resuming"); if (this._context.state === "running") { + console.log("Runnign!"); // TODO: Add this to the disposable document.body.removeEventListener("touchend", resume, false); document.body.removeEventListener("click", resume, false); document.body.removeEventListener("keydown", resume, false); + } else { + console.log("Not running"); } };