syntax = "proto3";

package devvit.plugin.redditapi.common;

import "devvit/reddit/user.proto";
import "google/protobuf/any.proto";
import "google/protobuf/descriptor.proto";
import "google/protobuf/struct.proto";
import "google/protobuf/wrappers.proto";
import "reddit/devvit/app_permission/v1/app_permission.proto";

option go_package = "github.snooguts.net/reddit/reddit-devplatform-monorepo/go-common/generated/protos/types/devvit/plugin/redditapi";
option java_package = "com.reddit.devvit.plugin.redditapi.common";

// Label that can be applied to a highlighted post in a subreddit.
// This enum should map to the equivalent in GraphQL: https://github.snooguts.net/reddit/reddit-service-graphql/blob/master/graphql-py/graphql_api/lib/community_eng/types/highlighted_post.py#L18
enum HighlightedPostLabel {
  // Post is highlighted without a label.
  HIGHLIGHTED_POST_LABEL_UNSPECIFIED = 0;
  // Post is highlighted as an announcement.
  ANNOUNCEMENT = 1;
  // Post is highlighted as an event.
  EVENT = 2;
  // Post is highlighted as a megathread.
  MEGATHREAD = 3;
  // Post is highlighted with its flair as the label.
  // If the post doesn't have flair, this is the same as UNSPECIFIED
  SHOW_POST_FLAIR = 4;
}

// A Listing is a paginated list of Things such as Subreddits, Posts, or Comments
message Listing {
  message ListingData {
    // If present, use this as the `after` parameter when calling the same
    // API again to fetch the next page
    google.protobuf.StringValue after = 1;
    // If present, use this as the `before` parameter when calling the same
    // API again to fetch the previous page
    google.protobuf.StringValue before = 2;
    // Contents of the current page of the listing
    repeated WrappedRedditObject children = 3;
    // Number of objects in `children`
    // Note: Only counts immediate entries in `children` and does not count
    //       nested objects such as comment trees
    google.protobuf.Int64Value dist = 4;
  }

  // String value: "Listing"
  string kind = 1;
  // Contents of the listing
  ListingData data = 2;
}

// A WrappedRedditObject couples a RedditObject with a type identifier
message WrappedRedditObject {
  // Thing ID prefix to identify what kind of object this is
  string kind = 1;
  // Object data of type `kind`
  RedditObject data = 2;
}

message JsonRedditObjects {
  message JsonType {
    message JsonData {
      repeated WrappedRedditObject things = 1;
    }

    repeated google.protobuf.Any errors = 1;
    JsonData data = 2;
  }
  JsonType json = 4;
}

// A RedditObject can either be a Post (t3) or a Comment (t1)
//
// Note: Will be replaced by the discrete {@link Comment} and {@link Post} types
message RedditObject {
  // oEmbed is a format for allowing an embedded representation of a URL on third party sites.
  // The simple API allows a website to display embedded content (such as photos or videos)
  // when a user posts a link to that resource, without having to parse the resource directly.
  // See: https://oembed.com/
  message OEmbed {
    //  The resource type. Valid values, along with value-specific parameters, are described below. E.g. "video"
    string type = 1;
    // A text title, describing the resource.
    optional string title = 2;
    // A URL for the author/owner of the resource. E.g. "YouTube"
    optional string provider_name = 3;
    // The name of the resource provider. E.g https://www.youtube.com/
    optional string provider_url = 4;
    // The oEmbed version number. This must be 1.0.
    string version = 5;
    // The width of the optional thumbnail in pixels
    optional google.protobuf.Int32Value thumbnail_width = 6;
    // The height of the optional thumbnail in pixels
    optional google.protobuf.Int32Value thumbnail_height = 7;
    // A URL to a thumbnail image representing the resource.
    optional string thumbnail_url = 8;
    // The HTML required to embed a video player. The HTML should have no padding or margins. Consumers may wish to load the HTML in an off-domain iframe to avoid XSS vulnerabilities.
    string html = 9;
    // The width in pixels required to display the HTML.
    google.protobuf.Int32Value height = 10;
    // The height in pixels required to display the HTML.
    google.protobuf.Int32Value width = 11;
    // A URL for the author/owner of the resource. E.g. https://www.youtube.com/@Reddit
    optional string author_url = 12;
    // The name of the author/owner of the resource. E.g. "Reddit"
    optional string author_name = 13;
  }

  // Contains the data for a video hosted on Reddit that is in a post
  message RedditVideo {
    // The bitrate of the video in kilobits per second. E.g. 450
    google.protobuf.Int32Value bitrate_kbps = 1;
    // The URL to the DASH playlist file. E.g. "https://v.redd.it/abc123/DASHPlaylist.mpd"
    google.protobuf.StringValue dash_url = 2;
    // The duration of the video in seconds. E.g. 30
    google.protobuf.Int32Value duration = 3;
    // The direct URL to the video. E.g. "https://v.redd.it/abc123/DASH_1080.mp4?source=fallback"
    google.protobuf.StringValue fallback_url = 4;
    // The height of the video in pixels. E.g. 1080
    google.protobuf.Int32Value height = 5;
    // The URL to the HLS playlist file. E.g. "https://v.redd.it/abc123/HLSPlaylist.m3u8"
    google.protobuf.StringValue hls_url = 6;
    // If `true`, the video is a GIF
    google.protobuf.BoolValue is_gif = 7;
    // The URL to the scrubber media file. E.g. "https://v.redd.it/abc123/DASH_96.mp4"
    google.protobuf.StringValue scrubber_media_url = 8;
    // The status of the transcoding process. E.g. "completed"
    google.protobuf.StringValue transcoding_status = 9;
    // The width of the video in pixels. E.g. 1920
    google.protobuf.Int32Value width = 10;
  }

  // RichText document for author flair
  message AuthorFlairRichText {
    // enum of element types.  e.g. emoji or text
    google.protobuf.StringValue e = 1;
    // text to show up in the flair, e.g. "power poster"
    google.protobuf.StringValue t = 2;
    // emoji references, e.g. ":rainbow:"
    google.protobuf.StringValue a = 3;
    // url string, e.g. "https://reddit.com/"
    google.protobuf.StringValue u = 4;
  }

  // RichText document for post flair
  message LinkFlairRichText {
    // enum of element types.  e.g. emoji or text
    google.protobuf.StringValue e = 1;
    // text to show up in the flair, e.g. "Need Advice"
    google.protobuf.StringValue t = 2;
    // emoji references, e.g. ":rainbow:"
    google.protobuf.StringValue a = 3;
    // url string, e.g. "https://reddit.com/"
    google.protobuf.StringValue u = 4;
  }

  // Secure Media object
  message SecureMedia {
    // The type of the Secure Media (e.g. "youtube.com"). Populated when 'oembed' is present.
    string type = 1;
    // Populated when the post media is hosted on a third-party site.
    OEmbed oembed = 2;
    // Populated when the post media is a video hosted on Reddit.
    RedditVideo reddit_video = 3;
  }

  // List of awards this object has received
  // Note: not yet parsed by RedditAPI
  // @ignore
  repeated google.protobuf.Any all_awardings = 1;
  // If `true` this has been approved by a moderator
  google.protobuf.BoolValue approved = 2;
  // Timestamp when this was approved
  google.protobuf.Int64Value approved_at_utc = 3;
  // Username of the moderator that manually approved this object
  google.protobuf.StringValue approved_by = 4;
  // If `true`, this object has been archived
  google.protobuf.BoolValue archived = 5;
  google.protobuf.StringValue associated_award = 6;
  // The username of the author of this object
  // @example "spez"
  google.protobuf.StringValue author = 7;
  // Flair background color as a hex color string (# prefixed)
  // @example "#FF4500"
  google.protobuf.StringValue author_flair_background_color = 8;
  // Custom CSS classes from the subreddit's stylesheet
  // to apply to the flair if rendered as HTML
  google.protobuf.StringValue author_flair_css_class = 9;
  // RichText representation of the author's flair
  // Note: incorrectly typed and not guaranteed to be useful
  repeated AuthorFlairRichText author_flair_richtext = 10;
  // Flair template ID to use when rendering this flair
  // @see Use {@link Flair.FlairList} to get flair templates for a subreddit
  // @example "813b473a-4d74-4933-ba79-a7f1b8b285ef"
  google.protobuf.StringValue author_flair_template_id = 11;
  // Plain text representation of the flair RichText
  google.protobuf.StringValue author_flair_text = 12;
  // One of: "light", "dark"
  google.protobuf.StringValue author_flair_text_color = 13;
  // One of: "text", "richtext"
  google.protobuf.StringValue author_flair_type = 14;
  // Thing ID of the author
  // @example "t2_abc123"
  google.protobuf.StringValue author_fullname = 15;
  // If `true`, the current user has blocked the author
  google.protobuf.BoolValue author_is_blocked = 16;
  // @deprecated
  google.protobuf.BoolValue author_patreon_flair = 17 [deprecated = true];
  // If `true`, this author is subscribed to Reddit Premium
  google.protobuf.BoolValue author_premium = 18;
  // List of usernames that have given awards to this object
  repeated google.protobuf.StringValue awarders = 19;
  // Timestamp when this was banned
  google.protobuf.Int64Value banned_at_utc = 20;
  // Username of the moderator that banned this object
  google.protobuf.StringValue banned_by = 21;
  // Markdown body text if this is a Comment
  google.protobuf.StringValue body = 22;
  // Pre-rendered HTML representing the Markdown or RichText body of a Comment
  google.protobuf.StringValue body_html = 23;
  // If `true`, the current user can award this object
  google.protobuf.BoolValue can_gild = 24;
  // If `true`, the current user has adequate permission to moderate this object
  google.protobuf.BoolValue can_mod_post = 25;
  // If `true`, this Comment is collapsed by default
  // @see {@link collapsed_reason} and {@link collapsed_reason_code} to determine why
  google.protobuf.BoolValue collapsed = 26;
  // Alias for collapsed_reason_code = "CROWD_CONTROL"
  google.protobuf.BoolValue collapsed_because_crowd_control = 27;
  // User-friendly string explaining why this Comment is collapsed
  google.protobuf.StringValue collapsed_reason = 28;
  // One of: "LOW_SCORE", "BLOCKED_AUTHOR", "POTENTIALLY_TOXIC", "CROWD_CONTROL", "DELETED"
  google.protobuf.StringValue collapsed_reason_code = 29;
  google.protobuf.StringValue comment_type = 30;
  // If set to `1` this Comment is considered controversial
  google.protobuf.Int64Value controversiality = 31;
  // Timestamp when this object was created
  // @see Alias for {@link created_utc}
  google.protobuf.Int64Value created = 32;
  // Timestamp when this object was created
  // @see Alias for {@link created}
  google.protobuf.Int64Value created_utc = 33;
  // If `true`, an admin has distinguished this object
  google.protobuf.StringValue distinguished = 34;
  // Previously displayed the number of downvotes this object received
  // @deprecated Always returns 0
  google.protobuf.Int64Value downs = 35;
  // If `true`, the body of this object has been edited since it was posted
  google.protobuf.BoolValue edited = 36;
  // Number of times this object has received a Gold award
  // @deprecated
  google.protobuf.Int64Value gilded = 37 [deprecated = true];
  // Map of gold awards to the number of times received
  // Note: Incorrectly typed and may be unusable.
  // @deprecated
  google.protobuf.Any gildings = 38 [deprecated = true];
  // Thing ID for this Post or Comment without leading thing ID prefix
  // @example "abc123" // for: t1_abc123
  google.protobuf.StringValue id = 39;
  // Whether or not a moderator has disabled reports for this object
  google.protobuf.BoolValue ignore_reports = 40;
  // If `true`, this object was submitted by the current user
  google.protobuf.BoolValue is_submitter = 41;
  // Upvote status where:
  //  - `true`: Upvote
  //  - `null`: No vote
  //  - `false`: Downvote
  google.protobuf.BoolValue likes = 42;
  // Thing ID of the parent Post for this Comment
  // @example "t3_abc123"
  google.protobuf.StringValue link_id = 43;
  // If `true`, this object has been locked and replies are disabled
  google.protobuf.BoolValue locked = 44;
  // Notes added by the moderator when a removal reason chosen
  google.protobuf.StringValue mod_note = 45;
  // Moderator username that chose the reason for the object to be removed
  google.protobuf.StringValue mod_reason_by = 46;
  // The title of the removal reason chosen by the moderator
  google.protobuf.StringValue mod_reason_title = 47;

  // prev repeated google.protobuf.Any mod_reports
  reserved 48;

  // Thing ID for this object
  // @example "t1_abc123"
  google.protobuf.StringValue name = 49;
  google.protobuf.BoolValue no_follow = 50;
  // Total number of reports that have been filed against this object
  google.protobuf.Int64Value num_reports = 52;
  // Thing ID of the parent object immediately above this object in the tree
  // Note: If this is a top-level comment the parent would be the Post (t3)
  //       but if it was a reply to another comment the parent would be the
  //       Comment (t1) being replied to
  // @see {@link link_id} to skip to the root of the comment tree
  // @example "t1_abc123"
  google.protobuf.StringValue parent_id = 53;
  // The path of this object relative to www.reddit.com
  // @example "/r/aww/comments/ze7u6n/oc_just_woke_up_from_his_nap/"
  google.protobuf.StringValue permalink = 54;
  google.protobuf.StringValue removal_reason = 55;
  // If `true`, the object has been removed by a moderator
  google.protobuf.BoolValue removed = 56;
  // Comments made directly to this object
  // Note: Incorrect type. Currently unusable.
  // @deprecated Please use replyList instead
  google.protobuf.StringValue replies = 57 [deprecated = true];
  google.protobuf.ListValue report_reasons = 58;
  // RichText editor mode
  // One of: "richtext", "markdown"
  google.protobuf.StringValue rte_mode = 59;
  // If `true`, the current user has saved this object to their profile
  google.protobuf.BoolValue saved = 60;
  // Current total score for this object
  google.protobuf.Int64Value score = 61;
  // If `true`, the `score` for this object is not visible to the current user
  google.protobuf.BoolValue score_hidden = 62;
  // If `true` the current user will receive notifications when someone replies to this object
  google.protobuf.BoolValue send_replies = 63;
  // If `true` this has been flagged as spam by a moderator
  google.protobuf.BoolValue spam = 64;
  // If `true` this should be presented before others relative to its type
  google.protobuf.BoolValue stickied = 65;
  // Name of the Subreddit that owns this object
  // @example "AskReddit"
  google.protobuf.StringValue subreddit = 66;
  // Thing ID of the Subreddit that owns this object
  // @example "t5_abc123"
  google.protobuf.StringValue subreddit_id = 67;
  // Name of the Subreddit that owns this object prefixed with "r/"
  // @example "r/aww"
  google.protobuf.StringValue subreddit_name_prefixed = 68;
  // One of: "public", "private", "restricted", "gold_only", "gold_restricted",
  //         "archived", "user", "employees_only"
  google.protobuf.StringValue subreddit_type = 69;
  // One of: "ACTIVE", "INACTIVE"
  google.protobuf.StringValue top_awarded_type = 70;
  // Total count of awards this object has received
  google.protobuf.Int64Value total_awards_received = 71;
  repeated google.protobuf.Any treatment_tags = 72;
  google.protobuf.StringValue unrepliable_reason = 73;
  // Alias for score
  google.protobuf.Int64Value ups = 74;

  // prev repeated google.protobuf.Any user_reports
  reserved 75;

  // The depth of this object relative to the Listing
  google.protobuf.Int64Value depth = 76;
  // If this is a Comment, the title of the parent Post
  google.protobuf.StringValue link_title = 77;
  // If this is a Comment, the author of the parent Post
  google.protobuf.StringValue link_author = 78;
  // Total number of comments this object has received
  google.protobuf.Int64Value num_comments = 79;
  // If `true`, mark as not-safe-for-work
  google.protobuf.BoolValue over_18 = 80;
  // The path of this object relative to www.reddit.com
  // @example "/r/aww/comments/ze7u6n/oc_just_woke_up_from_his_nap/"
  google.protobuf.StringValue link_permalink = 81;
  // Whether this Thing has been
  google.protobuf.BoolValue quarantine = 82;
  // If this is a Comment, the URL associated with the parent Post
  google.protobuf.StringValue link_url = 83;
  // Markdown body text if this is a Text Post
  google.protobuf.StringValue selftext = 84;
  // Pre-rendered HTML representing the Markdown or RichText body of a Text Post
  google.protobuf.StringValue selftext_html = 85;

  // prev: google.protobuf.StringValue spoiler = 86;
  reserved 86;

  // URL of a scaled down preview image of the media in this object
  google.protobuf.StringValue thumbnail = 87;
  // Width of the thumbnail image, in pixels
  google.protobuf.Int64Value thumbnail_width = 88;
  // Height of the thumbnail image, in pixels
  google.protobuf.Int64Value thumbnail_height = 89;
  // Title of the Post if it is a Post
  google.protobuf.StringValue title = 90;
  // If this is a Post, contains one of the following:
  //  - Empty if this is a Text Post
  //  - The URL submitted by the user if this is a Link Post
  //  - The full-size image or video URL if this is an Image, Video, or VideoGif Post
  google.protobuf.StringValue url = 91;
  // The name of the Subreddit if this object represents a Subreddit
  //
  // Note: This object is intended for Post and Comment data but
  //       Listings.Info() returns a ListingObject which can only contain
  //       WrappedRedditObject data, though that endpoint is able to
  //       fetch Subreddit data if a t5_ ID is provided as an argument.
  google.protobuf.StringValue display_name = 92;
  // The list of moderator permissions for a user
  repeated google.protobuf.StringValue mod_permissions = 93;

  // Number of replies intended for More data
  google.protobuf.Int64Value count = 94;
  // Ids of children intended for More data (without leading thing ID prefix)
  google.protobuf.ListValue children = 95;

  // List of replies if this is a comment
  Listing reply_list = 96;

  // If `true` this post has been hidden
  google.protobuf.BoolValue hidden = 97;

  // Post Flair aka Link Flair
  // Flair background color as a hex color string (# prefixed)
  // @example "#FF4500"
  google.protobuf.StringValue link_flair_background_color = 98;
  // Custom CSS classes from the subreddit's stylesheet
  // to apply to the flair if rendered as HTML
  google.protobuf.StringValue link_flair_css_class = 99;
  // RichText representation of the post's flair
  repeated LinkFlairRichText link_flair_richtext = 100;
  // Flair template ID to use when rendering this flair
  // @see Use {@link Flair.FlairList} to get flair templates for a subreddit
  // @example "813b473a-4d74-4933-ba79-a7f1b8b285ef"
  google.protobuf.StringValue link_flair_template_id = 101;
  // Plain text representation of the flair RichText
  google.protobuf.StringValue link_flair_text = 102;
  // One of: "light", "dark"
  google.protobuf.StringValue link_flair_text_color = 103;
  // One of: "text", "richtext"
  google.protobuf.StringValue link_flair_type = 104;
  // Information about the media embedded to the post
  SecureMedia secure_media = 105;

  // If `true`, hide the contents of this post until the user explicitly opens it
  bool spoiler = 106;

  // List of reports submitted by moderators against this object
  repeated google.protobuf.ListValue mod_reports = 107;

  // List of reports submitted by users against this object
  repeated google.protobuf.ListValue user_reports = 108;

  // Who removed this object (username)
  google.protobuf.StringValue removed_by = 109;

  // Returns information about who/what removed this object. It will return one of the following:
  // - "anti_evil_ops": object is removed by a aeops member
  // - "author": object is removed by author of the post
  // - "automod_filtered": object is filtered by automod
  // - "community_ops": object is removed by a community team member
  // - "content_takedown": object is removed due to content violation
  // - "copyright_takedown": object is removed due to copyright violation
  // - "deleted": object is deleted
  // - "moderator": object is removed by a mod of the sub
  // - "reddit": object is removed by anyone else
  // - None: object is not removed
  google.protobuf.StringValue removed_by_category = 110;

  message GalleryMedia {
    // The URL of the media
    string url = 1;
    // The width of the media in pixels
    int64 width = 2;
    // The height of the media in pixels
    int64 height = 3;
    // Status of the media upload (e.g. "valid", "failed")
    GalleryMediaStatus status = 4;
  }
  // List of media (images or gifs) in a gallery post
  repeated GalleryMedia gallery = 111;

  // NEXT: 112
}

// @privateRemarks
// TODO: remove in favor of Subreddit
// A SubredditObject represents a Subreddit (t5)
message SubredditObject {
  // @deprecated
  google.protobuf.BoolValue default_set = 1 [deprecated = true];
  // If `true`, the current user has posted
  google.protobuf.BoolValue user_is_contributor = 2;
  // Banner image for old.reddit.com
  // @deprecated
  google.protobuf.StringValue banner_img = 3 [deprecated = true];
  // If `true`, crowd control is enabled
  google.protobuf.BoolValue restrict_posting = 4;
  // If `true`, the current user is banned
  google.protobuf.BoolValue user_is_banned = 5;
  // If `true`, users are given the option to write a custom explanation when reporting content
  google.protobuf.BoolValue free_form_reports = 6;
  // URL to the custom icon as configured from www.reddit.com
  google.protobuf.StringValue community_icon = 7;
  // If `true`, show thumbnail images of content is enabled on old.reddit.com
  // @deprecated
  google.protobuf.BoolValue show_media = 8 [deprecated = true];
  // @deprecated
  google.protobuf.StringValue icon_color = 9 [deprecated = true];
  // Permanent identifier
  // @example "AskReddit"
  google.protobuf.StringValue display_name = 11;
  // URL to the custom header icon as configured from old.reddit.com
  // @deprecated
  google.protobuf.StringValue header_img = 12 [deprecated = true];
  // Current, editable name
  // @example "Ask Reddit Something"
  google.protobuf.StringValue title = 13;
  // Community coin balance
  google.protobuf.Int64Value coins = 14;
  // @deprecated
  repeated google.protobuf.StringValue previous_names = 15 [deprecated = true];
  // If `true`, this community contains content deemed not-safe-for-work (NSFW)
  google.protobuf.BoolValue over_18 = 16;
  // Resolution of icon_img
  // Format: [width, height]
  // @deprecated
  repeated google.protobuf.Int32Value icon_size = 17 [deprecated = true];
  // Theme base color as a # prefixed hex color, configured on www.reddit.com
  // @example "#FF4500"
  google.protobuf.StringValue primary_color = 18;
  // URL to the custom community icon as configured from old.reddit.com as the mobile icon image
  // Note: used as a fallback if community_icon_img is not set
  // @deprecated
  google.protobuf.StringValue icon_img = 19 [deprecated = true];
  // Sidebar description displayed on old.reddit.com
  // @deprecated
  google.protobuf.StringValue description = 20 [deprecated = true];
  // Custom label for the Submit Link button when viewed on old.reddit.com
  // @deprecated
  google.protobuf.StringValue submit_link_label = 21 [deprecated = true];
  // Resolution of header_img
  // Note: Incorrectly typed and unusable.
  // @deprecated
  google.protobuf.StringValue header_size = 22 [deprecated = true];
  // If `true`, crowd control is currently enabled
  google.protobuf.BoolValue restrict_commenting = 23;
  // Current count of subscribed users
  google.protobuf.Int64Value subscribers = 24;
  // Custom label for the Submit Text Post button when viewed on old.reddit.com
  // @deprecated
  google.protobuf.StringValue submit_text_label = 25;
  // If `true`, this Subreddit is using the default icon
  // @deprecated
  google.protobuf.BoolValue is_default_icon = 26 [deprecated = true];
  // Where flair should be shown relative to the Post title on old.reddit.com
  // One of: "left", "right", ""
  // @deprecated
  google.protobuf.StringValue link_flair_position = 27 [deprecated = true];
  // Permanent identifier with the leading "r/" prefix
  // @example "r/AskReddit"
  google.protobuf.StringValue display_name_prefixed = 28;
  // Mobile theme color as configured on old.reddit.com
  // @deprecated
  google.protobuf.StringValue key_color = 29 [deprecated = true];
  // Thing ID for this object
  // @example "t5_abc123"
  google.protobuf.StringValue name = 30;
  // If `true`, this Subreddit is using the default banner without customizing it
  google.protobuf.BoolValue is_default_banner = 31 [deprecated = true];
  // The path of this object relative to www.reddit.com
  // @example "/r/AskReddit/"
  google.protobuf.StringValue url = 32;
  // If `true`, this Subreddit has been put in quarantine for breaking site rules
  google.protobuf.BoolValue quarantine = 33;
  // Resolution of banner_img
  // Format: [width, height]
  // @deprecated
  repeated google.protobuf.Int32Value banner_size = 34 [deprecated = true];
  // If `true`, the current user is a moderator
  google.protobuf.BoolValue user_is_moderator = 35;
  // If `true`, users can join
  google.protobuf.BoolValue accept_followers = 36;
  // Plain text description
  google.protobuf.StringValue public_description = 37;
  // If `true`, Post Flair is enabled
  google.protobuf.BoolValue link_flair_enabled = 38;
  // If `true`, users may not request access to join
  google.protobuf.BoolValue disable_contributor_requests = 39;
  // One of: "public", "private", "restricted", "gold_only", "gold_restricted",
  //         "archived", "user", "employees_only"
  google.protobuf.StringValue subreddit_type = 40;
  // If `true`, the current user has joined
  google.protobuf.BoolValue user_is_subscriber = 41;
  // Pre-rendered HTML representing public_description
  google.protobuf.StringValue public_description_html = 42;
  // Thing ID without leading thing ID prefix
  // @example "abc123" // for: t5_abc123
  google.protobuf.StringValue id = 43;

  reserved 10; // prev: google.protobuf.StringValue user_is_muted = 10;
  // If `true`, the current user may not send messages to moderators
  bool user_is_muted = 44;

  // NEXT 45
}

message JsonStatus {
  message JsonErrorType {
    repeated google.protobuf.StringValue errors = 1;
  }
  JsonErrorType json = 4;
}

message WrappedUserObject {
  google.protobuf.StringValue id = 1;
  devvit.reddit.User data = 2;
}

extend google.protobuf.MethodOptions {
  ApiClientConfig api_client_config = 60001;
}

// Method extension for specifying how to call a Reddit API endpoint. These
// options are used for generating API client code.
message ApiClientConfig {
  // 'GET', 'POST', 'PUT', 'DELETE', etc.
  string method = 1;

  // The path of the API endpoint. Placeholders for variables MUST match names of fields in the input message.
  // For example:
  //   "/r/{subreddit}/api/delete_sr_img"
  // Only works if the input message has a string field named 'subreddit'.
  string path = 2;

  // For methods with a request body, this specifies how the request body should be serialized.
  enum BodyType {
    NONE = 0;
    JSON_CAMEL = 1;
    JSON_SNAKE = 2;
    FORM_CAMEL = 3;
    FORM_SNAKE = 4;
  }
  BodyType request_body_type = 3;

  // If set to true, the parameter `api_type=json` will be sent to the reddit API with this request.
  // Note: in the current implementation, this only works for bodyType=FORM_SNAKE.
  bool enforce_json = 4;

  // Some requests involve sending a specific `kind` field that's not otherwise part of the
  // request message. If this field is specified, that will be included in the request.
  string request_kind_value = 5;

  // If set, the thing specified in the input message's field specified by `validate_content_id_context`
  // must belong to the subreddit in the call's metadata before the call is allowed to proceed.
  //
  // For example, setting:
  //  option (devvit.plugin.redditapi.common.api_client_config).validate_content_id_context = 'id';
  // will test that the input message's `id` field contains a thing (post/comment) that belongs
  // to the subreddit in the call's metadata.
  string validate_content_id_context = 6;

  // If set, the subreddit specified in the input message's field specified by `validate_subreddit_context`
  // must match the subreddit in the call's metadata before the call is allowed to proceed.
  //
  // For example, setting:
  //  option (devvit.plugin.redditapi.common.api_client_config).validate_subreddit_context = 'subreddit';
  // will test that the input message's `subreddit` field contains a subreddit *name* matches the subreddit
  // in the call's metadata.
  string validate_subreddit_context = 7;

  // If set, the generated code should invoke the specified method to parse the response, rather
  // than using the default protojson rehydration.
  // The method specified signature looks like:
  //   func fixMethodNameResponse([]bytes) (*ResponseType, error)
  bool use_custom_response_parser = 8;

  // For methods that accept a `run_as` field, this specifies the scopes that the user must authorize
  // in order to call the method with runAs="USER".
  repeated .reddit.devvit.app_permission.v1.Scope run_as_user_scopes = 9;

  // For methods that implicitly run as user.
  bool always_run_as_user = 10;
}

// Indicates who the request should be made on behalf of. Currently, only 'APP' or 'USER' types are supported.
enum RunAs {
  APP = 0;
  USER = 1;
  UNSPECIFIED = 2;
}

// Represents data on the user's content submission
message UserGeneratedContent {
  // The text body of the content
  string text = 1;
  // The imageUrls attached to the content, if any
  repeated string image_urls = 2;
}

enum GalleryMediaStatus {
  GALLERY_MEDIA_STATUS_UNSPECIFIED = 0;
  GALLERY_MEDIA_STATUS_VALID = 1;
  GALLERY_MEDIA_STATUS_FAILED = 2;
}
