From 650b3bc13cbb10737dbd602db653f1fd6047fa05 Mon Sep 17 00:00:00 2001 From: Ivan Malison Date: Mon, 20 Jul 2026 14:46:00 -0700 Subject: [PATCH] Regenerate schema with upstream Strawberry --- src/schema.gql | 3070 ++++++++++++++++++++++++------------------------ 1 file changed, 1536 insertions(+), 1534 deletions(-) diff --git a/src/schema.gql b/src/schema.gql index c42221d..76ed32f 100644 --- a/src/schema.gql +++ b/src/schema.gql @@ -1,3 +1,978 @@ +directive @oneOf on INPUT_OBJECT + +type AddShotAnnotationErrors { + error: DoesNotOwnShotErrOtherErrorNeedsNote! +} + +type AddShotAnnotationReturn { + value: SuccessfulAddAddShotAnnotationErrors! +} + +input AggregateInputGQL { + aggregations: [AggregationInput!]! + filterInput: FilterInput +} + +type AggregateResultGQL { + aggregationIdentifiers: [AggregationIdentifierGQL!]! + targetMetrics: TargetMetricsGQL! +} + +type AggregationIdentifierGQL { + featureName: String! + groupName: String! +} + +input AggregationInput @oneOf { + bucketSet: BucketSetInputGQL + enum: EnumAggregation + datetimeRange: DatetimeRangeAggregationInput +} + +enum AlignedIntervalEnum { + MONTH + YEAR + WEEK + DAY +} + +type AppleIapSubscriptionOptionsGQL { + enabled: Boolean! + proMonthlyProductId: String + productIds: [String!]! +} + +type BallTrajectoryGQL { + ballId: Int! + points: [TrajectoryPointGQL!]! +} + +type BankFeaturesGQL { + wallsHit: [WallTypeEnum!]! + bankAngle: Float! + distance: Float! +} + +type BannerGQL { + id: Int! + message: String! + color: String! + kind: BannerKindEnum! + dismissible: Boolean! + priority: Int! +} + +enum BannerKindEnum { + INFO + WARNING + ERROR +} + +""" +Integer value that can exceed GraphQL Int's 32-bit range. +""" +scalar BigInt + +type BoundingBoxGQL { + left: Float! + top: Float! + width: Float! + height: Float! +} + +input BoundingBoxInputGQL { + left: Float! + top: Float! + width: Float! + height: Float! +} + +type BucketGQL { + rangeKey: String! + lowerBound: Float! +} + +input BucketInputGQL { + rangeKey: String! + lowerBound: Float! +} + +type BucketSetGQL { + keyName: String! + feature: String! + buckets: [BucketGQL!]! +} + +input BucketSetInputGQL { + feature: String! + buckets: [BucketInputGQL!]! +} + +type CameraClaimSession { + id: ID! + cameraId: ID! + userId: ID! + challengeCode: String! + status: String! + expiresAt: DateTime! + detectedAt: DateTime + failedAt: DateTime + failureReason: String + agreedTermsVersion: Int + createdAt: DateTime! + updatedAt: DateTime! + camera: PoolHallCamera! +} + +type CameraLease { + id: ID! + cameraId: ID! + claimSessionId: ID + userId: ID! + videoId: ID + status: String! + startedAt: DateTime! + endedAt: DateTime + expiresAt: DateTime + endReason: String + createdAt: DateTime! + updatedAt: DateTime! + camera: PoolHallCamera! +} + +input CancellationFeedbackMetadataInput { + appVersion: String = null + gitRevision: String = null + platform: String = null +} + +enum CancellationReasonEnum { + DONT_PLAY_ENOUGH + TOO_EXPENSIVE + MISSING_FEATURES + TECHNICAL_ISSUES + DATA_NOT_ACCURATE + OTHER +} + +type Challenge { + id: ID! + name: String! + description: String + minimumShots: Int! + requiredTableSize: Float + requiredPocketSize: Float + isPublic: Boolean! + maxAttempts: Int + startDate: DateTime! + endDate: DateTime! + createdAt: DateTime! + updatedAt: DateTime! + ruleSet: RuleSet! + createdBy: UserGQL! + invitations: [ChallengeInvitation!]! + participantCount: Int! +} + +type ChallengeEntry { + id: ID! + status: String! + shotsCount: Int + makesCount: Int + makeRate: Float + qualified: Boolean + createdAt: DateTime! + attemptCount: Int + challenge: Challenge! + video: VideoGQL + user: UserGQL! +} + +type ChallengeInvitation { + id: ID! + status: String! + createdAt: DateTime! + challenge: Challenge! + inviter: UserGQL! + invitee: UserGQL! +} + +enum ClientUploadStatusEnum { + UPLOAD_ENABLED + UPLOAD_DISABLED +} + +input ClusterAssignmentInput { + clusterId: Int! + userId: Int = null + score: Int = null +} + +type CohortStatsGQL { + weekStart: Date! + signups: Int! + activated7d: Int! + paid7d: Int! + activatedNotPaid7d: Int! +} + +type CommentGQL { + id: Int! + user: UserGQL! + message: String! + replies: [CommentGQL!]! +} + +type CountLeaderboardGQL { + entries: [UserShotCountEntry!]! +} + +input CreateBucketSetInput { + keyName: String! + feature: String! + buckets: [BucketInputGQL!]! +} + +type CreateCustomerPortalSessionResultGQL { + portalUrl: String! +} + +input CreatePoolHallCameraInput { + poolHallId: ID! + name: String! + tableLabel: String = null + streamPath: String = null + tableSize: Float = null + pocketSize: Float = null + allowsPrivateVideos: Boolean = null + claimTermsText: String = null +} + +input CreatePoolHallInput { + name: String! + address: String = null + city: String = null + state: String = null + latitude: Float = null + longitude: Float = null + timezone: String = null +} + +type CreateSubscriptionResultGQL { + checkoutUrl: String! + sessionId: String! +} + +type CreateUploadStreamReturn { + videoId: Int! +} + +input CreatedAfter @oneOf { + videoId: Int + createdAt: DateTime +} + +type CueObjectFeaturesGQL { + cueObjectDistance: Float + cueObjectAngle: Float + cueBallSpeed: Float + shotDirection: ShotDirectionEnum + spinType: SpinTypeEnum +} + +input CueStrikeInputGQL { + v0: Float! + phi: Float! + theta: Float! = 0 + a: Float! = 0 + b: Float! = 0 +} + +""" +Date (isoformat) +""" +scalar Date + +input DateRangeFilter { + lessThan: Date = null + greaterThanEqualTo: Date = null + greaterThan: Date = null + includeOnNone: Boolean! = false + lessThanInclusive: Boolean! = false + greaterThanInclusive: Boolean! = true +} + +""" +Date with time (isoformat) +""" +scalar DateTime + +input DatetimeOrdering { + descending: Boolean! = true + startingAt: DateTime = null +} + +input DatetimeRangeAggregationInput { + startDatetime: DateTime = null + endDatetime: DateTime = null + interval: TimeInterval! + feature: String! = "created_at" +} + +type DeployedConfigGQL { + allowNewUsers: Boolean! + firebase: Boolean! + devMode: Boolean! + environment: String! + minimumAllowedAppVersion: String! + subscriptionGatingEnabled: Boolean! + quotaEnforcementEnabled: Boolean! + storageLimitEnforcementEnabled: Boolean! + capabilityEnforcementEnabled: Boolean! + bannerMessages: [BannerGQL!]! + defaultAndroidRecordingFormat: StreamSegmentTypeEnum! + bucketUrl: String! +} + +type DoesNotOwnShotErr { + shotId: Int! + msg: String +} + +union DoesNotOwnShotErrOtherErrorNeedsNote = + DoesNotOwnShotErr + | OtherErrorNeedsNote + +type DrillRunLeaderboardGQL { + entries: [RunGQL!]! + youRun: RunGQL + youRank: Int + totalPlayers: Int! +} + +type EditShotReturn { + shot: ShotGQL + error: DoesNotOwnShotErr +} + +input EditUserInputGQL { + username: String = null + fargoRating: Int = null + videosPrivateByDefault: Boolean = null + agreesToMarketing: Boolean = null + bio: String = null +} + +input EditableShotFieldInputGQL { + intendedPocketType: PocketEnum + shotDirection: ShotDirectionEnum + spinType: SpinTypeEnum + targetPocketAngleDirection: ShotDirectionEnum + make: Boolean + backcut: Boolean + excludeFromStats: Boolean + notes: String +} + +enum EntitlementSourceTypeEnum { + ADMIN + MANUAL + STRIPE + APPLE + ALPHA_LEGACY +} + +input EnumAggregation { + feature: String! +} + +input FilterInput @oneOf { + andFilters: [FilterInput!] + orFilters: [FilterInput!] + notFilter: FilterInput + cueObjectDistance: FloatRangeFilter + targetPocketDistance: FloatRangeFilter + cueObjectAngle: FloatRangeFilter + cueBallSpeed: FloatRangeFilter + difficulty: FloatRangeFilter + intendedPocketType: [PocketEnum!] + shotDirection: [ShotDirectionEnum!] + videoId: [Int!] + userId: [Int!] + runId: [Int!] + username: [String!] + fargoRating: FloatRangeFilter + make: [Boolean!] + tags: [VideoTagInput!] + annotations: [ShotAnnotationInput!] + isStraight: [Boolean!] + isRight: [Boolean!] + isLeft: [Boolean!] + isLeftMiss: [Boolean!] + isRightMiss: [Boolean!] + isDirect: [Boolean!] + isBreakHeuristic: [Boolean!] + tableSize: FloatRangeFilter + bankAngle: FloatRangeFilter + bankDistance: FloatRangeFilter + kickAngle: FloatRangeFilter + kickDistance: FloatRangeFilter + cueAngleAfterObject: FloatRangeFilter + spinType: [SpinTypeEnum!] + cueSpeedAfterObject: FloatRangeFilter + falsePositiveScore: FloatRangeFilter + backcut: [Boolean!] + targetPocketAngleDirection: [ShotDirectionEnum!] + targetPocketAngle: FloatRangeFilter + missAngleInDegrees: FloatRangeFilter + marginOfErrorInDegrees: FloatRangeFilter + createdAt: DateRangeFilter + totalDistance: FloatRangeFilter + runLength: FloatRangeFilter +} + +input FinalizePlayerAssignmentsInput { + videoId: Int! + clusterAssignments: [ClusterAssignmentInput!]! = [] + shotMoves: [ShotMoveInput!]! = [] +} + +input FloatOrdering { + descending: Boolean! = true + startingAt: Float = null +} + +input FloatRangeFilter { + lessThan: Float = null + greaterThanEqualTo: Float = null + greaterThan: Float = null + includeOnNone: Boolean! = false + lessThanInclusive: Boolean! = false + greaterThanInclusive: Boolean! = true +} + +type FunnelStatsGQL { + freemiumEpoch: Date! + eraSignups: Int! + eraPaying: Int! + activationCohort: Int! + activationActivated: Int! + payingUsers: Int! + newPaid7d: Int! + newPaid30d: Int! + retentionPrevActive: Int! + retentionReturned: Int! +} + +type GameTypeTagMetric { + tagName: String! + tagLabel: String! + tableSize: Float + shotCount: Int! + madeShots: Int! + makeRate: Float! +} + +input GameTypeTagMetricsInput { + userId: Int! + createdAt: DateRangeFilter = null + maxTags: Int = null + groupByTableSize: Boolean! = true + includeUnknown: Boolean! = true + tagClass: String = "game_type" + includePrivate: IncludePrivateEnum! = MINE +} + +type GetProfileUploadLinkErrors { + error: TooManyProfileImageUploadsErr! +} + +type GetProfileUploadLinkReturn { + value: UploadLinkGetProfileUploadLinkErrors! +} + +input GetRunsOrdering { + orderings: [RunsOrderingComponent!]! +} + +type GetRunsResult { + runs: [RunGQL!]! + count: Int + runIds: [Int!]! +} + +input GetShotsOrdering { + orderings: [ShotsOrderingComponent!]! +} + +input GetShotsPagination { + createdAfter: CreatedAfter! + startFrameAfter: Int! +} + +type GetShotsResult { + shots: [ShotGQL!]! + count: Int + ids: [Int!]! +} + +type GetUploadLinkErrors { + error: MustHaveSetForUploadLinkErrSegmentAlreadyUploadedErrProcessingFailedErrNoInitForChunkedUploadErrTooManyProfileImageUploadsErrInitUploadAlreadyCompletedErrTooManyInitUploadsErrStorageLimitExceededErr! +} + +type GetUploadLinkReturn { + value: UploadLinkGetUploadLinkErrors! + stream: UploadStreamGQL +} + +type HLSPlaylistGQL { + videoId: Int! + m3u8Text: String! + segmentDurations: [Float!]! +} + +type Header { + key: String! + value: String! +} + +enum HomographyBackendGQL { + CLASSIC + TABLENET +} + +type HomographyInfoGQL { + id: Int + frameIndex: Int! + crop: BoundingBoxGQL! + pockets: [BoundingBoxGQL!]! + sourcePoints: PocketPointsGQL! + destPoints: PocketPointsGQL! +} + +input HomographyInputGQL { + crop: BoundingBoxInputGQL! + pockets: [BoundingBoxInputGQL!]! + sourcePoints: PocketPointsInputGQL! + destPoints: PocketPointsInputGQL! +} + +enum IncludePrivateEnum { + ALL + MINE + NONE +} + +enum InitPlaylistUploadStatusEnum { + NOT_APPLICABLE + NOT_UPLOADED + UPLOADED +} + +type InitUploadAlreadyCompletedErr { + segmentType: StreamSegmentTypeEnum! +} + +input IntOrdering { + descending: Boolean! = true + startingAt: Int = null +} + +type IntPoint2D { + x: Int! + y: Int! +} + +input IntPoint2DInput { + x: Int! + y: Int! +} + +""" +The `JSON` scalar type represents JSON values as specified by [ECMA-404](https://ecma-international.org/wp-content/uploads/ECMA-404_2nd_edition_december_2017.pdf). +""" +scalar JSON + @specifiedBy( + url: "https://ecma-international.org/wp-content/uploads/ECMA-404_2nd_edition_december_2017.pdf" + ) + +type LiveTableStateGQL { + videoId: Int! + frameIndex: Int! + tableState: TableStateGQL! +} + +type MakePercentageIntervalGQL { + makePercentage: Float! + elapsedTime: Float! +} + +type MedalGQL { + count: Int! + nickname: String +} + +input MedalScope @oneOf { + videoId: Int + interval: TimeInterval + @deprecated(reason: "NO LONGER SUPPORTED, USE DATETIME_RANGE") + datetimeRange: DatetimeRangeAggregationInput +} + +type MustHaveSetForUploadLinkErr { + resolution: Boolean + framesPerSecond: Boolean +} + +union MustHaveSetForUploadLinkErrSegmentAlreadyUploadedErrProcessingFailedErrNoInitForChunkedUploadErrTooManyProfileImageUploadsErrInitUploadAlreadyCompletedErrTooManyInitUploadsErrStorageLimitExceededErr = + MustHaveSetForUploadLinkErr + | SegmentAlreadyUploadedErr + | ProcessingFailedErr + | NoInitForChunkedUploadErr + | TooManyProfileImageUploadsErr + | InitUploadAlreadyCompletedErr + | TooManyInitUploadsErr + | StorageLimitExceededErr + +type Mutation { + createBucketSet(params: CreateBucketSetInput!): BucketSetGQL! + createRuleSet(name: String!, description: String = null): RuleSet! + createChallenge( + name: String! + ruleSetId: ID! + minimumShots: Int! + startDate: DateTime! + endDate: DateTime! + description: String = null + requiredTableSize: Float = null + requiredPocketSize: Float = null + isPublic: Boolean! = false + maxAttempts: Int = null + ): Challenge! + inviteUsersToChallenge( + challengeId: ID! + userIds: [ID!]! + ): [ChallengeInvitation!]! + respondToChallengeInvitation( + invitationId: ID! + accept: Boolean! + ): ChallengeInvitation! + startChallenge(challengeId: ID!): ChallengeEntry! + recalculateChallengeEntry(entryId: ID!): ChallengeEntry! + submitChallengeEntry(entryId: ID!, videoId: ID!): ChallengeEntry! + dismissChallenge(challengeId: ID!): Boolean! + undismissChallenge(challengeId: ID!): Boolean! + setLoggerLevel(path: String!, level: String!): Boolean! + reactToVideo(videoId: Int!, reaction: ReactionEnum): Boolean! + commentOnVideo( + videoId: Int! + message: String! + parentCommentId: Int + ): Boolean! + editComment(videoId: Int!, commentId: Int!, newMessage: String!): Boolean! + deleteComment(videoId: Int!, commentId: Int!): Boolean! + blockContent(videoId: Int!): Boolean! + blockUser(userId: Int!): Boolean! + reportContent( + videoId: Int! + reason: ReportReasonEnum! + customReason: String = null + ): Boolean! + markNotificationAsRead(notificationId: Int!): Boolean! + markAllNotificationsAsRead: Boolean! + markNotificationsAsRead(notificationIds: [Int!]!): Boolean! + deleteNotification(notificationId: Int!): Boolean! + createPoolHall(input: CreatePoolHallInput!): PoolHall! + updatePoolHall(input: UpdatePoolHallInput!): PoolHall! + createPoolHallCamera( + input: CreatePoolHallCameraInput! + ): PoolHallCameraStreamCredentials! + updatePoolHallCamera(input: UpdatePoolHallCameraInput!): PoolHallCamera! + rotatePoolHallCameraStreamKey(cameraId: ID!): PoolHallCameraStreamCredentials! + createCameraClaimSession( + cameraId: ID! + durationMinutes: Int = null + videoName: String = null + videoPrivate: Boolean = null + agreedTermsVersion: Int = null + tags: [VideoTagInput!] = null + ): CameraClaimSession! + cancelCameraClaimSession(claimSessionId: ID!): CameraClaimSession! + endCameraLease(leaseId: ID!): CameraLease! + extendCameraLease(leaseId: ID!, additionalMinutes: Int! = 60): CameraLease! + finalizePlayerAssignments( + input: FinalizePlayerAssignmentsInput! + ): [PlayerClusterGQL!]! + addAnnotationToShot( + shotId: Int! + annotationName: String! + notes: String = null + ): AddShotAnnotationReturn! + updateShotAnnotations( + shotId: Int! + annotations: [UpdateAnnotationInputGQL!]! + ): UpdateShotAnnotationReturn! + editShot( + shotId: Int! + fieldsToEdit: EditableShotFieldInputGQL! + ): EditShotReturn! + getProfileImageUploadLink( + fileExt: String = ".png" + ): GetProfileUploadLinkReturn! + editProfileImageUri(profileImageUri: String!): UserGQL! + editUser(input: EditUserInputGQL!): UserGQL! + followUser(followedUserId: Int!): UserGQL! + unfollowUser(followedUserId: Int!): UserGQL! + retireTags(tagIds: [Int!]!): Boolean! + ensureStripeCustomerExists: UserGQL! + deleteUser: Boolean! + syncAppleSubscription( + input: SyncAppleSubscriptionInputGQL! + ): SyncAppleSubscriptionResultGQL! + createSubscription(priceId: String!): CreateSubscriptionResultGQL! + createCustomerPortalSession: CreateCustomerPortalSessionResultGQL! + cancelSubscription: UserSubscriptionStatusGQL! + grantManualEntitlement( + userId: Int! + tierName: String! = "pro" + startsAt: DateTime = null + endsAt: DateTime = null + reason: String = null + ): UserSubscriptionStatusGQL! + revokeManualEntitlement(userId: Int!): UserSubscriptionStatusGQL! + submitCancellationFeedback( + reasons: [CancellationReasonEnum!] = null + feedback: String = null + metadata: CancellationFeedbackMetadataInput = null + ): Boolean! + requestVideoExport(input: RequestVideoExportInput!): VideoExportJobGQL! + dismissVideoExport(jobId: Int!): Boolean! + findPrerecordTableLayout(b64Image: String!, videoId: Int!): HomographyInfoGQL + createUploadStream( + videoMetadata: VideoMetadataInput! + expectedDurationSeconds: Float = null + ): CreateUploadStreamReturn! + getUploadLink(videoId: Int!, segmentIndex: Int!): GetUploadLinkReturn! + getHlsInitUploadLink(videoId: Int!): GetUploadLinkReturn! + setSegmentDuration( + videoId: Int! + segmentIndex: Int! + duration: Float! + ): Boolean! + editUploadStream(videoId: Int!, videoMetadata: VideoMetadataInput!): Boolean! + deleteVideo(videoId: Int!): Boolean! + deleteTags(videoId: Int!, tagsToDelete: [VideoTagInput!]!): Boolean! +} + +type NoInitForChunkedUploadErr { + segmentType: StreamSegmentTypeEnum! +} + +type NotificationConnection { + notifications: [NotificationGQL!]! + totalCount: Int! + unreadCount: Int! + hasMore: Boolean! +} + +input NotificationFilters { + isRead: Boolean = null + notificationTypes: [NotificationTypeEnum!] = null +} + +type NotificationGQL { + id: Int! + notificationType: NotificationTypeEnum! + actor: UserGQL! + videoId: Int + challengeId: Int + challenge: Challenge + comment: CommentGQL + reactionType: String + isRead: Boolean! + createdAt: DateTime! + readAt: DateTime +} + +enum NotificationTypeEnum { + COMMENT + COMMENT_REPLY + REACTION + FOLLOW + CHALLENGE_INVITE + EXPORT_READY +} + +type OtherErrorNeedsNote { + msg: String +} + +type PageInfoGQL { + hasNextPage: Boolean! + endCursor: String +} + +type PlayerClusterGQL { + videoId: Int! + clusterId: Int! + nShots: Int! + userId: Int + username: String + profileImageUri: String + confirmed: Boolean! + score: Int + shots: [PlayerClusterShotGQL!]! +} + +type PlayerClusterShotGQL { + shotId: Int! + bboxX1: Int! + bboxY1: Int! + bboxX2: Int! + bboxY2: Int! + confidence: Float! + isConfirmed: Boolean! + cropUrl: String + fullFrameUrl: String +} + +type PlayerSummaryGQL { + clusterId: Int! + userId: Int + username: String + profileImageUri: String + representativeFullFrameUrl: String + totalShots: Int! + totalShotsMade: Int! + makePercentage: Float! + score: Int + longestRun: Int! + runLengths: [Int!]! + spinTypeBreakdown: SpinTypeBreakdownGQL! + averageDifficulty: Float + averageTimeBetweenShots: Float +} + +enum PocketEnum { + CORNER + SIDE +} + +enum PocketIdentifier { + TOP_LEFT + TOP_SIDE + TOP_RIGHT + BOTTOM_LEFT + BOTTOM_SIDE + BOTTOM_RIGHT +} + +type PocketPointsGQL { + topLeft: IntPoint2D! + topSide: IntPoint2D! + topRight: IntPoint2D! + bottomLeft: IntPoint2D! + bottomSide: IntPoint2D! + bottomRight: IntPoint2D! +} + +input PocketPointsInputGQL { + topLeft: IntPoint2DInput! + topSide: IntPoint2DInput! + topRight: IntPoint2DInput! + bottomLeft: IntPoint2DInput! + bottomSide: IntPoint2DInput! + bottomRight: IntPoint2DInput! +} + +type PocketingIntentionFeaturesGQL { + targetPocketDistance: Float + make: Boolean + intendedPocketType: PocketEnum + difficulty: Float + targetPocketAngle: Float + targetPocketAngleDirection: ShotDirectionEnum + marginOfErrorInDegrees: Float + backcut: Boolean +} + +type PocketingIntentionInfoGQL { + ballId: Int! + pocketId: PocketIdentifier! + pathMetadataIndex: Int! +} + +type PoolHall { + id: ID! + name: String! + address: String + city: String + state: String + latitude: Float + longitude: Float + timezone: String + status: String! + createdAt: DateTime! + updatedAt: DateTime! +} + +type PoolHallCamera { + id: ID! + poolHallId: ID! + name: String! + tableLabel: String + streamPath: String! + status: String! + tableSize: Float + pocketSize: Float + allowsPrivateVideos: Boolean! + claimTermsText: String + claimTermsVersion: Int + lastPublishedAt: DateTime + lastUnpublishedAt: DateTime + createdAt: DateTime! + updatedAt: DateTime! + inUse: Boolean! + poolHall: PoolHall! +} + +type PoolHallCameraStreamCredentials { + camera: PoolHallCamera! + streamKey: String! + rtmpPath: String! +} + +type PotAimGQL { + phi: Float! + geometricPhi: Float! + cutAngle: Float! + requiredPrecision: Float! + feasible: Boolean! + potted: Boolean! + converged: Boolean! + occludingBallIds: [Int!]! +} + +type ProcessingFailedErr { + processing: VideoProcessingGQL! +} + +type ProcessingStatusCountGQL { + status: String! + count: Int! +} + +enum ProcessingStatusEnum { + STARTED + FAILED + SUCCEEDED + SUSPENDED + CREATED + QUEUED + RUNNING + REEXTRACTING_FEATURES +} + type Query { getAggregatedShotMetrics( aggregateInput: AggregateInputGQL! @@ -143,538 +1118,42 @@ type Query { getVideos(videoIds: [Int!]!): [VideoGQL!]! } -type AggregateResultGQL { - aggregationIdentifiers: [AggregationIdentifierGQL!]! - targetMetrics: TargetMetricsGQL! +type QuotaBucketStatusGQL { + quotaKey: String! + appliesToUploadKind: String! + periodStart: DateTime! + periodEnd: DateTime! + durationUsedSeconds: Float! + durationLimitSeconds: Int + durationRemainingSeconds: Float + canUpload: Boolean! } -type AggregationIdentifierGQL { - featureName: String! - groupName: String! +type QuotaStatusGQL { + tierName: String! + periodStart: DateTime! + periodEnd: DateTime! + durationUsedSeconds: Float! + durationLimitSeconds: Int + maxVideoDurationSeconds: Int + importQuotaBuckets: [QuotaBucketStatusGQL!]! + recordingQuotaBuckets: [QuotaBucketStatusGQL!]! + durationRemainingSeconds: Float + canUpload: Boolean! } -type TargetMetricsGQL { - count: Int! - makePercentage: Float - averageDifficulty: Float - spinTypeCounts: SpinTypeCountsGQL - shotDirectionCounts: ShotDirectionCountsGQL +type RGBColorGQL { + r: Int! + g: Int! + b: Int! + hex: String! } -type SpinTypeCountsGQL { - follow: Int! - draw: Int! - center: Int! - unknown: Int! -} - -type ShotDirectionCountsGQL { - left: Int! - right: Int! - straight: Int! -} - -input AggregateInputGQL { - aggregations: [AggregationInput!]! - filterInput: FilterInput -} - -input AggregationInput @oneOf { - bucketSet: BucketSetInputGQL - enum: EnumAggregation - datetimeRange: DatetimeRangeAggregationInput -} - -input BucketSetInputGQL { - feature: String! - buckets: [BucketInputGQL!]! -} - -input BucketInputGQL { - rangeKey: String! - lowerBound: Float! -} - -input EnumAggregation { - feature: String! -} - -input DatetimeRangeAggregationInput { - startDatetime: DateTime = null - endDatetime: DateTime = null - interval: TimeInterval! - feature: String! = "created_at" -} - -""" -Date with time (isoformat) -""" -scalar DateTime - -input TimeInterval @oneOf { - timedelta: TimeDeltaGQL - aligned: AlignedIntervalEnum -} - -input TimeDeltaGQL { - days: Int = 0 - weeks: Int = 0 - months: Int = 0 - years: Int = 0 -} - -enum AlignedIntervalEnum { - MONTH - YEAR - WEEK - DAY -} - -input FilterInput @oneOf { - andFilters: [FilterInput!] - orFilters: [FilterInput!] - notFilter: FilterInput - cueObjectDistance: FloatRangeFilter - targetPocketDistance: FloatRangeFilter - cueObjectAngle: FloatRangeFilter - cueBallSpeed: FloatRangeFilter - difficulty: FloatRangeFilter - intendedPocketType: [PocketEnum!] - shotDirection: [ShotDirectionEnum!] - videoId: [Int!] - userId: [Int!] - runId: [Int!] - username: [String!] - fargoRating: FloatRangeFilter - make: [Boolean!] - tags: [VideoTagInput!] - annotations: [ShotAnnotationInput!] - isStraight: [Boolean!] - isRight: [Boolean!] - isLeft: [Boolean!] - isLeftMiss: [Boolean!] - isRightMiss: [Boolean!] - isDirect: [Boolean!] - isBreakHeuristic: [Boolean!] - tableSize: FloatRangeFilter - bankAngle: FloatRangeFilter - bankDistance: FloatRangeFilter - kickAngle: FloatRangeFilter - kickDistance: FloatRangeFilter - cueAngleAfterObject: FloatRangeFilter - spinType: [SpinTypeEnum!] - cueSpeedAfterObject: FloatRangeFilter - falsePositiveScore: FloatRangeFilter - backcut: [Boolean!] - targetPocketAngleDirection: [ShotDirectionEnum!] - targetPocketAngle: FloatRangeFilter - missAngleInDegrees: FloatRangeFilter - marginOfErrorInDegrees: FloatRangeFilter - createdAt: DateRangeFilter - totalDistance: FloatRangeFilter - runLength: FloatRangeFilter -} - -input FloatRangeFilter { - lessThan: Float = null - greaterThanEqualTo: Float = null - greaterThan: Float = null - includeOnNone: Boolean! = false - lessThanInclusive: Boolean! = false - greaterThanInclusive: Boolean! = true -} - -enum PocketEnum { - CORNER - SIDE -} - -enum ShotDirectionEnum { - LEFT - RIGHT - STRAIGHT -} - -input VideoTagInput { - tagClasses: [VideoTagClassInput!]! = [] - name: String! -} - -input VideoTagClassInput { - name: String! -} - -input ShotAnnotationInput { - name: String! -} - -enum SpinTypeEnum { - DRAW - FOLLOW - CENTER - UNKNOWN -} - -input DateRangeFilter { - lessThan: Date = null - greaterThanEqualTo: Date = null - greaterThan: Date = null - includeOnNone: Boolean! = false - lessThanInclusive: Boolean! = false - greaterThanInclusive: Boolean! = true -} - -""" -Date (isoformat) -""" -scalar Date - -type BucketSetGQL { - keyName: String! - feature: String! - buckets: [BucketGQL!]! -} - -type BucketGQL { - rangeKey: String! - lowerBound: Float! -} - -type Challenge { - id: ID! - name: String! - description: String - minimumShots: Int! - requiredTableSize: Float - requiredPocketSize: Float - isPublic: Boolean! - maxAttempts: Int - startDate: DateTime! - endDate: DateTime! - createdAt: DateTime! - updatedAt: DateTime! - ruleSet: RuleSet! - createdBy: UserGQL! - invitations: [ChallengeInvitation!]! - participantCount: Int! -} - -type RuleSet { - id: ID! - name: String! - description: String - createdAt: DateTime! - updatedAt: DateTime! -} - -type UserGQL { - id: Int! - firebaseUid: String - username: String! - isAdmin: Boolean - fargoRating: Int - activeVideoId: Int - stripeCustomerId: String - profileImageUri: String - bio: String - createdAt: DateTime - updatedAt: DateTime - videosPrivateByDefault: Boolean - agreesToMarketing: Boolean - following: [UserGQL!] - followers: [UserGQL!] - isFollowedByCurrentUser: Boolean -} - -type ChallengeInvitation { - id: ID! - status: String! - createdAt: DateTime! - challenge: Challenge! - inviter: UserGQL! - invitee: UserGQL! -} - -type ChallengeEntry { - id: ID! - status: String! - shotsCount: Int - makesCount: Int - makeRate: Float - qualified: Boolean - createdAt: DateTime! - attemptCount: Int - challenge: Challenge! - video: VideoGQL - user: UserGQL! -} - -type VideoGQL { - id: Int! - owner: UserGQL - name: String - screenshotUri: String - totalShotsMade: Int! - totalShots: Int! - makePercentage: Float! - medianRun: Float - averageTimeBetweenShots: Float - averageDifficulty: Float - createdAt: DateTime - updatedAt: DateTime - shots: [ShotGQL!]! - startTime: DateTime - endTime: DateTime - elapsedTime: Float - framesPerSecond: Float! - tableSize: Float! - pocketSize: Float - private: Boolean! - stream: UploadStreamGQL - playlist: HLSPlaylistGQL - tags: [VideoTag!]! - currentHomography: HomographyInfoGQL - homographyHistory: [HomographyInfoGQL!]! - currentProcessing: VideoProcessingGQL - reactions: [ReactionGQL!]! - comments: [CommentGQL!]! - playerSummaries: [PlayerSummaryGQL!]! -} - -type ShotGQL { - id: Int! - videoId: Int! - startFrame: Int! - endFrame: Int! - createdAt: DateTime - updatedAt: DateTime - cueObjectFeatures: CueObjectFeaturesGQL - pocketingIntentionFeatures: PocketingIntentionFeaturesGQL - pocketingIntentionInfo: PocketingIntentionInfoGQL - bankFeatures: BankFeaturesGQL - serializedShotPaths: SerializedShotPathsGQL - user: UserGQL - annotations: [ShotAnnotationGQL!]! - falsePositiveScore: Float - video: VideoGQL - run: RunGQL - runFeatures: RunFeaturesGQL -} - -type CueObjectFeaturesGQL { - cueObjectDistance: Float - cueObjectAngle: Float - cueBallSpeed: Float - shotDirection: ShotDirectionEnum - spinType: SpinTypeEnum -} - -type PocketingIntentionFeaturesGQL { - targetPocketDistance: Float - make: Boolean - intendedPocketType: PocketEnum - difficulty: Float - targetPocketAngle: Float - targetPocketAngleDirection: ShotDirectionEnum - marginOfErrorInDegrees: Float - backcut: Boolean -} - -type PocketingIntentionInfoGQL { - ballId: Int! - pocketId: PocketIdentifier! - pathMetadataIndex: Int! -} - -enum PocketIdentifier { - TOP_LEFT - TOP_SIDE - TOP_RIGHT - BOTTOM_LEFT - BOTTOM_SIDE - BOTTOM_RIGHT -} - -type BankFeaturesGQL { - wallsHit: [WallTypeEnum!]! - bankAngle: Float! - distance: Float! -} - -enum WallTypeEnum { - LONG - SHORT -} - -type SerializedShotPathsGQL { - b64EncodedBuffer: String -} - -type ShotAnnotationGQL { - shotId: Int! - type: ShotAnnotationTypeGQL! - creator: UserGQL! - notes: String! - errorDefault: Boolean! - createdAt: DateTime - updatedAt: DateTime -} - -type ShotAnnotationTypeGQL { - id: Int! - name: String! -} - -type RunGQL { - id: Int! - runLength: Int! - videoId: Int! - userId: Int! - shots: [ShotGQL!]! - video: VideoGQL! - user: UserGQL! -} - -type RunFeaturesGQL { - runId: Int! - indexInRun: Int! -} - -type UploadStreamGQL { - id: ID! - linksRequested: Int! - uploadsCompleted: Int! - segmentProcessingCursor: Int! - lastIntendedSegmentBound: Int - isCompleted: Boolean! - initPlaylistUploadStatus: InitPlaylistUploadStatusEnum - lowestUnuploadedSegmentIndex: Int! - uploadCompletionCursor: Int! - lastSegmentUploadedAt: DateTime - errors: [StreamErrorGQL!]! - createdAt: DateTime! - updatedAt: DateTime! - segments: [UploadSegmentGQL!]! - clientUploadStatus: ClientUploadStatusEnum - resolution: VideoResolutionGQL! - streamSegmentType: StreamSegmentTypeEnum! -} - -enum InitPlaylistUploadStatusEnum { - NOT_APPLICABLE - NOT_UPLOADED - UPLOADED -} - -type StreamErrorGQL { - message: String! -} - -type UploadSegmentGQL { - segmentIndex: Int! - uploaded: Boolean! - valid: Boolean! - endFrameIndex: Int - framesPerSecond: Float - durationInSeconds: Float - linksRequested: Int! -} - -enum ClientUploadStatusEnum { - UPLOAD_ENABLED - UPLOAD_DISABLED -} - -type VideoResolutionGQL { - width: Int - height: Int -} - -enum StreamSegmentTypeEnum { - FRAGMENTED_MP4 - RB_CHUNKED_MP4 -} - -type HLSPlaylistGQL { - videoId: Int! - m3u8Text: String! - segmentDurations: [Float!]! -} - -type VideoTag { - tagClasses: [VideoTagClass!]! - name: String! -} - -type VideoTagClass { - name: String! -} - -type HomographyInfoGQL { - id: Int - frameIndex: Int! - crop: BoundingBoxGQL! - pockets: [BoundingBoxGQL!]! - sourcePoints: PocketPointsGQL! - destPoints: PocketPointsGQL! -} - -type BoundingBoxGQL { - left: Float! - top: Float! - width: Float! - height: Float! -} - -type PocketPointsGQL { - topLeft: IntPoint2D! - topSide: IntPoint2D! - topRight: IntPoint2D! - bottomLeft: IntPoint2D! - bottomSide: IntPoint2D! - bottomRight: IntPoint2D! -} - -type IntPoint2D { - x: Int! - y: Int! -} - -type VideoProcessingGQL { - id: Int! - parentProcessingId: Int - labels: [String!]! - errors: [VideoProcessingErrorGQL!]! - status: ProcessingStatusEnum! - statuses: [VideoProcessingStatusGQL!]! - framesProcessed: Int - currentSegment: Int - progressPercentage: Float -} - -type VideoProcessingErrorGQL { - message: String! - startSegmentIndex: Int - endSegmentIndex: Int -} - -enum ProcessingStatusEnum { - STARTED - FAILED - SUCCEEDED - SUSPENDED - CREATED - QUEUED - RUNNING - REEXTRACTING_FEATURES -} - -type VideoProcessingStatusGQL { - status: ProcessingStatusEnum! - appVersion: String! - sequenceId: Int! - createdAt: DateTime - updatedAt: DateTime +enum ReactionEnum { + LIKE + HEART + BULLSEYE + HUNDRED } type ReactionGQL { @@ -685,131 +1164,20 @@ type ReactionGQL { updatedAt: DateTime } -enum ReactionEnum { - LIKE - HEART - BULLSEYE - HUNDRED +enum ReportReasonEnum { + SPAM + NUDITY + VIOLENCE + HATE + COPYRIGHT + OTHER } -type CommentGQL { - id: Int! - user: UserGQL! - message: String! - replies: [CommentGQL!]! -} - -type PlayerSummaryGQL { - clusterId: Int! - userId: Int - username: String - profileImageUri: String - representativeFullFrameUrl: String - totalShots: Int! - totalShotsMade: Int! - makePercentage: Float! - score: Int - longestRun: Int! - runLengths: [Int!]! - spinTypeBreakdown: SpinTypeBreakdownGQL! - averageDifficulty: Float - averageTimeBetweenShots: Float -} - -type SpinTypeBreakdownGQL { - draw: Int! - center: Int! - follow: Int! -} - -type DeployedConfigGQL { - allowNewUsers: Boolean! - firebase: Boolean! - devMode: Boolean! - environment: String! - minimumAllowedAppVersion: String! - subscriptionGatingEnabled: Boolean! - quotaEnforcementEnabled: Boolean! - storageLimitEnforcementEnabled: Boolean! - capabilityEnforcementEnabled: Boolean! - bannerMessages: [BannerGQL!]! - defaultAndroidRecordingFormat: StreamSegmentTypeEnum! - bucketUrl: String! -} - -type BannerGQL { - id: Int! - message: String! - color: String! - kind: BannerKindEnum! - dismissible: Boolean! - priority: Int! -} - -enum BannerKindEnum { - INFO - WARNING - ERROR -} - -type VideoHistoryGQL { - videos: [VideoGQL!]! - pageInfo: PageInfoGQL! - hasFollowing: Boolean! - followingCount: Int! -} - -type PageInfoGQL { - hasNextPage: Boolean! - endCursor: String -} - -enum IncludePrivateEnum { - ALL - MINE - NONE -} - -input VideoFilterInput { - isStreamCompleted: Boolean = null - requireCursorCompletion: Boolean! = true - createdAt: DateRangeFilter = null - excludeVideosWithNoShots: Boolean = null -} - -input VideoFeedInputGQL @oneOf { - followedByUserId: Int - userId: Int - allUsers: Boolean - home: Boolean -} - -type MakePercentageIntervalGQL { - makePercentage: Float! - elapsedTime: Float! -} - -type RunLeaderboardGQL { - entries: [RunGQL!]! -} - -type DrillRunLeaderboardGQL { - entries: [RunGQL!]! - youRun: RunGQL - youRank: Int - totalPlayers: Int! -} - -type CountLeaderboardGQL { - entries: [UserShotCountEntry!]! -} - -type UserShotCountEntry { - user: UserGQL! - value: Int! - total: Int! - proportionMade: Float! - videos: Int! +input RequestVideoExportInput { + videoId: Int! + mode: VideoExportModeEnum! + shotIds: [Int!] = null + runId: Int = null } type RequestedMedalsGQL { @@ -845,123 +1213,28 @@ type RequestedMedalsGQL { dailyMakes250: MedalGQL } -type MedalGQL { - count: Int! - nickname: String +type ResolvedTierGQL { + tierName: String! + tierDisplayName: String! + hasActiveSubscription: Boolean! + entitlementSource: EntitlementSourceTypeEnum + entitlementStatus: String + entitlementStartsAt: DateTime + entitlementEndsAt: DateTime + capabilities: [String!]! } -input MedalScope @oneOf { - videoId: Int - interval: TimeInterval - @deprecated(reason: "NO LONGER SUPPORTED, USE DATETIME_RANGE") - datetimeRange: DatetimeRangeAggregationInput -} - -type NotificationConnection { - notifications: [NotificationGQL!]! - totalCount: Int! - unreadCount: Int! - hasMore: Boolean! -} - -type NotificationGQL { - id: Int! - notificationType: NotificationTypeEnum! - actor: UserGQL! - videoId: Int - challengeId: Int - challenge: Challenge - comment: CommentGQL - reactionType: String - isRead: Boolean! - createdAt: DateTime! - readAt: DateTime -} - -enum NotificationTypeEnum { - COMMENT - COMMENT_REPLY - REACTION - FOLLOW - CHALLENGE_INVITE - EXPORT_READY -} - -input NotificationFilters { - isRead: Boolean = null - notificationTypes: [NotificationTypeEnum!] = null -} - -type PoolHall { +type RuleSet { id: ID! name: String! - address: String - city: String - state: String - latitude: Float - longitude: Float - timezone: String - status: String! + description: String createdAt: DateTime! updatedAt: DateTime! } -type PoolHallCamera { - id: ID! - poolHallId: ID! - name: String! - tableLabel: String - streamPath: String! - status: String! - tableSize: Float - pocketSize: Float - allowsPrivateVideos: Boolean! - claimTermsText: String - claimTermsVersion: Int - lastPublishedAt: DateTime - lastUnpublishedAt: DateTime - createdAt: DateTime! - updatedAt: DateTime! - inUse: Boolean! - poolHall: PoolHall! -} - -type CameraClaimSession { - id: ID! - cameraId: ID! - userId: ID! - challengeCode: String! - status: String! - expiresAt: DateTime! - detectedAt: DateTime - failedAt: DateTime - failureReason: String - agreedTermsVersion: Int - createdAt: DateTime! - updatedAt: DateTime! - camera: PoolHallCamera! -} - -type CameraLease { - id: ID! - cameraId: ID! - claimSessionId: ID - userId: ID! - videoId: ID - status: String! - startedAt: DateTime! - endedAt: DateTime - expiresAt: DateTime - endReason: String - createdAt: DateTime! - updatedAt: DateTime! - camera: PoolHallCamera! -} - -type GetRunsResult { - runs: [RunGQL!]! - count: Int - runIds: [Int!]! +type RunFeaturesGQL { + runId: Int! + indexInRun: Int! } input RunFilterInput { @@ -976,8 +1249,18 @@ input RunFilterInput { runLength: FloatRangeFilter } -input GetRunsOrdering { - orderings: [RunsOrderingComponent!]! +type RunGQL { + id: Int! + runLength: Int! + videoId: Int! + userId: Int! + shots: [ShotGQL!]! + video: VideoGQL! + user: UserGQL! +} + +type RunLeaderboardGQL { + entries: [RunGQL!]! } input RunsOrderingComponent @oneOf { @@ -986,45 +1269,21 @@ input RunsOrderingComponent @oneOf { videoCreation: DatetimeOrdering } -input IntOrdering { - descending: Boolean! = true - startingAt: Int = null +type SegmentAlreadyUploadedErr { + segmentId: Int! } -input DatetimeOrdering { - descending: Boolean! = true - startingAt: DateTime = null +type SerializedShotPathsGQL { + b64EncodedBuffer: String } -type SessionCoachGQL { - videoId: Int! - processingId: Int - analysisVersion: String! - state: SessionCoachStateEnum! - generatedAt: DateTime! - processingStatus: String - ineligibilityReason: SessionCoachIneligibilityReasonEnum - summary: String - shotCount: Int! - madeCount: Int! - missedCount: Int! - unknownOutcomeCount: Int! - analyzedShotCount: Int! - makePercentage: Float - primaryCandidate: SessionCoachCandidateGQL - candidates: [SessionCoachCandidateGQL!]! -} - -enum SessionCoachStateEnum { - PROCESSING - READY - NO_TRACKED_SHOTS - INELIGIBLE - FAILED -} - -enum SessionCoachIneligibilityReasonEnum { - MULTIPLAYER +enum SessionCoachCandidateFamilyEnum { + AIMING + CUT_ANGLE + SPIN + OBJECT_TO_POCKET_DISTANCE + CUE_TO_OBJECT_DISTANCE + BACK_CUT } type SessionCoachCandidateGQL { @@ -1041,15 +1300,6 @@ type SessionCoachCandidateGQL { limitations: [String!]! } -enum SessionCoachCandidateFamilyEnum { - AIMING - CUT_ANGLE - SPIN - OBJECT_TO_POCKET_DISTANCE - CUE_TO_OBJECT_DISTANCE - BACK_CUT -} - enum SessionCoachCandidateKindEnum { DIRECTIONAL_MISS OUTCOME_PATTERN @@ -1071,82 +1321,91 @@ type SessionCoachEvidenceGQL { rankReason: String! } -type PlayerClusterGQL { +type SessionCoachGQL { videoId: Int! - clusterId: Int! - nShots: Int! - userId: Int - username: String - profileImageUri: String - confirmed: Boolean! - score: Int - shots: [PlayerClusterShotGQL!]! + processingId: Int + analysisVersion: String! + state: SessionCoachStateEnum! + generatedAt: DateTime! + processingStatus: String + ineligibilityReason: SessionCoachIneligibilityReasonEnum + summary: String + shotCount: Int! + madeCount: Int! + missedCount: Int! + unknownOutcomeCount: Int! + analyzedShotCount: Int! + makePercentage: Float + primaryCandidate: SessionCoachCandidateGQL + candidates: [SessionCoachCandidateGQL!]! } -type PlayerClusterShotGQL { +enum SessionCoachIneligibilityReasonEnum { + MULTIPLAYER +} + +enum SessionCoachStateEnum { + PROCESSING + READY + NO_TRACKED_SHOTS + INELIGIBLE + FAILED +} + +type ShotAnnotationGQL { shotId: Int! - bboxX1: Int! - bboxY1: Int! - bboxX2: Int! - bboxY2: Int! - confidence: Float! - isConfirmed: Boolean! - cropUrl: String - fullFrameUrl: String + type: ShotAnnotationTypeGQL! + creator: UserGQL! + notes: String! + errorDefault: Boolean! + createdAt: DateTime + updatedAt: DateTime } -type TableStateGQL { - identifierToPosition: [[Float!]!]! - homography: HomographyInfoGQL - identifierToColor: [RGBColorGQL]! +input ShotAnnotationInput { + name: String! } -type RGBColorGQL { - r: Int! - g: Int! - b: Int! - hex: String! +type ShotAnnotationTypeGQL { + id: Int! + name: String! } -input HomographyInputGQL { - crop: BoundingBoxInputGQL! - pockets: [BoundingBoxInputGQL!]! - sourcePoints: PocketPointsInputGQL! - destPoints: PocketPointsInputGQL! +type ShotDirectionCountsGQL { + left: Int! + right: Int! + straight: Int! } -input BoundingBoxInputGQL { - left: Float! - top: Float! - width: Float! - height: Float! +enum ShotDirectionEnum { + LEFT + RIGHT + STRAIGHT } -input PocketPointsInputGQL { - topLeft: IntPoint2DInput! - topSide: IntPoint2DInput! - topRight: IntPoint2DInput! - bottomLeft: IntPoint2DInput! - bottomSide: IntPoint2DInput! - bottomRight: IntPoint2DInput! -} - -input IntPoint2DInput { - x: Int! - y: Int! -} - -type LiveTableStateGQL { +type ShotGQL { + id: Int! videoId: Int! - frameIndex: Int! - tableState: TableStateGQL! + startFrame: Int! + endFrame: Int! + createdAt: DateTime + updatedAt: DateTime + cueObjectFeatures: CueObjectFeaturesGQL + pocketingIntentionFeatures: PocketingIntentionFeaturesGQL + pocketingIntentionInfo: PocketingIntentionInfoGQL + bankFeatures: BankFeaturesGQL + serializedShotPaths: SerializedShotPathsGQL + user: UserGQL + annotations: [ShotAnnotationGQL!]! + falsePositiveScore: Float + video: VideoGQL + run: RunGQL + runFeatures: RunFeaturesGQL } -type ShotTableStateGQL { +input ShotMoveInput { shotId: Int! - videoId: Int! - frameIndex: Int! - tableState: TableStateGQL! + newClusterId: Int! } type ShotProjectionGQL { @@ -1156,13 +1415,38 @@ type ShotProjectionGQL { pottedBallIds: [Int!]! } -type BallTrajectoryGQL { - ballId: Int! - points: [TrajectoryPointGQL!]! +type ShotTableStateGQL { + shotId: Int! + videoId: Int! + frameIndex: Int! + tableState: TableStateGQL! } -type TrajectoryPointGQL { - time: Float! +input ShotsOrderingComponent @oneOf { + videoCreation: DatetimeOrdering + marginOfError: FloatOrdering + difficulty: FloatOrdering + videoId: IntOrdering + startFrame: IntOrdering + runLength: IntOrdering +} + +input SimulateShotInputGQL { + cueBallId: Int! + strike: CueStrikeInputGQL! + balls: [SimulationBallStateInputGQL!] = null + b64Image: String = null + useHomography: HomographyInputGQL = null + tableSize: Float = null +} + +type SimulationBallStateGQL { + ballId: Int! + position: [Float!]! +} + +input SimulationBallStateInputGQL { + ballId: Int! position: [Float!]! } @@ -1181,254 +1465,32 @@ enum SimulationEventType { BALL_STOP } -type SimulationBallStateGQL { - ballId: Int! - position: [Float!]! +type SpinTypeBreakdownGQL { + draw: Int! + center: Int! + follow: Int! } -input SimulateShotInputGQL { - cueBallId: Int! - strike: CueStrikeInputGQL! - balls: [SimulationBallStateInputGQL!] = null - b64Image: String = null - useHomography: HomographyInputGQL = null - tableSize: Float = null +type SpinTypeCountsGQL { + follow: Int! + draw: Int! + center: Int! + unknown: Int! } -input CueStrikeInputGQL { - v0: Float! - phi: Float! - theta: Float! = 0 - a: Float! = 0 - b: Float! = 0 +enum SpinTypeEnum { + DRAW + FOLLOW + CENTER + UNKNOWN } -input SimulationBallStateInputGQL { - ballId: Int! - position: [Float!]! -} - -type PotAimGQL { - phi: Float! - geometricPhi: Float! - cutAngle: Float! - requiredPrecision: Float! - feasible: Boolean! - potted: Boolean! - converged: Boolean! - occludingBallIds: [Int!]! -} - -type GetShotsResult { - shots: [ShotGQL!]! - count: Int - ids: [Int!]! -} - -input GetShotsOrdering { - orderings: [ShotsOrderingComponent!]! -} - -input ShotsOrderingComponent @oneOf { - videoCreation: DatetimeOrdering - marginOfError: FloatOrdering - difficulty: FloatOrdering - videoId: IntOrdering - startFrame: IntOrdering - runLength: IntOrdering -} - -input FloatOrdering { - descending: Boolean! = true - startingAt: Float = null -} - -input GetShotsPagination { - createdAfter: CreatedAfter! - startFrameAfter: Int! -} - -input CreatedAfter @oneOf { - videoId: Int - createdAt: DateTime -} - -type UsageStatsGQL { - funnel: FunnelStatsGQL! - totalUsers: Int! - totalVideos: Int! - totalShots: Int! - totalRuns: Int! - cohorts: [CohortStatsGQL!]! - windows: [UsageStatsWindowGQL!]! - daily: [UsageStatsDailyGQL!]! - processingLast24h: [ProcessingStatusCountGQL!]! -} - -type FunnelStatsGQL { - freemiumEpoch: Date! - eraSignups: Int! - eraPaying: Int! - activationCohort: Int! - activationActivated: Int! - payingUsers: Int! - newPaid7d: Int! - newPaid30d: Int! - retentionPrevActive: Int! - retentionReturned: Int! -} - -type CohortStatsGQL { - weekStart: Date! - signups: Int! - activated7d: Int! - paid7d: Int! - activatedNotPaid7d: Int! -} - -type UsageStatsWindowGQL { - label: String! - newUsers: Int! - activeUsers: Int! - sessions: Int! - shots: Int! -} - -type UsageStatsDailyGQL { - day: Date! - newUsers: Int! - activeUsers: Int! - sessions: Int! - shots: Int! -} - -type ProcessingStatusCountGQL { - status: String! - count: Int! -} - -type UserRelationshipsResult { - inquiringUser: UserGQL! - relationships: [UserRelationship!]! -} - -type UserRelationship { - toUser: UserGQL! - toUserFollows: Boolean! - toUserIsFollowedBy: Boolean! -} - -type StripeSubscriptionOptionsGQL { - products: [StripeProductGQL!]! - trialPeriodDays: Int - appleIap: AppleIapSubscriptionOptionsGQL! - tierOptions: [SubscriptionTierPurchaseOptionGQL!]! -} - -type StripeProductGQL { - id: String! - name: String! - description: String - active: Boolean! - prices: [StripePriceGQL!]! -} - -type StripePriceGQL { - id: String! - currency: String! - unitAmount: Int - recurringInterval: String - recurringIntervalCount: Int - type: String! - active: Boolean! -} - -type AppleIapSubscriptionOptionsGQL { - enabled: Boolean! - proMonthlyProductId: String - productIds: [String!]! -} - -type SubscriptionTierPurchaseOptionGQL { +type StorageLimitExceededErr { + reason: String! tierName: String! - tierDisplayName: String! - billingInterval: String! - platform: String! - isConfigured: Boolean! - isAvailable: Boolean! - stripeProductId: String - stripePriceId: String - appleProductId: String - currency: String - unitAmount: Int - recurringIntervalCount: Int -} - -type UserSubscriptionStatusGQL { - hasActiveSubscription: Boolean! - entitlementSource: EntitlementSourceTypeEnum - entitlementStartsAt: DateTime - entitlementEndsAt: DateTime - subscriptionStatus: StripeSubscriptionStatusEnum - currentPeriodStart: DateTime - currentPeriodEnd: DateTime - validUntil: DateTime - stripePriceId: String - stripeSubscriptionId: String -} - -enum EntitlementSourceTypeEnum { - ADMIN - MANUAL - STRIPE - APPLE - ALPHA_LEGACY -} - -enum StripeSubscriptionStatusEnum { - INCOMPLETE - INCOMPLETE_EXPIRED - TRIALING - ACTIVE - PAST_DUE - CANCELED - UNPAID - PAUSED -} - -type ResolvedTierGQL { - tierName: String! - tierDisplayName: String! - hasActiveSubscription: Boolean! - entitlementSource: EntitlementSourceTypeEnum - entitlementStatus: String - entitlementStartsAt: DateTime - entitlementEndsAt: DateTime - capabilities: [String!]! -} - -type QuotaStatusGQL { - tierName: String! - periodStart: DateTime! - periodEnd: DateTime! - durationUsedSeconds: Float! - durationLimitSeconds: Int - maxVideoDurationSeconds: Int - importQuotaBuckets: [QuotaBucketStatusGQL!]! - recordingQuotaBuckets: [QuotaBucketStatusGQL!]! - durationRemainingSeconds: Float - canUpload: Boolean! -} - -type QuotaBucketStatusGQL { - quotaKey: String! - appliesToUploadKind: String! - periodStart: DateTime! - periodEnd: DateTime! - durationUsedSeconds: Float! - durationLimitSeconds: Int - durationRemainingSeconds: Float - canUpload: Boolean! + retainedStorageUsedBytes: BigInt! + retainedStorageLimitBytes: BigInt + remainingStorageBytes: BigInt } type StorageStatusGQL { @@ -1447,13 +1509,103 @@ type StorageStatusGQL { lastCalculatedAt: DateTime } -""" -Integer value that can exceed GraphQL Int's 32-bit range. -""" -scalar BigInt +type StreamErrorGQL { + message: String! +} -type UserPlayTimeGQL { - totalSeconds: Float! +enum StreamSegmentTypeEnum { + FRAGMENTED_MP4 + RB_CHUNKED_MP4 +} + +type StripePriceGQL { + id: String! + currency: String! + unitAmount: Int + recurringInterval: String + recurringIntervalCount: Int + type: String! + active: Boolean! +} + +type StripeProductGQL { + id: String! + name: String! + description: String + active: Boolean! + prices: [StripePriceGQL!]! +} + +type StripeSubscriptionOptionsGQL { + products: [StripeProductGQL!]! + trialPeriodDays: Int + appleIap: AppleIapSubscriptionOptionsGQL! + tierOptions: [SubscriptionTierPurchaseOptionGQL!]! +} + +enum StripeSubscriptionStatusEnum { + INCOMPLETE + INCOMPLETE_EXPIRED + TRIALING + ACTIVE + PAST_DUE + CANCELED + UNPAID + PAUSED +} + +type SubscriptionTierPurchaseOptionGQL { + tierName: String! + tierDisplayName: String! + billingInterval: String! + platform: String! + isConfigured: Boolean! + isAvailable: Boolean! + stripeProductId: String + stripePriceId: String + appleProductId: String + currency: String + unitAmount: Int + recurringIntervalCount: Int +} + +type SuccessfulAdd { + value: Boolean! +} + +union SuccessfulAddAddShotAnnotationErrors = + SuccessfulAdd + | AddShotAnnotationErrors + +input SyncAppleSubscriptionInputGQL { + signedTransactionInfo: String! + signedRenewalInfo: String = null +} + +type SyncAppleSubscriptionResultGQL { + ok: Boolean! + errorCode: String + errorMessage: String + hasActiveSubscription: Boolean! + entitlementSource: EntitlementSourceTypeEnum + entitlementStartsAt: DateTime + entitlementEndsAt: DateTime + appleStatus: Int + originalTransactionId: String + latestTransactionId: String + productId: String + expiresAt: DateTime +} + +type TableStateGQL { + identifierToPosition: [[Float!]!]! + homography: HomographyInfoGQL + identifierToColor: [RGBColorGQL]! +} + +type TagClassGQL { + id: Int! + name: String! } type TagGQL { @@ -1463,28 +1615,194 @@ type TagGQL { retired: Boolean! } -type TagClassGQL { - id: Int! +type TargetMetricsGQL { + count: Int! + makePercentage: Float + averageDifficulty: Float + spinTypeCounts: SpinTypeCountsGQL + shotDirectionCounts: ShotDirectionCountsGQL +} + +input TimeDeltaGQL { + days: Int = 0 + weeks: Int = 0 + months: Int = 0 + years: Int = 0 +} + +input TimeInterval @oneOf { + timedelta: TimeDeltaGQL + aligned: AlignedIntervalEnum +} + +type TooManyInitUploadsErr { + linksRequested: Int! +} + +type TooManyProfileImageUploadsErr { + linksRequested: Int! +} + +type TrajectoryPointGQL { + time: Float! + position: [Float!]! +} + +input UpdateAnnotationInputGQL { name: String! + notes: String = null } -type GameTypeTagMetric { - tagName: String! - tagLabel: String! - tableSize: Float - shotCount: Int! - madeShots: Int! - makeRate: Float! +input UpdatePoolHallCameraInput { + id: ID! + name: String = null + tableLabel: String = null + status: String = null + tableSize: Float = null + pocketSize: Float = null + allowsPrivateVideos: Boolean = null + claimTermsText: String = null } -input GameTypeTagMetricsInput { - userId: Int! - createdAt: DateRangeFilter = null - maxTags: Int = null - groupByTableSize: Boolean! = true - includeUnknown: Boolean! = true - tagClass: String = "game_type" - includePrivate: IncludePrivateEnum! = MINE +input UpdatePoolHallInput { + id: ID! + name: String = null + address: String = null + city: String = null + state: String = null + latitude: Float = null + longitude: Float = null + timezone: String = null + status: String = null +} + +type UpdateShotAnnotationReturn { + shot: ShotGQL + error: DoesNotOwnShotErr +} + +type UploadLink { + uploadUrl: String! + headers: [Header]! +} + +union UploadLinkGetProfileUploadLinkErrors = + UploadLink + | GetProfileUploadLinkErrors + +union UploadLinkGetUploadLinkErrors = UploadLink | GetUploadLinkErrors + +type UploadSegmentGQL { + segmentIndex: Int! + uploaded: Boolean! + valid: Boolean! + endFrameIndex: Int + framesPerSecond: Float + durationInSeconds: Float + linksRequested: Int! +} + +type UploadStreamGQL { + id: ID! + linksRequested: Int! + uploadsCompleted: Int! + segmentProcessingCursor: Int! + lastIntendedSegmentBound: Int + isCompleted: Boolean! + initPlaylistUploadStatus: InitPlaylistUploadStatusEnum + lowestUnuploadedSegmentIndex: Int! + uploadCompletionCursor: Int! + lastSegmentUploadedAt: DateTime + errors: [StreamErrorGQL!]! + createdAt: DateTime! + updatedAt: DateTime! + segments: [UploadSegmentGQL!]! + clientUploadStatus: ClientUploadStatusEnum + resolution: VideoResolutionGQL! + streamSegmentType: StreamSegmentTypeEnum! +} + +type UsageStatsDailyGQL { + day: Date! + newUsers: Int! + activeUsers: Int! + sessions: Int! + shots: Int! +} + +type UsageStatsGQL { + funnel: FunnelStatsGQL! + totalUsers: Int! + totalVideos: Int! + totalShots: Int! + totalRuns: Int! + cohorts: [CohortStatsGQL!]! + windows: [UsageStatsWindowGQL!]! + daily: [UsageStatsDailyGQL!]! + processingLast24h: [ProcessingStatusCountGQL!]! +} + +type UsageStatsWindowGQL { + label: String! + newUsers: Int! + activeUsers: Int! + sessions: Int! + shots: Int! +} + +type UserGQL { + id: Int! + firebaseUid: String + username: String! + isAdmin: Boolean + fargoRating: Int + activeVideoId: Int + stripeCustomerId: String + profileImageUri: String + bio: String + createdAt: DateTime + updatedAt: DateTime + videosPrivateByDefault: Boolean + agreesToMarketing: Boolean + following: [UserGQL!] + followers: [UserGQL!] + isFollowedByCurrentUser: Boolean +} + +type UserPlayTimeGQL { + totalSeconds: Float! +} + +type UserRelationship { + toUser: UserGQL! + toUserFollows: Boolean! + toUserIsFollowedBy: Boolean! +} + +type UserRelationshipsResult { + inquiringUser: UserGQL! + relationships: [UserRelationship!]! +} + +type UserShotCountEntry { + user: UserGQL! + value: Int! + total: Int! + proportionMade: Float! + videos: Int! +} + +type UserSubscriptionStatusGQL { + hasActiveSubscription: Boolean! + entitlementSource: EntitlementSourceTypeEnum + entitlementStartsAt: DateTime + entitlementEndsAt: DateTime + subscriptionStatus: StripeSubscriptionStatusEnum + currentPeriodStart: DateTime + currentPeriodEnd: DateTime + validUntil: DateTime + stripePriceId: String + stripeSubscriptionId: String } type VideoExportJobGQL { @@ -1517,368 +1835,57 @@ enum VideoExportStatusEnum { EXPIRED } -""" -The `JSON` scalar type represents JSON values as specified by [ECMA-404](https://ecma-international.org/wp-content/uploads/ECMA-404_2nd_edition_december_2017.pdf). -""" -scalar JSON - @specifiedBy( - url: "https://ecma-international.org/wp-content/uploads/ECMA-404_2nd_edition_december_2017.pdf" - ) - -type Mutation { - createBucketSet(params: CreateBucketSetInput!): BucketSetGQL! - createRuleSet(name: String!, description: String = null): RuleSet! - createChallenge( - name: String! - ruleSetId: ID! - minimumShots: Int! - startDate: DateTime! - endDate: DateTime! - description: String = null - requiredTableSize: Float = null - requiredPocketSize: Float = null - isPublic: Boolean! = false - maxAttempts: Int = null - ): Challenge! - inviteUsersToChallenge( - challengeId: ID! - userIds: [ID!]! - ): [ChallengeInvitation!]! - respondToChallengeInvitation( - invitationId: ID! - accept: Boolean! - ): ChallengeInvitation! - startChallenge(challengeId: ID!): ChallengeEntry! - recalculateChallengeEntry(entryId: ID!): ChallengeEntry! - submitChallengeEntry(entryId: ID!, videoId: ID!): ChallengeEntry! - dismissChallenge(challengeId: ID!): Boolean! - undismissChallenge(challengeId: ID!): Boolean! - setLoggerLevel(path: String!, level: String!): Boolean! - reactToVideo(videoId: Int!, reaction: ReactionEnum): Boolean! - commentOnVideo( - videoId: Int! - message: String! - parentCommentId: Int - ): Boolean! - editComment(videoId: Int!, commentId: Int!, newMessage: String!): Boolean! - deleteComment(videoId: Int!, commentId: Int!): Boolean! - blockContent(videoId: Int!): Boolean! - blockUser(userId: Int!): Boolean! - reportContent( - videoId: Int! - reason: ReportReasonEnum! - customReason: String = null - ): Boolean! - markNotificationAsRead(notificationId: Int!): Boolean! - markAllNotificationsAsRead: Boolean! - markNotificationsAsRead(notificationIds: [Int!]!): Boolean! - deleteNotification(notificationId: Int!): Boolean! - createPoolHall(input: CreatePoolHallInput!): PoolHall! - updatePoolHall(input: UpdatePoolHallInput!): PoolHall! - createPoolHallCamera( - input: CreatePoolHallCameraInput! - ): PoolHallCameraStreamCredentials! - updatePoolHallCamera(input: UpdatePoolHallCameraInput!): PoolHallCamera! - rotatePoolHallCameraStreamKey(cameraId: ID!): PoolHallCameraStreamCredentials! - createCameraClaimSession( - cameraId: ID! - durationMinutes: Int = null - videoName: String = null - videoPrivate: Boolean = null - agreedTermsVersion: Int = null - tags: [VideoTagInput!] = null - ): CameraClaimSession! - cancelCameraClaimSession(claimSessionId: ID!): CameraClaimSession! - endCameraLease(leaseId: ID!): CameraLease! - extendCameraLease(leaseId: ID!, additionalMinutes: Int! = 60): CameraLease! - finalizePlayerAssignments( - input: FinalizePlayerAssignmentsInput! - ): [PlayerClusterGQL!]! - addAnnotationToShot( - shotId: Int! - annotationName: String! - notes: String = null - ): AddShotAnnotationReturn! - updateShotAnnotations( - shotId: Int! - annotations: [UpdateAnnotationInputGQL!]! - ): UpdateShotAnnotationReturn! - editShot( - shotId: Int! - fieldsToEdit: EditableShotFieldInputGQL! - ): EditShotReturn! - getProfileImageUploadLink( - fileExt: String = ".png" - ): GetProfileUploadLinkReturn! - editProfileImageUri(profileImageUri: String!): UserGQL! - editUser(input: EditUserInputGQL!): UserGQL! - followUser(followedUserId: Int!): UserGQL! - unfollowUser(followedUserId: Int!): UserGQL! - retireTags(tagIds: [Int!]!): Boolean! - ensureStripeCustomerExists: UserGQL! - deleteUser: Boolean! - syncAppleSubscription( - input: SyncAppleSubscriptionInputGQL! - ): SyncAppleSubscriptionResultGQL! - createSubscription(priceId: String!): CreateSubscriptionResultGQL! - createCustomerPortalSession: CreateCustomerPortalSessionResultGQL! - cancelSubscription: UserSubscriptionStatusGQL! - grantManualEntitlement( - userId: Int! - tierName: String! = "pro" - startsAt: DateTime = null - endsAt: DateTime = null - reason: String = null - ): UserSubscriptionStatusGQL! - revokeManualEntitlement(userId: Int!): UserSubscriptionStatusGQL! - submitCancellationFeedback( - reasons: [CancellationReasonEnum!] = null - feedback: String = null - metadata: CancellationFeedbackMetadataInput = null - ): Boolean! - requestVideoExport(input: RequestVideoExportInput!): VideoExportJobGQL! - dismissVideoExport(jobId: Int!): Boolean! - findPrerecordTableLayout(b64Image: String!, videoId: Int!): HomographyInfoGQL - createUploadStream( - videoMetadata: VideoMetadataInput! - expectedDurationSeconds: Float = null - ): CreateUploadStreamReturn! - getUploadLink(videoId: Int!, segmentIndex: Int!): GetUploadLinkReturn! - getHlsInitUploadLink(videoId: Int!): GetUploadLinkReturn! - setSegmentDuration( - videoId: Int! - segmentIndex: Int! - duration: Float! - ): Boolean! - editUploadStream(videoId: Int!, videoMetadata: VideoMetadataInput!): Boolean! - deleteVideo(videoId: Int!): Boolean! - deleteTags(videoId: Int!, tagsToDelete: [VideoTagInput!]!): Boolean! +input VideoFeedInputGQL @oneOf { + followedByUserId: Int + userId: Int + allUsers: Boolean + home: Boolean } -input CreateBucketSetInput { - keyName: String! - feature: String! - buckets: [BucketInputGQL!]! +input VideoFilterInput { + isStreamCompleted: Boolean = null + requireCursorCompletion: Boolean! = true + createdAt: DateRangeFilter = null + excludeVideosWithNoShots: Boolean = null } -enum ReportReasonEnum { - SPAM - NUDITY - VIOLENCE - HATE - COPYRIGHT - OTHER +type VideoGQL { + id: Int! + owner: UserGQL + name: String + screenshotUri: String + totalShotsMade: Int! + totalShots: Int! + makePercentage: Float! + medianRun: Float + averageTimeBetweenShots: Float + averageDifficulty: Float + createdAt: DateTime + updatedAt: DateTime + shots: [ShotGQL!]! + startTime: DateTime + endTime: DateTime + elapsedTime: Float + framesPerSecond: Float! + tableSize: Float! + pocketSize: Float + private: Boolean! + stream: UploadStreamGQL + playlist: HLSPlaylistGQL + tags: [VideoTag!]! + currentHomography: HomographyInfoGQL + homographyHistory: [HomographyInfoGQL!]! + currentProcessing: VideoProcessingGQL + reactions: [ReactionGQL!]! + comments: [CommentGQL!]! + playerSummaries: [PlayerSummaryGQL!]! } -input CreatePoolHallInput { - name: String! - address: String = null - city: String = null - state: String = null - latitude: Float = null - longitude: Float = null - timezone: String = null -} - -input UpdatePoolHallInput { - id: ID! - name: String = null - address: String = null - city: String = null - state: String = null - latitude: Float = null - longitude: Float = null - timezone: String = null - status: String = null -} - -type PoolHallCameraStreamCredentials { - camera: PoolHallCamera! - streamKey: String! - rtmpPath: String! -} - -input CreatePoolHallCameraInput { - poolHallId: ID! - name: String! - tableLabel: String = null - streamPath: String = null - tableSize: Float = null - pocketSize: Float = null - allowsPrivateVideos: Boolean = null - claimTermsText: String = null -} - -input UpdatePoolHallCameraInput { - id: ID! - name: String = null - tableLabel: String = null - status: String = null - tableSize: Float = null - pocketSize: Float = null - allowsPrivateVideos: Boolean = null - claimTermsText: String = null -} - -input FinalizePlayerAssignmentsInput { - videoId: Int! - clusterAssignments: [ClusterAssignmentInput!]! = [] - shotMoves: [ShotMoveInput!]! = [] -} - -input ClusterAssignmentInput { - clusterId: Int! - userId: Int = null - score: Int = null -} - -input ShotMoveInput { - shotId: Int! - newClusterId: Int! -} - -type AddShotAnnotationReturn { - value: SuccessfulAddAddShotAnnotationErrors! -} - -union SuccessfulAddAddShotAnnotationErrors = - SuccessfulAdd - | AddShotAnnotationErrors - -type SuccessfulAdd { - value: Boolean! -} - -type AddShotAnnotationErrors { - error: DoesNotOwnShotErrOtherErrorNeedsNote! -} - -union DoesNotOwnShotErrOtherErrorNeedsNote = - DoesNotOwnShotErr - | OtherErrorNeedsNote - -type DoesNotOwnShotErr { - shotId: Int! - msg: String -} - -type OtherErrorNeedsNote { - msg: String -} - -type UpdateShotAnnotationReturn { - shot: ShotGQL - error: DoesNotOwnShotErr -} - -input UpdateAnnotationInputGQL { - name: String! - notes: String = null -} - -type EditShotReturn { - shot: ShotGQL - error: DoesNotOwnShotErr -} - -input EditableShotFieldInputGQL { - intendedPocketType: PocketEnum - shotDirection: ShotDirectionEnum - spinType: SpinTypeEnum - targetPocketAngleDirection: ShotDirectionEnum - make: Boolean - backcut: Boolean - excludeFromStats: Boolean - notes: String -} - -type GetProfileUploadLinkReturn { - value: UploadLinkGetProfileUploadLinkErrors! -} - -union UploadLinkGetProfileUploadLinkErrors = - UploadLink - | GetProfileUploadLinkErrors - -type UploadLink { - uploadUrl: String! - headers: [Header]! -} - -type Header { - key: String! - value: String! -} - -type GetProfileUploadLinkErrors { - error: TooManyProfileImageUploadsErr! -} - -type TooManyProfileImageUploadsErr { - linksRequested: Int! -} - -input EditUserInputGQL { - username: String = null - fargoRating: Int = null - videosPrivateByDefault: Boolean = null - agreesToMarketing: Boolean = null - bio: String = null -} - -type SyncAppleSubscriptionResultGQL { - ok: Boolean! - errorCode: String - errorMessage: String - hasActiveSubscription: Boolean! - entitlementSource: EntitlementSourceTypeEnum - entitlementStartsAt: DateTime - entitlementEndsAt: DateTime - appleStatus: Int - originalTransactionId: String - latestTransactionId: String - productId: String - expiresAt: DateTime -} - -input SyncAppleSubscriptionInputGQL { - signedTransactionInfo: String! - signedRenewalInfo: String = null -} - -type CreateSubscriptionResultGQL { - checkoutUrl: String! - sessionId: String! -} - -type CreateCustomerPortalSessionResultGQL { - portalUrl: String! -} - -enum CancellationReasonEnum { - DONT_PLAY_ENOUGH - TOO_EXPENSIVE - MISSING_FEATURES - TECHNICAL_ISSUES - DATA_NOT_ACCURATE - OTHER -} - -input CancellationFeedbackMetadataInput { - appVersion: String = null - gitRevision: String = null - platform: String = null -} - -input RequestVideoExportInput { - videoId: Int! - mode: VideoExportModeEnum! - shotIds: [Int!] = null - runId: Int = null -} - -type CreateUploadStreamReturn { - videoId: Int! +type VideoHistoryGQL { + videos: [VideoGQL!]! + pageInfo: PageInfoGQL! + hasFollowing: Boolean! + followingCount: Int! } input VideoMetadataInput { @@ -1904,66 +1911,61 @@ input VideoMetadataInput { homographyBackend: HomographyBackendGQL = null } +type VideoProcessingErrorGQL { + message: String! + startSegmentIndex: Int + endSegmentIndex: Int +} + +type VideoProcessingGQL { + id: Int! + parentProcessingId: Int + labels: [String!]! + errors: [VideoProcessingErrorGQL!]! + status: ProcessingStatusEnum! + statuses: [VideoProcessingStatusGQL!]! + framesProcessed: Int + currentSegment: Int + progressPercentage: Float +} + +type VideoProcessingStatusGQL { + status: ProcessingStatusEnum! + appVersion: String! + sequenceId: Int! + createdAt: DateTime + updatedAt: DateTime +} + input VideoResolution { width: Int! height: Int! } -enum HomographyBackendGQL { - CLASSIC - TABLENET +type VideoResolutionGQL { + width: Int + height: Int } -type GetUploadLinkReturn { - value: UploadLinkGetUploadLinkErrors! - stream: UploadStreamGQL +type VideoTag { + tagClasses: [VideoTagClass!]! + name: String! } -union UploadLinkGetUploadLinkErrors = UploadLink | GetUploadLinkErrors - -type GetUploadLinkErrors { - error: MustHaveSetForUploadLinkErrSegmentAlreadyUploadedErrProcessingFailedErrNoInitForChunkedUploadErrTooManyProfileImageUploadsErrInitUploadAlreadyCompletedErrTooManyInitUploadsErrStorageLimitExceededErr! +type VideoTagClass { + name: String! } -union MustHaveSetForUploadLinkErrSegmentAlreadyUploadedErrProcessingFailedErrNoInitForChunkedUploadErrTooManyProfileImageUploadsErrInitUploadAlreadyCompletedErrTooManyInitUploadsErrStorageLimitExceededErr = - MustHaveSetForUploadLinkErr - | SegmentAlreadyUploadedErr - | ProcessingFailedErr - | NoInitForChunkedUploadErr - | TooManyProfileImageUploadsErr - | InitUploadAlreadyCompletedErr - | TooManyInitUploadsErr - | StorageLimitExceededErr - -type MustHaveSetForUploadLinkErr { - resolution: Boolean - framesPerSecond: Boolean +input VideoTagClassInput { + name: String! } -type SegmentAlreadyUploadedErr { - segmentId: Int! +input VideoTagInput { + tagClasses: [VideoTagClassInput!]! = [] + name: String! } -type ProcessingFailedErr { - processing: VideoProcessingGQL! -} - -type NoInitForChunkedUploadErr { - segmentType: StreamSegmentTypeEnum! -} - -type InitUploadAlreadyCompletedErr { - segmentType: StreamSegmentTypeEnum! -} - -type TooManyInitUploadsErr { - linksRequested: Int! -} - -type StorageLimitExceededErr { - reason: String! - tierName: String! - retainedStorageUsedBytes: BigInt! - retainedStorageLimitBytes: BigInt - remainingStorageBytes: BigInt +enum WallTypeEnum { + LONG + SHORT }