mirror of
https://github.com/discordeno/discordeno.git
synced 2026-05-21 02:40:08 +00:00
Use Partial<T> in user transformers
- Add transformUser overloads - Use `typeof` of the transformers in `transformers.ts` to avoid the unions for the partial functions - Join the imports for the transformers in `transformers.ts`
This commit is contained in:
@@ -1,9 +1,5 @@
|
||||
import type {
|
||||
AllowedMentions,
|
||||
BigString,
|
||||
CreateApplicationCommand,
|
||||
DiscordActivity,
|
||||
DiscordAllowedMentions,
|
||||
DiscordApplication,
|
||||
DiscordApplicationCommand,
|
||||
DiscordApplicationCommandOption,
|
||||
@@ -14,7 +10,6 @@ import type {
|
||||
DiscordAutoModerationRule,
|
||||
DiscordAvatarDecorationData,
|
||||
DiscordChannel,
|
||||
DiscordCreateApplicationCommand,
|
||||
DiscordEmbed,
|
||||
DiscordEmoji,
|
||||
DiscordEntitlement,
|
||||
@@ -54,78 +49,119 @@ import type {
|
||||
} from '@discordeno/types'
|
||||
import { logger } from '@discordeno/utils'
|
||||
import { bigintToSnowflake, snowflakeToBigint, type Bot } from './index.js'
|
||||
import { transformActivity, type Activity } from './transformers/activity.js'
|
||||
import { transformApplication, type Application } from './transformers/application.js'
|
||||
import { transformApplicationCommand, type ApplicationCommand } from './transformers/applicationCommand.js'
|
||||
import { transformApplicationCommandOption, type ApplicationCommandOption } from './transformers/applicationCommandOption.js'
|
||||
import { transformApplicationCommandOptionChoice, type ApplicationCommandOptionChoice } from './transformers/applicationCommandOptionChoice.js'
|
||||
import { transformApplicationCommandPermission, type ApplicationCommandPermission } from './transformers/applicationCommandPermission.js'
|
||||
import { transformAttachment, type Attachment } from './transformers/attachment.js'
|
||||
import { transformAuditLogEntry, type AuditLogEntry } from './transformers/auditLogEntry.js'
|
||||
import { transformAutoModerationActionExecution, type AutoModerationActionExecution } from './transformers/automodActionExecution.js'
|
||||
import { transformAutoModerationRule, type AutoModerationRule } from './transformers/automodRule.js'
|
||||
import { transformChannel, type Channel } from './transformers/channel.js'
|
||||
import { transformComponent, type Component } from './transformers/component.js'
|
||||
import { transformEmbed, type Embed } from './transformers/embed.js'
|
||||
import { transformEmoji, type Emoji } from './transformers/emoji.js'
|
||||
import { transformEntitlement, type Entitlement } from './transformers/entitlement.js'
|
||||
import { transformGatewayBot, type GetGatewayBot } from './transformers/gatewayBot.js'
|
||||
import { transformGuild, type Guild } from './transformers/guild.js'
|
||||
import {
|
||||
transformActivity,
|
||||
transformActivityToDiscordActivity,
|
||||
transformAllowedMentionsToDiscordAllowedMentions,
|
||||
transformApplication,
|
||||
transformApplicationCommand,
|
||||
transformApplicationCommandOption,
|
||||
transformApplicationCommandOptionChoice,
|
||||
transformApplicationCommandOptionChoiceToDiscordApplicationCommandOptionChoice,
|
||||
transformApplicationCommandOptionToDiscordApplicationCommandOption,
|
||||
transformApplicationCommandPermission,
|
||||
transformApplicationCommandToDiscordApplicationCommand,
|
||||
transformApplicationToDiscordApplication,
|
||||
transformAttachment,
|
||||
transformAttachmentToDiscordAttachment,
|
||||
transformAuditLogEntry,
|
||||
transformAutoModerationActionExecution,
|
||||
transformAutoModerationRule,
|
||||
transformAvatarDecorationData,
|
||||
transformChannel,
|
||||
transformComponent,
|
||||
transformComponentToDiscordComponent,
|
||||
transformCreateApplicationCommandToDiscordCreateApplicationCommand,
|
||||
transformEmbed,
|
||||
transformEmbedToDiscordEmbed,
|
||||
transformEmoji,
|
||||
transformEntitlement,
|
||||
transformGatewayBot,
|
||||
transformGuild,
|
||||
transformGuildOnboarding,
|
||||
transformIntegration,
|
||||
transformInteraction,
|
||||
transformInteractionDataOption,
|
||||
transformInteractionResponseToDiscordInteractionResponse,
|
||||
transformInvite,
|
||||
transformInviteStageInstance,
|
||||
transformMember,
|
||||
transformMemberToDiscordMember,
|
||||
transformTeamToDiscordTeam,
|
||||
transformUserToDiscordUser,
|
||||
type AvatarDecorationData,
|
||||
} from './transformers/index.js'
|
||||
import { transformIntegration, type Integration } from './transformers/integration.js'
|
||||
import { transformInteraction, transformInteractionDataOption, type Interaction, type InteractionDataOption } from './transformers/interaction.js'
|
||||
import { transformInvite, type Invite } from './transformers/invite.js'
|
||||
import { transformMember, type Member } from './transformers/member.js'
|
||||
import {
|
||||
transformMessage,
|
||||
transformMessageCall,
|
||||
transformMessageInteractionMetadata,
|
||||
transformPoll,
|
||||
transformPollMedia,
|
||||
transformPresence,
|
||||
transformRole,
|
||||
transformScheduledEvent,
|
||||
transformSku,
|
||||
transformStageInstance,
|
||||
transformSticker,
|
||||
transformStickerPack,
|
||||
transformTeam,
|
||||
transformTeamToDiscordTeam,
|
||||
transformTemplate,
|
||||
transformThreadMember,
|
||||
transformThreadMemberGuildCreate,
|
||||
transformUser,
|
||||
transformUserToDiscordUser,
|
||||
transformVoiceRegion,
|
||||
transformVoiceState,
|
||||
transformWebhook,
|
||||
transformWelcomeScreen,
|
||||
transformWidget,
|
||||
transformWidgetSettings,
|
||||
type Activity,
|
||||
type Application,
|
||||
type ApplicationCommand,
|
||||
type ApplicationCommandOption,
|
||||
type ApplicationCommandOptionChoice,
|
||||
type ApplicationCommandPermission,
|
||||
type Attachment,
|
||||
type AuditLogEntry,
|
||||
type AutoModerationActionExecution,
|
||||
type AutoModerationRule,
|
||||
type AvatarDecorationData,
|
||||
type Channel,
|
||||
type Component,
|
||||
type Embed,
|
||||
type Emoji,
|
||||
type Entitlement,
|
||||
type GetGatewayBot,
|
||||
type Guild,
|
||||
type GuildOnboarding,
|
||||
type GuildWidget,
|
||||
type GuildWidgetSettings,
|
||||
type Integration,
|
||||
type Interaction,
|
||||
type InteractionDataOption,
|
||||
type Invite,
|
||||
type InviteStageInstance,
|
||||
type Member,
|
||||
type Message,
|
||||
type MessageCall,
|
||||
type MessageInteractionMetadata,
|
||||
} from './transformers/message.js'
|
||||
import { transformGuildOnboarding, type GuildOnboarding } from './transformers/onboarding.js'
|
||||
import { transformPoll, transformPollMedia, type Poll, type PollMedia } from './transformers/poll.js'
|
||||
import { transformPresence, type PresenceUpdate } from './transformers/presence.js'
|
||||
import { transformAllowedMentionsToDiscordAllowedMentions } from './transformers/reverse/allowedMentions.js'
|
||||
import { transformCreateApplicationCommandToDiscordCreateApplicationCommand } from './transformers/reverse/createApplicationCommand.js'
|
||||
import { transformInteractionResponseToDiscordInteractionResponse } from './transformers/reverse/interactionResponse.js'
|
||||
import { transformRole, type Role } from './transformers/role.js'
|
||||
import { transformScheduledEvent, type ScheduledEvent } from './transformers/scheduledEvent.js'
|
||||
import { transformSku, type Sku } from './transformers/sku.js'
|
||||
import { transformStageInstance, type StageInstance } from './transformers/stageInstance.js'
|
||||
import { transformInviteStageInstance, type InviteStageInstance } from './transformers/stageInviteInstance.js'
|
||||
import { transformSticker, transformStickerPack, type Sticker, type StickerPack } from './transformers/sticker.js'
|
||||
import { transformTeam, type Team } from './transformers/team.js'
|
||||
import { transformTemplate, type Template } from './transformers/template.js'
|
||||
import {
|
||||
transformThreadMember,
|
||||
transformThreadMemberGuildCreate,
|
||||
type Poll,
|
||||
type PollMedia,
|
||||
type PresenceUpdate,
|
||||
type Role,
|
||||
type ScheduledEvent,
|
||||
type Sku,
|
||||
type StageInstance,
|
||||
type Sticker,
|
||||
type StickerPack,
|
||||
type Team,
|
||||
type Template,
|
||||
type ThreadMember,
|
||||
type ThreadMemberGuildCreate,
|
||||
} from './transformers/threadMember.js'
|
||||
import { transformUser, type User } from './transformers/user.js'
|
||||
import { transformVoiceRegion, type VoiceRegion } from './transformers/voiceRegion.js'
|
||||
import { transformVoiceState, type VoiceState } from './transformers/voiceState.js'
|
||||
import { transformWebhook, type Webhook } from './transformers/webhook.js'
|
||||
import { transformWelcomeScreen, type WelcomeScreen } from './transformers/welcomeScreen.js'
|
||||
import { transformWidget, type GuildWidget } from './transformers/widget.js'
|
||||
import { transformWidgetSettings, type GuildWidgetSettings } from './transformers/widgetSettings.js'
|
||||
import type { BotInteractionResponse, DiscordComponent, DiscordInteractionResponse, DiscordThreadMemberGuildCreate } from './typings.js'
|
||||
type User,
|
||||
type VoiceRegion,
|
||||
type VoiceState,
|
||||
type Webhook,
|
||||
type WelcomeScreen,
|
||||
} from './transformers/index.js'
|
||||
import type { DiscordComponent, DiscordThreadMemberGuildCreate } from './typings.js'
|
||||
|
||||
export interface Transformers {
|
||||
customizers: {
|
||||
@@ -134,7 +170,7 @@ export interface Transformers {
|
||||
message: (bot: Bot, payload: DiscordMessage, message: Message) => any
|
||||
messageInteractionMetadata: (bot: Bot, payload: DiscordMessageInteractionMetadata, metadata: MessageInteractionMetadata) => any
|
||||
messageCall: (bot: Bot, payload: DiscordMessageCall, call: MessageCall) => any
|
||||
user: (bot: Bot, payload: DiscordUser, user: User) => any
|
||||
user: (bot: Bot, payload: Partial<DiscordUser>, user: User) => any
|
||||
member: (bot: Bot, payload: DiscordMember, member: Member) => any
|
||||
role: (bot: Bot, payload: DiscordRole, role: Role) => any
|
||||
automodRule: (bot: Bot, payload: DiscordAutoModerationRule, automodRule: AutoModerationRule) => any
|
||||
@@ -572,72 +608,71 @@ export interface Transformers {
|
||||
}
|
||||
}
|
||||
reverse: {
|
||||
allowedMentions: (bot: Bot, payload: AllowedMentions) => DiscordAllowedMentions
|
||||
embed: (bot: Bot, payload: Embed) => DiscordEmbed
|
||||
component: (bot: Bot, payload: Component) => DiscordComponent
|
||||
activity: (bot: Bot, payload: Activity) => DiscordActivity
|
||||
member: (bot: Bot, payload: Member) => DiscordMember
|
||||
user: (bot: Bot, payload: User) => DiscordUser
|
||||
team: (bot: Bot, payload: Team) => DiscordTeam
|
||||
application: (bot: Bot, payload: Application) => DiscordApplication
|
||||
snowflake: (snowflake: BigString) => string
|
||||
createApplicationCommand: (bot: Bot, payload: CreateApplicationCommand) => DiscordCreateApplicationCommand
|
||||
applicationCommand: (bot: Bot, payload: ApplicationCommand) => DiscordApplicationCommand
|
||||
applicationCommandOption: (bot: Bot, payload: ApplicationCommandOption) => DiscordApplicationCommandOption
|
||||
applicationCommandOptionChoice: (bot: Bot, payload: ApplicationCommandOptionChoice) => DiscordApplicationCommandOptionChoice
|
||||
interactionResponse: (bot: Bot, payload: BotInteractionResponse) => DiscordInteractionResponse
|
||||
attachment: (bot: Bot, payload: Attachment) => DiscordAttachment
|
||||
allowedMentions: typeof transformAllowedMentionsToDiscordAllowedMentions
|
||||
embed: typeof transformEmbedToDiscordEmbed
|
||||
component: typeof transformComponentToDiscordComponent
|
||||
activity: typeof transformActivityToDiscordActivity
|
||||
member: typeof transformMemberToDiscordMember
|
||||
user: typeof transformUserToDiscordUser
|
||||
team: typeof transformTeamToDiscordTeam
|
||||
application: typeof transformApplicationToDiscordApplication
|
||||
snowflake: typeof bigintToSnowflake
|
||||
createApplicationCommand: typeof transformCreateApplicationCommandToDiscordCreateApplicationCommand
|
||||
applicationCommand: typeof transformApplicationCommandToDiscordApplicationCommand
|
||||
applicationCommandOption: typeof transformApplicationCommandOptionToDiscordApplicationCommandOption
|
||||
applicationCommandOptionChoice: typeof transformApplicationCommandOptionChoiceToDiscordApplicationCommandOptionChoice
|
||||
interactionResponse: typeof transformInteractionResponseToDiscordInteractionResponse
|
||||
attachment: typeof transformAttachmentToDiscordAttachment
|
||||
}
|
||||
snowflake: (snowflake: BigString) => bigint
|
||||
gatewayBot: (bot: Bot, payload: DiscordGetGatewayBot) => GetGatewayBot
|
||||
automodRule: (bot: Bot, payload: DiscordAutoModerationRule) => AutoModerationRule
|
||||
automodActionExecution: (bot: Bot, payload: DiscordAutoModerationActionExecution) => AutoModerationActionExecution
|
||||
channel: (bot: Bot, payload: { channel: DiscordChannel } & { guildId?: BigString }) => Channel
|
||||
guild: (bot: Bot, payload: { guild: DiscordGuild } & { shardId: number }) => Guild
|
||||
user: (bot: Bot, payload: DiscordUser) => User
|
||||
member: (bot: Bot, payload: DiscordMember, guildId: BigString, userId: BigString) => Member
|
||||
message: (bot: Bot, payload: DiscordMessage) => Message
|
||||
messageInteractionMetadata: (bot: Bot, payload: DiscordMessageInteractionMetadata) => MessageInteractionMetadata
|
||||
messageCall: (bot: Bot, payload: DiscordMessageCall) => MessageCall
|
||||
role: (bot: Bot, payload: { role: DiscordRole } & { guildId: BigString }) => Role
|
||||
voiceState: (bot: Bot, payload: { voiceState: DiscordVoiceState } & { guildId: bigint }) => VoiceState
|
||||
interaction: (bot: Bot, payload: DiscordInteraction) => Interaction
|
||||
interactionDataOptions: (bot: Bot, payload: DiscordInteractionDataOption) => InteractionDataOption
|
||||
integration: (bot: Bot, payload: DiscordIntegrationCreateUpdate) => Integration
|
||||
invite: (bot: Bot, payload: { invite: DiscordInviteCreate | DiscordInviteMetadata; shardId: number }) => Invite
|
||||
application: (bot: Bot, payload: { application: DiscordApplication; shardId: number }) => Application
|
||||
team: (bot: Bot, payload: DiscordTeam) => Team
|
||||
emoji: (bot: Bot, payload: DiscordEmoji) => Emoji
|
||||
activity: (bot: Bot, payload: DiscordActivity) => Activity
|
||||
presence: (bot: Bot, payload: DiscordPresenceUpdate) => PresenceUpdate
|
||||
attachment: (bot: Bot, payload: DiscordAttachment) => Attachment
|
||||
embed: (bot: Bot, payload: DiscordEmbed) => Embed
|
||||
component: (bot: Bot, payload: DiscordComponent) => Component
|
||||
webhook: (bot: Bot, payload: DiscordWebhook) => Webhook
|
||||
auditLogEntry: (bot: Bot, payload: DiscordAuditLogEntry) => AuditLogEntry
|
||||
applicationCommand: (bot: Bot, payload: DiscordApplicationCommand) => ApplicationCommand
|
||||
applicationCommandOption: (bot: Bot, payload: DiscordApplicationCommandOption) => ApplicationCommandOption
|
||||
applicationCommandPermission: (bot: Bot, payload: DiscordGuildApplicationCommandPermissions) => ApplicationCommandPermission
|
||||
scheduledEvent: (bot: Bot, payload: DiscordScheduledEvent) => ScheduledEvent
|
||||
threadMember: (bot: Bot, payload: DiscordThreadMember) => ThreadMember
|
||||
threadMemberGuildCreate: (bot: Bot, payload: DiscordThreadMemberGuildCreate) => ThreadMemberGuildCreate
|
||||
welcomeScreen: (bot: Bot, payload: DiscordWelcomeScreen) => WelcomeScreen
|
||||
voiceRegion: (bot: Bot, payload: DiscordVoiceRegion) => VoiceRegion
|
||||
widget: (bot: Bot, payload: DiscordGuildWidget) => GuildWidget
|
||||
widgetSettings: (bot: Bot, payload: DiscordGuildWidgetSettings) => GuildWidgetSettings
|
||||
stageInstance: (bot: Bot, payload: DiscordStageInstance) => StageInstance
|
||||
inviteStageInstance: (bot: Bot, payload: DiscordInviteStageInstance & { guildId: BigString }) => InviteStageInstance
|
||||
|
||||
sticker: (bot: Bot, payload: DiscordSticker) => Sticker
|
||||
stickerPack: (bot: Bot, payload: DiscordStickerPack) => StickerPack
|
||||
applicationCommandOptionChoice: (bot: Bot, payload: DiscordApplicationCommandOptionChoice) => ApplicationCommandOptionChoice
|
||||
template: (bot: Bot, payload: DiscordTemplate) => Template
|
||||
guildOnboarding: (bot: Bot, payload: DiscordGuildOnboarding) => GuildOnboarding
|
||||
entitlement: (bot: Bot, payload: DiscordEntitlement) => Entitlement
|
||||
sku: (bot: Bot, payload: DiscordSku) => Sku
|
||||
poll: (bot: Bot, payload: DiscordPoll) => Poll
|
||||
pollMedia: (bot: Bot, payload: DiscordPollMedia) => PollMedia
|
||||
avatarDecorationData: (bot: Bot, payload: DiscordAvatarDecorationData) => AvatarDecorationData
|
||||
snowflake: typeof snowflakeToBigint
|
||||
gatewayBot: typeof transformGatewayBot
|
||||
automodRule: typeof transformAutoModerationRule
|
||||
automodActionExecution: typeof transformAutoModerationActionExecution
|
||||
channel: typeof transformChannel
|
||||
guild: typeof transformGuild
|
||||
user: typeof transformUser
|
||||
member: typeof transformMember
|
||||
message: typeof transformMessage
|
||||
messageInteractionMetadata: typeof transformMessageInteractionMetadata
|
||||
messageCall: typeof transformMessageCall
|
||||
role: typeof transformRole
|
||||
voiceState: typeof transformVoiceState
|
||||
interaction: typeof transformInteraction
|
||||
interactionDataOptions: typeof transformInteractionDataOption
|
||||
integration: typeof transformIntegration
|
||||
invite: typeof transformInvite
|
||||
application: typeof transformApplication
|
||||
team: typeof transformTeam
|
||||
emoji: typeof transformEmoji
|
||||
activity: typeof transformActivity
|
||||
presence: typeof transformPresence
|
||||
attachment: typeof transformAttachment
|
||||
embed: typeof transformEmbed
|
||||
component: typeof transformComponent
|
||||
webhook: typeof transformWebhook
|
||||
auditLogEntry: typeof transformAuditLogEntry
|
||||
applicationCommand: typeof transformApplicationCommand
|
||||
applicationCommandOption: typeof transformApplicationCommandOption
|
||||
applicationCommandPermission: typeof transformApplicationCommandPermission
|
||||
scheduledEvent: typeof transformScheduledEvent
|
||||
threadMember: typeof transformThreadMember
|
||||
threadMemberGuildCreate: typeof transformThreadMemberGuildCreate
|
||||
welcomeScreen: typeof transformWelcomeScreen
|
||||
voiceRegion: typeof transformVoiceRegion
|
||||
widget: typeof transformWidget
|
||||
widgetSettings: typeof transformWidgetSettings
|
||||
stageInstance: typeof transformStageInstance
|
||||
inviteStageInstance: typeof transformInviteStageInstance
|
||||
sticker: typeof transformSticker
|
||||
stickerPack: typeof transformStickerPack
|
||||
applicationCommandOptionChoice: typeof transformApplicationCommandOptionChoice
|
||||
template: typeof transformTemplate
|
||||
guildOnboarding: typeof transformGuildOnboarding
|
||||
entitlement: typeof transformEntitlement
|
||||
sku: typeof transformSku
|
||||
poll: typeof transformPoll
|
||||
pollMedia: typeof transformPollMedia
|
||||
avatarDecorationData: typeof transformAvatarDecorationData
|
||||
}
|
||||
|
||||
export interface CreateTransformerOptions {
|
||||
|
||||
@@ -28,10 +28,7 @@ export function transformApplication(bot: Bot, payload: { application: DiscordAp
|
||||
|
||||
id: bot.transformers.snowflake(payload.application.id),
|
||||
icon: payload.application.icon ? iconHashToBigInt(payload.application.icon) : undefined,
|
||||
owner: payload.application.owner
|
||||
? // @ts-expect-error the partial here wont break anything
|
||||
bot.transformers.user(bot, payload.application.owner)
|
||||
: undefined,
|
||||
owner: payload.application.owner ? bot.transformers.user(bot, payload.application.owner) : undefined,
|
||||
team: payload.application.team ? bot.transformers.team(bot, payload.application.team) : undefined,
|
||||
guildId: payload.application.guild_id ? bot.transformers.snowflake(payload.application.guild_id) : undefined,
|
||||
// @ts-expect-error the partial here wont break anything
|
||||
|
||||
@@ -13,18 +13,18 @@ export const UserToggle = {
|
||||
}
|
||||
|
||||
export class UserToggles extends ToggleBitfield {
|
||||
constructor(userOrTogglesInt: DiscordUser | number) {
|
||||
constructor(toggles: Partial<DiscordUser> | number) {
|
||||
super()
|
||||
|
||||
if (typeof userOrTogglesInt === 'number') this.bitfield = userOrTogglesInt
|
||||
else {
|
||||
const user = userOrTogglesInt
|
||||
|
||||
if (user.bot) this.add(UserToggle.bot)
|
||||
if (user.system) this.add(UserToggle.system)
|
||||
if (user.mfa_enabled) this.add(UserToggle.mfaEnabled)
|
||||
if (user.verified) this.add(UserToggle.verified)
|
||||
if (typeof toggles === 'number') {
|
||||
this.bitfield = toggles
|
||||
return
|
||||
}
|
||||
|
||||
if (toggles.bot) this.add(UserToggle.bot)
|
||||
if (toggles.system) this.add(UserToggle.system)
|
||||
if (toggles.mfa_enabled) this.add(UserToggle.mfaEnabled)
|
||||
if (toggles.verified) this.add(UserToggle.verified)
|
||||
}
|
||||
|
||||
/** Whether the user belongs to an OAuth2 application */
|
||||
|
||||
@@ -21,13 +21,13 @@ const baseUser: Partial<User> & BaseUser = {
|
||||
},
|
||||
}
|
||||
|
||||
export function transformUser(bot: Bot, payload: DiscordUser): User {
|
||||
export function transformUser(bot: Bot, payload: DiscordUser): User
|
||||
export function transformUser(bot: Bot, payload: Partial<DiscordUser>): Partial<User>
|
||||
export function transformUser(bot: Bot, payload: Partial<DiscordUser>): User {
|
||||
const user: User = Object.create(baseUser)
|
||||
const props = bot.transformers.desiredProperties.user
|
||||
|
||||
if (props.bot || props.system || props.mfaEnabled || props.verified) {
|
||||
user.toggles = new UserToggles(payload)
|
||||
}
|
||||
if (props.bot || props.system || props.mfaEnabled || props.verified) user.toggles = new UserToggles(payload)
|
||||
if (props.flags) user.flags = new ToggleBitfield(payload.flags)
|
||||
if (props.publicFlags) user.publicFlags = new ToggleBitfield(payload.public_flags)
|
||||
if (props.id && payload.id) user.id = bot.transformers.snowflake(payload.id)
|
||||
|
||||
Reference in New Issue
Block a user