syntax = "proto3";

package code.justin.tv.commerce.mako;
option go_package = "mako-client";

import "google/protobuf/timestamp.proto";

service Mako {

    // Get Entitlements for a user. Results can be filtered with an EntitlementScopedKey
    rpc GetEntitlements(GetEntitlementsRequest) returns (GetEntitlementsResponse);

    // Set Entitlement for a user.
    rpc SetEntitlement(SetEntitlementRequest) returns (SetEntitlementResponse);

    // Delete Entitlements for a user.
    rpc DeleteEntitlements(DeleteEntitlementsRequest) returns (DeleteEntitlementsResponse);

    // Get the emote set details for a given user.
    rpc GetEmoteSetDetails(GetEmoteSetDetailsRequest) returns (GetEmoteSetDetailsResponse);

    // Get the emoticon group details for the given emoticon groups
    rpc GetEmoticonsByGroups(GetEmoticonsByGroupsRequest) returns (GetEmoticonsByGroupsResponse);

    // Get the emoticon details for the given emoticon ids
    rpc GetEmoticonsByEmoticonIds(GetEmoticonsByEmoticonIdsRequest) returns (GetEmoticonsByEmoticonIdsResponse);

    // Get all emotes for the given channel id
    rpc GetAllEmotesByOwnerId(GetAllEmotesByOwnerIdRequest) returns (GetAllEmotesByOwnerIdResponse);

    // Get all emotes including emote modifications for the given owner id
    rpc GetAllEmotesWithModificationsByOwnerID(GetAllEmotesWithModificationsByOwnerIDRequest) returns (GetAllEmotesWithModificationsByOwnerIDResponse);

    // Get all emotes for a user and group them by ownerID and then by emote groups
    rpc GetEmoticonsForEmotePicker(GetEmoticonsForEmotePickerRequest) returns (GetEmoticonsForEmotePickerResponse);

    // Get all emotes that a user is entitled to given a set of emote codes.
    rpc GetEmotesByCodes(GetEmotesByCodesRequest) returns (GetEmotesByCodesResponse);

    // Get active emote codes for a given user.
    rpc GetActiveEmoteCodes(GetActiveEmoteCodesRequest) returns (GetActiveEmoteCodesResponse);

    // Get emoticon image/upload id and url.
    rpc GetEmoticonUploadConfiguration(GetEmoticonUploadConfigurationRequest) returns (GetEmoticonUploadConfigurationResponse);

    // Get emote entitlements from Materia.
    rpc GetEmoteEntitlements(GetEmoteEntitlementsRequest) returns (GetEmoteEntitlementsResponse);

    // Entitle single emotes.
    rpc CreateEmoteEntitlements(CreateEmoteEntitlementsRequest) returns (CreateEmoteEntitlementsResponse);

    // Entitle emote groups (emote slots, groups of emotes, etc).
    rpc CreateEmoteGroupEntitlements(CreateEmoteGroupEntitlementsRequest) returns (CreateEmoteGroupEntitlementsResponse);

    // Delete entitlements
    rpc DeleteEmoteGroupEntitlements(DeleteEmoteGroupEntitlementsRequest) returns (DeleteEmoteGroupEntitlementsResponse);

    // Create emoticon given 3 image IDs and emoticon info.
    rpc CreateEmoticon(CreateEmoticonRequest) returns (CreateEmoticonReponse);

    // Delete emoticon given id, code, and option to delete assets images from S3. Images are used for VOD Chat. Set true if ABSOLUTELY want to nuke emoticon.
    rpc DeleteEmoticon(DeleteEmoticonRequest) returns (DeleteEmoticonResponse);

    // Deactivate emoticon given id
    rpc DeactivateEmoticon(DeactivateEmoticonRequest) returns (DeactivateEmoticonResponse);

    // Update the specified emote's code suffix
    rpc UpdateEmoteCodeSuffix(UpdateEmoteCodeSuffixRequest) returns (UpdateEmoteCodeSuffixResponse);

    // Get the selected smilies set and emoticon info.
    rpc GetSelectedSmilies(GetSelectedSmiliesRequest) returns (GetSelectedSmiliesResponse);

    // Get all of the smilies sets and emoticon info.
    rpc GetAllSmilies(GetAllSmiliesRequest) returns (GetAllSmiliesResponse);

    //Set the selected smilies set and emoticon info.
    rpc SetSmilies(SetSmiliesRequest) returns (SetSmiliesResponse);

    // Emote Modifiers Endpoints:
    //
    // These are used to manage the content of the emote_modifier_groups table in Mako. This table is where
    // broadcaster's settings about what modifiers they have enabled on their channel are stored.
    // There may be more than one Emote Modifier Group per channel.
    rpc CreateEmoteModifierGroups(CreateEmoteModifierGroupsRequest) returns (CreateEmoteModifierGroupsResponse);
    rpc UpdateEmoteModifierGroups(UpdateEmoteModifierGroupsRequest) returns (UpdateEmoteModifierGroupsResponse);
    rpc GetEmoteModifierGroups(GetEmoteModifierGroupsRequest) returns (GetEmoteModifierGroupsResponse);
    rpc DeleteEmoteModifierGroups(DeleteEmoteModifierGroupsRequest) returns (DeleteEmoteModifierGroupsResponse);

    // (Emote/Cheermote) Prefix Endpoints

    // Set a prefix for a channel.
    rpc SetPrefix(SetPrefixRequest) returns (SetPrefixResponse);

    // Get a prefix for a channel
    rpc GetPrefix(GetPrefixRequest) returns (GetPrefixResponse);

    // Get prefixes by state
    rpc GetPrefixesByState(GetPrefixesByStateRequest) returns (GetPrefixesByStateResponse);

    // Generates a recommended prefix for the channel based on a very simple set of rules
    rpc GetRecommendedPrefix(GetRecommendedPrefixRequest) returns (GetRecommendedPrefixResponse);

    // Submit a user initiated prefix change. Checks if the user is allowed to change their prefix
    rpc SubmitPrefix(SubmitPrefixRequest) returns (SubmitPrefixResponse);

    // Pending emotes

    // GetPendingEmoticonByID returns a particular pending emoticon for use in the aegis GQL loader
    rpc GetPendingEmoticonsByIDs (GetPendingEmoticonsByIDsRequest) returns (GetPendingEmoticonsByIDsResponse);

    // GetPendingEmoticons returns an array of pending emoticons for the moderation team's approval flow.
    rpc GetPendingEmoticons (GetPendingEmoticonsRequest) returns (GetPendingEmoticonsResponse);

    // ReviewPendingEmoticons accepts an array of approve or reject actions and either approves or rejects each emoticon
    rpc ReviewPendingEmoticons (ReviewPendingEmoticonsRequest) returns (ReviewPendingEmoticonsResponse);

    // DeferPendingEmoticons marks a list of pending emoticons' review states as "deferred".
    rpc DeferPendingEmoticons (DeferPendingEmoticonsRequest) returns (DeferPendingEmoticonsResponse) ;

    // CreatePendingEmoticon creates a pending emoticon.
    rpc CreatePendingEmoticon (CreatePendingEmoticonRequest) returns (CreatePendingEmoticonResponse);

    // DeletePendingEmoticons deletes a list of pending emoticons.
    rpc DeletePendingEmoticons (DeletePendingEmoticonsRequest) returns (DeletePendingEmoticonsResponse);

    // CreateEmoteGroup creates an emote group and returns its ID.
    rpc CreateEmoteGroup (CreateEmoteGroupRequest) returns (CreateEmoteGroupResponse);

    // Legacy Emoticon Endpoints

    // Returns S3 URLs to the emoticon all payloads for the legacy kraken endpoints.
    rpc GetLegacyEmoticonAllURLs(GetLegacyEmoticonAllURLsRequest) returns (GetLegacyEmoticonAllURLsResponse);

    // Represents the kraken/chat/:channel_name/emoticons API which return channel and global emoticons
    // based upon channel_name.
    rpc GetLegacyChannelEmoticons(GetLegacyChannelEmoticonsRequest) returns (GetLegacyChannelEmoticonsResponse);

    // Given a list of emote codes, BatchValidateCodeUniqueness returns a map indicating whether the codes are unique
    // to all existing emotes of the given emote filter.
    rpc BatchValidateCodeUniqueness(BatchValidateCodeUniquenessRequest) returns (BatchValidateCodeUniquenessResponse);
}

// Request/Response Types

message GetEmotesByCodesRequest {
    string owner_id = 1;
    repeated string codes = 2;
}

message GetEmotesByCodesResponse {
    repeated Emoticon emoticons = 1;
}

message GetEntitlementsRequest {
    string user_id = 1; // Required
    ScopedKey entitlement_scoped_key = 2; // Optional
    bool is_staff = 3; // Optional. True if the passed-in user is a Twitch Staff account, false otherwise.
}

message GetSelectedSmiliesRequest {
    string user_id = 1; // Required
}

message GetSelectedSmiliesResponse {
    SmiliesSetId smilies_set_id = 1;
}

message GetAllSmiliesRequest {
}

message GetAllSmiliesResponse {
    repeated SmiliesSet smiliesSets = 1;
}

message SetSmiliesRequest {
    string user_id = 1; // Required
    SmiliesSetId smilies_set_id = 2; // Required
}

message SetSmiliesResponse {
    SmiliesSetId smilies_set_id = 1;
}

message GetEntitlementsResponse {
    repeated Entitlement entitlements = 1;
}

message SetEntitlementRequest {
    Entitlement entitlement = 1; // Required
}

message SetEntitlementResponse {
    Entitlement entitlement = 1;
}

message DeleteEntitlementsRequest {
    repeated Entitlement entitlements = 1; // Required
}

message DeleteEntitlementsResponse {
    repeated Entitlement entitlements = 1;
}

message GetEmoteSetDetailsRequest {
    string user_id = 1; // Required
    // Temporary field for the Octane project that is used to verify that entitlements are correctly
    // returned via Materia instead of SiteDB.
    // TODO: https://jira.twitch.com/browse/SUBS-4860
    bool skip_sitedb = 2;
}

message GetEmoteSetDetailsResponse {
    repeated EmoteSet emote_sets = 1;
}

message GetEmoticonsByGroupsRequest {
    repeated string emoticon_group_keys = 1;
    EmoteFilter filter = 2;
}

message GetEmoticonsByGroupsResponse {
    repeated EmoticonGroup groups = 1;
}

message GetEmoticonsByEmoticonIdsRequest {
    repeated string emoticon_ids = 1;
}

message GetEmoticonsByEmoticonIdsResponse {
    repeated Emoticon emoticons = 1;
}

message EmoteFilter {
    Domain domain = 2;
    repeated EmoteState states = 3;
}

message GetAllEmotesByOwnerIdRequest {
    string owner_id = 1;
    EmoteFilter filter = 2;
}

message GetAllEmotesByOwnerIdResponse {
    repeated Emoticon emoticons = 1;
}

message GetAllEmotesWithModificationsByOwnerIDRequest {
    string owner_id = 1;
}

message GetAllEmotesWithModificationsByOwnerIDResponse {
    repeated EmoteModificationGroup emote_groups = 1;
}

message GetEmoticonsForEmotePickerRequest {
    string user_id = 1; // Optional. Logged out users won't have a user_id in their request
}

message GetEmoticonsForEmotePickerResponse {
    repeated EmoticonDisplayGroup emoticon_groups = 1;
}

message GetActiveEmoteCodesRequest {
    string user_id = 1; // Required
    Domain domain = 2;
}

message GetActiveEmoteCodesResponse {
    map<string, EmoteDetails> codes = 1;
    Domain domain = 2;
}

message GetEmoticonUploadConfigurationRequest {
    string user_id = 1;
    int32 image_width = 2;
    int32 image_height = 3;
    string code = 4;
    string sns_callback_topic = 5;
    string group_id = 6;
}

message GetEmoticonUploadConfigurationResponse {
    string upload_id = 1;
    string upload_url = 2;
    string image_id = 3;
    string image_url = 4;
}

message CreateEmoticonRequest {
    string user_id = 1;
    string code = 2;
    string code_suffix = 3;
    string state = 4;
    string group_id = 5;
    string image28_id = 6;
    string image56_id = 7;
    string image112_id = 8;
    string domain = 9;
    // TODO: There is an inverse relationship between @ryanresi's happiness and how long we let emote_group
    // live alongside (the in no way related) group_id. We should change emote_group to be something like emote_type.
    EmoteGroup emote_group = 10;
    // Set this to true if you want Mako to determine initial emote state, based on the logic below:
    // (Partner OR Affiliate) AND inGoodStanding -> Active
    // Otherwise -> Pending and added to the moderation queue
    bool enforce_moderation_workflow = 11;
}

message CreateEmoticonReponse {
    string id = 1;
    string code = 2;
    string group_id = 3;
    string state = 4;
}

message DeleteEmoticonRequest {
    string id = 1;
    string code = 2 [deprecated = true];
    bool deleteImages = 3;
    EmoteGroup emote_group = 4 [deprecated = true];
    bool requires_permitted_user = 5;
    string user_id = 6;
}

message DeleteEmoticonResponse {
}

message DeactivateEmoticonRequest {
    string id = 1;
}

message DeactivateEmoticonResponse {}

message UpdateEmoteCodeSuffixRequest {
    string id = 1;
    string code_suffix = 2;
}

message UpdateEmoteCodeSuffixResponse {}

message GetEmoteEntitlementsRequest {
    // REQUIRED: owner_id is the Twitch user id who owns the entitlement.
    string owner_id = 1;
    // OPTIONAL: item_id is the id of the emote or emote_set the user is entitled to.
    string item_id = 2;
    // OPTIONAL: origin_id represents how the entitlement was created, for example through a purchase order id.
    string origin_id = 4;
    // OPTIONAL: group represents the type of emote group (i.e. Materia's source)
    EmoteGroup group = 5;
}

message GetEmoteEntitlementsResponse {
    repeated EmoteEntitlement entitlements = 1;
}

message CreateEmoteEntitlementsRequest {
    repeated EmoteEntitlement entitlements = 1;
}

message CreateEmoteEntitlementsResponse {}

message CreateEmoteGroupEntitlementsRequest {
    repeated EmoteGroupEntitlement entitlements = 1;
}

message CreateEmoteGroupEntitlementsResponse {}

message DeleteEmoteGroupEntitlementsRequest {
    repeated EmoteGroupEntitlement entitlements = 1;
}

message DeleteEmoteGroupEntitlementsResponse {}

message BatchValidateCodeUniquenessRequest {
    repeated string emote_codes = 1;
    EmoteFilter filter = 2;
}

message BatchValidateCodeUniquenessResponse {
    map<string, bool> is_unique = 1;
}

// Data Types

// Lookup identifier used across Mako. The scope and key are used together
// to identify various resources such as events and entitlements.
message ScopedKey {
    string scope = 1; // e.g. "/my/scope/"
    string key = 2; // e.g. "mykey"
}

// An Entitlement represents a user "being entitled to" something.
// For example in plain english, "user 123 is entitled to emote set 456".
message Entitlement {
    string user_id = 1;
    ScopedKey scoped_key = 2;
    string origin = 3;
}

// Deprecated.  Use EmoticonGroup for future APIs
// An Emote Set contains a list of emotes tied to that emote set
message EmoteSet {
    string id = 1;
    repeated Emote emotes = 2;
    string channel_id = 3;
}

// An Emoticon Group contains a list of emoticons tied to that emoticon set
message EmoticonGroup {
    string id = 1;
    repeated Emoticon emoticons = 2;
}

// A Smilies Set contains a set id along with the emoticon group contained in it
message SmiliesSet {
    SmiliesSetId smilies_set_id = 1;
    repeated Emoticon emoticons = 2;
}

enum SmiliesSetId {
    NONE = 0; // Indicates missing argument
    ROBOTS = 1; // default smilies set
    PURPLE = 2;
    MONKEYS = 3;
}

// Deprecated.  Use Emoticon for future APIs
// An emote has an identifier and a regex pattern used in clients
message Emote {
    string id = 1;
    string pattern = 2;
    repeated Modification modifiers = 3;
}

// An emoticon has an identifier and a code used in clients
message Emoticon {
    string id = 1;
    string code = 2;
    string group_id = 3;
    string owner_id = 4;
    string product_id = 5;
    EmoteState state = 6;
    Domain domain = 7;
    string suffix = 8;
}

// An emote detail contains an emote identifier and associated group ID
message EmoteDetails {
    string id = 1;
    string group_id = 2;
}

message SetPrefixRequest {
    string channel_id = 1;
    string prefix = 2;
    PrefixState state = 3;
}

message SetPrefixResponse {

}

message GetPrefixRequest {
    string channel_id = 1;
}

message GetPrefixResponse {
    string prefix = 1;
    PrefixState state = 2;
    bool is_editable = 3;
}

message GetPrefixesByStateRequest {
    PrefixState state = 1;
    int32 limit = 2;
}

message GetPrefixesByStateResponse {
    repeated PrefixEntry prefix_entries = 1;
}

message PrefixEntry {
    string channel_id = 1;
    string prefix = 2;
    PrefixState state = 3;
}

enum PrefixState {
    PREFIX_STATE_UNKNOWN = 0;
    PREFIX_UNSET = 1;
    PREFIX_ACTIVE = 2;
    PREFIX_REJECTED = 3;
    PREFIX_PENDING = 4;
}

message SubmitPrefixRequest {
    string channel_id = 1;
    string prefix = 2;
}

message SubmitPrefixResponse {}

message GetRecommendedPrefixRequest {
    string channel_id = 1;
}

message GetRecommendedPrefixResponse {
    string prefix = 1;
}

// NOTE: This object is separate and distinct from the Emote Modifier Groups in the emote_modifier_groups table in Dynamo.
// This object powers the GetAllEmotesWithModifiers API that chat uses to power the CoPo modifiers display.
// The name of this unfortunately collides with the name of the new emote_modifier_groups table :cclamrip:
message EmoteModificationGroup {
    Modification modification = 1;
    repeated EmoteWithModified emotes = 2;
}

message EmoteWithModified{
    Emoticon base_emote = 1;
    ModifiedEmote modified_emote = 2;
}

message ModifiedEmote {
    string id = 1;
    string code = 2;
}

enum Modification {
    ModificationNone = 0;
    BlackWhite = 1;
    HorizontalFlip = 2;
    Sunglasses = 3;
    Thinking = 4;
    Squished = 5;
    Pumpkin = 6;
    Reindeer = 7;
    Santa = 8;
    RedEnvelope = 9;
    LunarRat = 10;
    HeartEyes = 11;
    KissImprint = 12;
    HeartBroken = 13;
    Beard = 14;
    LuckyHat = 15;
    CloverEyes = 16;
    WomensDay = 17;
    RosieBandana = 18;
}

// Emote Modifier Groups
// ---------------------
// NOTE: This object represents the Emote Modifier Groups in the emote_modifier_groups table in Dynamo.
// The table is used to hold the source of truth for what emote modifications a broacaster has enabled on their channel.
message EmoteModifierGroup {
    // ID must be omitted for Create requests, and must be included for Update requests
    string id = 1;
    string owner_id = 2;
    repeated Modification modifiers = 3;
    repeated string benefit_set_ids = 4;
}

message CreateEmoteModifierGroupsRequest {
    repeated EmoteModifierGroup groups = 1;
}

message CreateEmoteModifierGroupsResponse {
    repeated EmoteModifierGroup groups = 1;
}

message UpdateEmoteModifierGroupsRequest {
    repeated EmoteModifierGroup groups = 1;
}

message UpdateEmoteModifierGroupsResponse {
    repeated EmoteModifierGroup groups = 1;
}

message GetEmoteModifierGroupsRequest {
    repeated string modifier_group_ids = 1;
}

message GetEmoteModifierGroupsResponse {
    repeated EmoteModifierGroup groups = 1;
}

message DeleteEmoteModifierGroupsRequest {
    repeated string modifier_group_ids = 1;
}

message DeleteEmoteModifierGroupsResponse {
}

message EmoteEntitlement {
    string owner_id = 1;
    string emote_id = 2;
    string origin_id = 3;
    EmoteGroup group = 4;
    google.protobuf.Timestamp start = 5;
    InfiniteTime end = 6;
    string item_owner_id = 7; // OPTIONAL
}

message EmoteGroupEntitlement {
    // owner_id represents who is entitled to the emote group.
    string owner_id = 1;
    // item_id represents who owns the emote group. It's required to be passed in by the requester
    // because the group may exist but have no emotes yet.
    string item_id = 2;
    // group_id represents the emote group to entitle.
    string group_id = 3;
    // origin_id represents how the entitlement was created, for example through a purchase order id.
    string origin_id = 4;
    // group represents the type of emote group.
    EmoteGroup group = 5;
    google.protobuf.Timestamp start = 6;
    InfiniteTime end = 7;
}

// An emoticon display group in the Emote Picker. (e.g. emotes for Mr_Woodchuck's channel, or all global emotes, etc)
message EmoticonDisplayGroup {
    string display_group_id = 1; //A way of tying multiple emote groups from various products into one grouping
    int32 display_group_order = 2; //A way of ordering the groups (e.g. current channel, other channels, prime, globals)
    repeated EmoticonDisplaySubgroup display_subgroups = 3;
}

// An emoticon display subgroup in the Emote Picker. (e.g. Mr_Woodchuck's subscription emoticons, Mr_Woodchuck's bits badge
// tier emoticons, Mr_Woodchucks channel points emoticons, etc)
message EmoticonDisplaySubgroup {
    string display_subgroup_id = 1; //A way of tying multiple emotes or emote slots from various sets into one grouping
    int32 display_subgroup_order = 2; //A way of ordering the subgroups (subs first, bits second, etc)
    EmoteGroup group = 3; //A way of telling what type of emote this subgroup holds (e.g. Subs, Bits, Channel Points)
    repeated EmoticonGroup emotes = 4;
}

// Legacy Emoticon Data Types
message GetLegacyEmoticonAllURLsRequest {}

message GetLegacyEmoticonAllURLsResponse {
    string emoticons_url = 1;
    string emoticon_images_url = 2;
    string emoticon_images_all_url = 3;
}

message GetLegacyChannelEmoticonsRequest {
    string channel_id = 1;
    string channel_name = 2;
}

message GetLegacyChannelEmoticonsResponse {
    Links _links = 1;
    repeated LegacyChannelEmoticonsEmoticon emoticons = 2;
}

message LegacyChannelEmoticonsEmoticon {
    string regex = 1;
    string state = 2;
    bool subscriber_only = 3;
    string url = 4;
    int32 height = 5;
    int32 width = 6;
}

message Links {
    string self = 1;
}

enum Domain {
    Emotes = 0;
    Stickers = 1;
}

enum EmoteState {
    Active = 0;
    Inactive = 1;
    Moderated = 2;
    Pending = 3;
    Archived = 4;
}

enum EmoteGroup {
    None = 0;
    ChannelPoints = 1;
    BitsBadgeTierEmotes = 2;
    Subscriptions = 3;
    Rewards = 4;
    HypeTrain = 5;
    Prime = 6;
    Turbo = 7;
    Smilies = 8;
    Globals = 9;
}

// InfiniteTime is a timestamp that can be either a specific time or an infinite date in the future.
// If is_infinite is true, then time will be nil and should not be used.
message InfiniteTime {
    // The time of the event, if is_infinite is false. WILL BE NIL IF is_infinite IS TRUE.
    google.protobuf.Timestamp time = 1;


    // If is_infinite is true then the date is an infinite time in the future.
    // is_infinite is used to represent entitlements that last forever.
    bool is_infinite = 2;
}

// Group Management
// =========
message CreateEmoteGroupRequest {
}

message CreateEmoteGroupResponse {
    string group_id = 1;
}

// Pending Emoticons
// =========
message GetPendingEmoticonsByIDsRequest {
    repeated string emoticon_ids = 1;
}

message GetPendingEmoticonsByIDsResponse {
    repeated PendingEmoticon emoticons = 1;
}

// GetPendingEmoticonsRequest
message GetPendingEmoticonsRequest {
    EmoticonFilter filter = 1;
    int32 count = 2; // Defaults to 25 - must be > 0
    EmoticonBucket bucket = 3;
    google.protobuf.Timestamp after_timestamp = 4;
    PendingEmoticonReviewStateFilter review_state_filter = 5;
}

// GetPendingEmoticonsResponse
message GetPendingEmoticonsResponse {
    repeated PendingEmoticon emoticons = 1;
    int32 total_count = 2;
}

message ReviewPendingEmoticonsRequest {
    repeated ReviewPendingEmoticonRequest reviews = 1;
    string admin_id = 2; // The LDAP ID of the admin who took this action
}

message ReviewPendingEmoticonRequest {
    string id = 1;
    bool approve = 2;
    string decline_reason = 3; // One of a set of well-known decline reasons
    string decline_explanation = 4; // A more descriptive explanation written by the admin
}

message ReviewPendingEmoticonsResponse {
    repeated ReviewPendingEmoticonResponse results = 1;
}

message ReviewPendingEmoticonResponse {
    string id = 1;
    bool succeeded = 2;
    string new_status = 3;
}

message DeferPendingEmoticonsRequest {
    repeated string emoticon_ids = 1;
    string admin_id = 2; // The LDAP ID of the admin who took this action
}

message DeferPendingEmoticonsResponse {
    repeated DeferPendingEmoticonsResult results = 1;
}

message DeferPendingEmoticonsResult {
    string emoticon_id = 1;
    bool succeeded = 2;
}

message CreatePendingEmoticonRequest {
    string id = 1;
    string prefix = 2;
    string code = 3;
    string owner_id = 4;
    AccountType account_type = 5;
}

message CreatePendingEmoticonResponse {
    PendingEmoticon pending_emoticon = 1;
}

message DeletePendingEmoticonsRequest {
    repeated string emoticon_ids = 1;
}

message DeletePendingEmoticonsResponse {
}

message EmoticonBucket {
    int32 requested = 1;
    int32 bucket_count = 2;
}

enum EmoticonFilter {
    EmoticonFilter_All = 0;
    EmoticonFilter_Partner = 1;
    EmoticonFilter_Affiliate = 2;
}

enum PendingEmoticonReviewStateFilter {
    // Filter to get both deferred and non-deferred pending emoticons
    PendingEmoticonReviewStateFilter_All = 0;
    // Filter to get non-deferred pending emoticons
    PendingEmoticonReviewStateFilter_None = 1;
    // Filter to get deferred pending emoticons
    PendingEmoticonReviewStateFilter_Deferred = 2;
}

// PendingEmoticon contains all the data necessary for Moderation to view and judge an emoticon
message PendingEmoticon {
    string id = 1;
    string prefix = 2;
    string code = 3;
    string owner_id = 4;
    google.protobuf.Timestamp upload_time = 5;
    AccountType account_type = 6;
}

enum AccountType {
    Partner = 0;
    Affiliate = 1;
}
