mirror of
https://github.com/billsonnn/nitro-renderer.git
synced 2024-11-30 03:00:51 +01:00
Talent Track messages
This commit is contained in:
parent
7d75fdd1b3
commit
a1eb711f6a
@ -1,5 +1,5 @@
|
|||||||
import { IMessageConfiguration } from '../../core/communication/messages/IMessageConfiguration';
|
import { IMessageConfiguration } from '../../core/communication/messages/IMessageConfiguration';
|
||||||
import { AchievementNotificationMessageEvent, ActivityPointNotificationMessageEvent, AddJukeboxDiskComposer, ApproveNameMessageComposer, ApproveNameMessageEvent, AvailabilityTimeMessageEvent, BadgePointLimitsEvent, BadgeReceivedEvent, BonusRareInfoMessageEvent, BuildersClubFurniCountMessageEvent, BuildersClubSubscriptionStatusMessageEvent, BundleDiscountRulesetMessageEvent, ChangeUserNameMessageComposer, ChangeUserNameResultMessageEvent, CheckUserNameMessageComposer, CheckUserNameResultMessageEvent, ClubGiftNotificationEvent, DirectSMSClubBuyAvailableMessageEvent, FigureUpdateEvent, FurnitureGroupInfoComposer, GetBonusRareInfoMessageComposer, GetCatalogPageExpirationComposer, GetCatalogPageWithEarliestExpiryComposer, GetDirectClubBuyAvailableComposer, GetHabboBasicMembershipExtendOfferComposer, GetHabboClubExtendOfferMessageComposer, GetInterstitialMessageComposer, GetJukeboxPlayListMessageComposer, GetLimitedOfferAppearingNextComposer, GetNextTargetedOfferComposer, GetNowPlayingMessageComposer, GetOfficialSongIdMessageComposer, GetRoomAdPurchaseInfoComposer, GetSeasonalCalendarDailyOfferComposer, GetSongInfoMessageComposer, GetSoundMachinePlayListMessageComposer, GetUserSongDisksMessageComposer, GroupBadgesComposer, GroupBadgesEvent, HabboClubExtendOfferMessageEvent, HotelClosedAndOpensEvent, HotelClosesAndWillOpenAtEvent, HotelWillCloseInMinutesEvent, InfoFeedEnableMessageEvent, InterstitialMessageEvent, InterstitialShownMessageComposer, IsBadgeRequestFulfilledEvent, IsOfferGiftableMessageEvent, JukeboxPlayListFullMessageEvent, JukeboxSongDisksMessageEvent, LimitedOfferAppearingNextMessageEvent, MaintenanceStatusMessageEvent, MarkCatalogNewAdditionsPageOpenedComposer, MarketplaceBuyOfferComposer, MarketplaceRedeemCreditsComposer, MarketplaceRequesstItemStatsComposer, MarketplaceRequestComposer, MarketplaceRequestOffersComposer, MarketplaceRequestOwnItemsComposer, MarketplaceTakeItemBackComposer, MysteryBoxKeysEvent, NotEnoughBalanceMessageEvent, NowPlayingMessageEvent, OfficialSongIdMessageEvent, OpenCampaignCalendarDoorAsStaffComposer, OpenCampaignCalendarDoorComposer, PetExperienceEvent, PetMountComposer, PetSupplementComposer, PlayListMessageEvent, PlayListSongAddedMessageEvent, PurchaseBasicMembershipExtensionComposer, PurchaseRoomAdMessageComposer, PurchaseTargetedOfferComposer, PurchaseVipMembershipExtensionComposer, RemoveAllRightsMessageComposer, RemoveJukeboxDiskComposer, RemoveOwnRoomRightsRoomMessageComposer, RemovePetSaddleComposer, RoomAdErrorEvent, RoomAdPurchaseInfoEvent, RoomUnitGiveHandItemPetComposer, SeasonalCalendarDailyOfferMessageEvent, SellablePetPalettesMessageEvent, SetTargetedOfferStateComposer, ShopTargetedOfferViewedComposer, TargetedOfferEvent, TargetedOfferNotFoundEvent, TogglePetBreedingComposer, TogglePetRidingComposer, TraxSongInfoMessageEvent, UnseenResetCategoryComposer, UnseenResetItemsComposer, UsePetProductComposer, UserSongDisksInventoryMessageEvent, WardrobeMessageEvent } from './messages';
|
import { AchievementNotificationMessageEvent, ActivityPointNotificationMessageEvent, AddJukeboxDiskComposer, ApproveNameMessageComposer, ApproveNameMessageEvent, AvailabilityTimeMessageEvent, BadgePointLimitsEvent, BadgeReceivedEvent, BonusRareInfoMessageEvent, BuildersClubFurniCountMessageEvent, BuildersClubSubscriptionStatusMessageEvent, BundleDiscountRulesetMessageEvent, ChangeUserNameMessageComposer, ChangeUserNameResultMessageEvent, CheckUserNameMessageComposer, CheckUserNameResultMessageEvent, ClubGiftNotificationEvent, DirectSMSClubBuyAvailableMessageEvent, FigureUpdateEvent, FurnitureGroupInfoComposer, GetBonusRareInfoMessageComposer, GetCatalogPageExpirationComposer, GetCatalogPageWithEarliestExpiryComposer, GetDirectClubBuyAvailableComposer, GetHabboBasicMembershipExtendOfferComposer, GetHabboClubExtendOfferMessageComposer, GetInterstitialMessageComposer, GetJukeboxPlayListMessageComposer, GetLimitedOfferAppearingNextComposer, GetNextTargetedOfferComposer, GetNowPlayingMessageComposer, GetOfficialSongIdMessageComposer, GetRoomAdPurchaseInfoComposer, GetSeasonalCalendarDailyOfferComposer, GetSongInfoMessageComposer, GetSoundMachinePlayListMessageComposer, GetUserSongDisksMessageComposer, GroupBadgesComposer, GroupBadgesEvent, HabboClubExtendOfferMessageEvent, HotelClosedAndOpensEvent, HotelClosesAndWillOpenAtEvent, HotelWillCloseInMinutesEvent, InfoFeedEnableMessageEvent, InterstitialMessageEvent, InterstitialShownMessageComposer, IsBadgeRequestFulfilledEvent, IsOfferGiftableMessageEvent, JukeboxPlayListFullMessageEvent, JukeboxSongDisksMessageEvent, LimitedOfferAppearingNextMessageEvent, MaintenanceStatusMessageEvent, MarkCatalogNewAdditionsPageOpenedComposer, MarketplaceBuyOfferComposer, MarketplaceRedeemCreditsComposer, MarketplaceRequesstItemStatsComposer, MarketplaceRequestComposer, MarketplaceRequestOffersComposer, MarketplaceRequestOwnItemsComposer, MarketplaceTakeItemBackComposer, MysteryBoxKeysEvent, NotEnoughBalanceMessageEvent, NowPlayingMessageEvent, OfficialSongIdMessageEvent, OpenCampaignCalendarDoorAsStaffComposer, OpenCampaignCalendarDoorComposer, PetExperienceEvent, PetMountComposer, PetSupplementComposer, PlayListMessageEvent, PlayListSongAddedMessageEvent, PurchaseBasicMembershipExtensionComposer, PurchaseRoomAdMessageComposer, PurchaseTargetedOfferComposer, PurchaseVipMembershipExtensionComposer, RemoveAllRightsMessageComposer, RemoveJukeboxDiskComposer, RemoveOwnRoomRightsRoomMessageComposer, RemovePetSaddleComposer, RoomAdErrorEvent, RoomAdPurchaseInfoEvent, RoomUnitGiveHandItemPetComposer, SeasonalCalendarDailyOfferMessageEvent, SellablePetPalettesMessageEvent, SetTargetedOfferStateComposer, ShopTargetedOfferViewedComposer, TalentTrackEvent, TargetedOfferEvent, TargetedOfferNotFoundEvent, TogglePetBreedingComposer, TogglePetRidingComposer, TraxSongInfoMessageEvent, UnseenResetCategoryComposer, UnseenResetItemsComposer, UsePetProductComposer, UserSongDisksInventoryMessageEvent, WardrobeMessageEvent } from './messages';
|
||||||
import { AvailabilityStatusMessageEvent } from './messages/incoming/availability/AvailabilityStatusMessageEvent';
|
import { AvailabilityStatusMessageEvent } from './messages/incoming/availability/AvailabilityStatusMessageEvent';
|
||||||
import { CfhSanctionMessageEvent, CfhTopicsInitEvent, SanctionStatusEvent } from './messages/incoming/callforhelp';
|
import { CfhSanctionMessageEvent, CfhTopicsInitEvent, SanctionStatusEvent } from './messages/incoming/callforhelp';
|
||||||
import { CameraPublishStatusMessageEvent } from './messages/incoming/camera/CameraPublishStatusMessageEvent';
|
import { CameraPublishStatusMessageEvent } from './messages/incoming/camera/CameraPublishStatusMessageEvent';
|
||||||
@ -293,6 +293,7 @@ import { GroupSettingsComposer } from './messages/outgoing/group/GroupSettingsCo
|
|||||||
import { AuthenticationMessageComposer } from './messages/outgoing/handshake/AuthenticationMessageComposer';
|
import { AuthenticationMessageComposer } from './messages/outgoing/handshake/AuthenticationMessageComposer';
|
||||||
import { InfoRetrieveBaseMessageComposer } from './messages/outgoing/handshake/InfoRetrieveBaseMessageComposer';
|
import { InfoRetrieveBaseMessageComposer } from './messages/outgoing/handshake/InfoRetrieveBaseMessageComposer';
|
||||||
import { SecurityTicketComposer } from './messages/outgoing/handshake/SecurityTicketComposer';
|
import { SecurityTicketComposer } from './messages/outgoing/handshake/SecurityTicketComposer';
|
||||||
|
import { TalentTrackComposer } from './messages/outgoing/helper/TalentTrackComposer';
|
||||||
import { RequestBadgesComposer } from './messages/outgoing/inventory/badges/RequestBadgesComposer';
|
import { RequestBadgesComposer } from './messages/outgoing/inventory/badges/RequestBadgesComposer';
|
||||||
import { SetActivatedBadgesComposer } from './messages/outgoing/inventory/badges/SetActivatedBadgesComposer';
|
import { SetActivatedBadgesComposer } from './messages/outgoing/inventory/badges/SetActivatedBadgesComposer';
|
||||||
import { GetBotInventoryComposer } from './messages/outgoing/inventory/bots/GetBotInventoryComposer';
|
import { GetBotInventoryComposer } from './messages/outgoing/inventory/bots/GetBotInventoryComposer';
|
||||||
@ -873,6 +874,9 @@ export class NitroMessages implements IMessageConfiguration
|
|||||||
this._events.set(IncomingHeader.PLAYLIST_SONG_ADDED, PlayListSongAddedMessageEvent);
|
this._events.set(IncomingHeader.PLAYLIST_SONG_ADDED, PlayListSongAddedMessageEvent);
|
||||||
this._events.set(IncomingHeader.TRAX_SONG_INFO, TraxSongInfoMessageEvent);
|
this._events.set(IncomingHeader.TRAX_SONG_INFO, TraxSongInfoMessageEvent);
|
||||||
this._events.set(IncomingHeader.USER_SONG_DISKS_INVENTORY, UserSongDisksInventoryMessageEvent);
|
this._events.set(IncomingHeader.USER_SONG_DISKS_INVENTORY, UserSongDisksInventoryMessageEvent);
|
||||||
|
|
||||||
|
// HELPER
|
||||||
|
this._events.set(IncomingHeader.HELPER_TALENT_TRACK, TalentTrackEvent);
|
||||||
}
|
}
|
||||||
|
|
||||||
private registerComposers(): void
|
private registerComposers(): void
|
||||||
@ -1267,6 +1271,9 @@ export class NitroMessages implements IMessageConfiguration
|
|||||||
this._composers.set(OutgoingHeader.GET_SOUND_MACHINE_PLAYLIST, GetSoundMachinePlayListMessageComposer);
|
this._composers.set(OutgoingHeader.GET_SOUND_MACHINE_PLAYLIST, GetSoundMachinePlayListMessageComposer);
|
||||||
this._composers.set(OutgoingHeader.GET_USER_SONG_DISKS, GetUserSongDisksMessageComposer);
|
this._composers.set(OutgoingHeader.GET_USER_SONG_DISKS, GetUserSongDisksMessageComposer);
|
||||||
this._composers.set(OutgoingHeader.REMOVE_JUKEBOX_DISK, RemoveJukeboxDiskComposer);
|
this._composers.set(OutgoingHeader.REMOVE_JUKEBOX_DISK, RemoveJukeboxDiskComposer);
|
||||||
|
|
||||||
|
// HELPER
|
||||||
|
this._composers.set(OutgoingHeader.HELPER_TALENT_TRACK, TalentTrackComposer);
|
||||||
}
|
}
|
||||||
|
|
||||||
public get events(): Map<number, Function>
|
public get events(): Map<number, Function>
|
||||||
|
@ -317,4 +317,5 @@ export class IncomingHeader
|
|||||||
public static COMPETITION_SECONDS_UNTIL = 3926;
|
public static COMPETITION_SECONDS_UNTIL = 3926;
|
||||||
public static BADGE_POINT_LIMITS = 2501;
|
public static BADGE_POINT_LIMITS = 2501;
|
||||||
public static BADGE_REQUEST_FULFILLED = 2998;
|
public static BADGE_REQUEST_FULFILLED = 2998;
|
||||||
|
public static HELPER_TALENT_TRACK = 3406;
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,16 @@
|
|||||||
|
import { IMessageEvent } from '../../../../../core/communication/messages/IMessageEvent';
|
||||||
|
import { MessageEvent } from '../../../../../core/communication/messages/MessageEvent';
|
||||||
|
import { TalentTrackParser } from '../../parser/help/TalentTrackParser';
|
||||||
|
|
||||||
|
export class TalentTrackEvent extends MessageEvent implements IMessageEvent
|
||||||
|
{
|
||||||
|
constructor(callBack: Function)
|
||||||
|
{
|
||||||
|
super(callBack, TalentTrackParser);
|
||||||
|
}
|
||||||
|
|
||||||
|
public getParser(): TalentTrackParser
|
||||||
|
{
|
||||||
|
return this.parser as TalentTrackParser;
|
||||||
|
}
|
||||||
|
}
|
@ -1 +1,2 @@
|
|||||||
export * from './CallForHelpResultMessageEvent';
|
export * from './CallForHelpResultMessageEvent';
|
||||||
|
export * from './TalentTrackEvent';
|
||||||
|
@ -307,4 +307,5 @@ export class OutgoingHeader
|
|||||||
public static ROOM_AD_PURCHASE_INITIATED = 2283;
|
public static ROOM_AD_PURCHASE_INITIATED = 2283;
|
||||||
public static SET_TARGETTED_OFFER_STATE = 2041;
|
public static SET_TARGETTED_OFFER_STATE = 2041;
|
||||||
public static SHOP_TARGETED_OFFER_VIEWED = 3483;
|
public static SHOP_TARGETED_OFFER_VIEWED = 3483;
|
||||||
|
public static HELPER_TALENT_TRACK = 196;
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,21 @@
|
|||||||
|
import { IMessageComposer } from '../../../../../core/communication/messages/IMessageComposer';
|
||||||
|
|
||||||
|
export class TalentTrackComposer implements IMessageComposer<ConstructorParameters<typeof TalentTrackComposer>>
|
||||||
|
{
|
||||||
|
private _data: ConstructorParameters<typeof TalentTrackComposer>;
|
||||||
|
|
||||||
|
constructor(type: string)
|
||||||
|
{
|
||||||
|
this._data = [ type ];
|
||||||
|
}
|
||||||
|
|
||||||
|
public getMessageArray()
|
||||||
|
{
|
||||||
|
return this._data;
|
||||||
|
}
|
||||||
|
|
||||||
|
public dispose(): void
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1 @@
|
|||||||
|
export * from './TalentTrackComposer';
|
@ -9,6 +9,7 @@ export * from './desktop';
|
|||||||
export * from './friendlist';
|
export * from './friendlist';
|
||||||
export * from './group';
|
export * from './group';
|
||||||
export * from './handshake';
|
export * from './handshake';
|
||||||
|
export * from './helper';
|
||||||
export * from './inventory';
|
export * from './inventory';
|
||||||
export * from './landingview';
|
export * from './landingview';
|
||||||
export * from './marketplace';
|
export * from './marketplace';
|
||||||
|
@ -0,0 +1,79 @@
|
|||||||
|
import { IMessageDataWrapper, IMessageParser } from '../../../../../core';
|
||||||
|
import { TalentTrackLevel } from './common/TalentTrackLevel';
|
||||||
|
import { TalentTrackLevelAchievement } from './common/TalentTrackLevelAchievement';
|
||||||
|
import { TalentTrackLevelItem } from './common/TalentTrackLevelItem';
|
||||||
|
|
||||||
|
export class TalentTrackParser implements IMessageParser
|
||||||
|
{
|
||||||
|
private _type: string;
|
||||||
|
private _levels: TalentTrackLevel[];
|
||||||
|
|
||||||
|
public flush(): boolean
|
||||||
|
{
|
||||||
|
this._type = null;
|
||||||
|
this._levels = null;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public parse(wrapper: IMessageDataWrapper): boolean
|
||||||
|
{
|
||||||
|
if(!wrapper) return false;
|
||||||
|
|
||||||
|
this._type = wrapper.readString();
|
||||||
|
|
||||||
|
this._levels = [];
|
||||||
|
const levelsCount = wrapper.readInt();
|
||||||
|
|
||||||
|
for(let i = 0; i < levelsCount; i++)
|
||||||
|
{
|
||||||
|
const levelId = wrapper.readInt();
|
||||||
|
const levelState = wrapper.readInt();
|
||||||
|
|
||||||
|
const levelAchievements: TalentTrackLevelAchievement[] = [];
|
||||||
|
const achievementsCount = wrapper.readInt();
|
||||||
|
|
||||||
|
for(let j = 0; j < achievementsCount; j++)
|
||||||
|
{
|
||||||
|
const id = wrapper.readInt();
|
||||||
|
const index = wrapper.readInt();
|
||||||
|
const code = wrapper.readString();
|
||||||
|
const state = wrapper.readInt();
|
||||||
|
const progress = wrapper.readInt();
|
||||||
|
const achievementProgress = wrapper.readInt();
|
||||||
|
|
||||||
|
levelAchievements.push(new TalentTrackLevelAchievement(id, index, code, state, progress, achievementProgress));
|
||||||
|
}
|
||||||
|
|
||||||
|
const levelPerks: string[] = [];
|
||||||
|
const perksCount = wrapper.readInt();
|
||||||
|
|
||||||
|
for(let j = 0; j < perksCount; j++) levelPerks.push(wrapper.readString());
|
||||||
|
|
||||||
|
const levelItems: TalentTrackLevelItem[] = [];
|
||||||
|
const itemsCount = wrapper.readInt();
|
||||||
|
|
||||||
|
for(let j = 0; j < itemsCount; j++)
|
||||||
|
{
|
||||||
|
const name = wrapper.readString();
|
||||||
|
const unknownInt = wrapper.readInt();
|
||||||
|
|
||||||
|
levelItems.push(new TalentTrackLevelItem(name, unknownInt));
|
||||||
|
}
|
||||||
|
|
||||||
|
this._levels.push(new TalentTrackLevel(levelId, levelState, levelAchievements, levelPerks, levelItems));
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public get type(): string
|
||||||
|
{
|
||||||
|
return this._type;
|
||||||
|
}
|
||||||
|
|
||||||
|
public get levels(): TalentTrackLevel[]
|
||||||
|
{
|
||||||
|
return this._levels;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,45 @@
|
|||||||
|
import { TalentTrackLevelAchievement } from './TalentTrackLevelAchievement';
|
||||||
|
import { TalentTrackLevelItem } from './TalentTrackLevelItem';
|
||||||
|
|
||||||
|
export class TalentTrackLevel
|
||||||
|
{
|
||||||
|
private _level: number;
|
||||||
|
private _state: number;
|
||||||
|
private _achievements: TalentTrackLevelAchievement[]
|
||||||
|
private _perks: string[];
|
||||||
|
private _items: TalentTrackLevelItem[];
|
||||||
|
|
||||||
|
constructor(level: number, state: number, achievements: TalentTrackLevelAchievement[], perks: string[], items: TalentTrackLevelItem[])
|
||||||
|
{
|
||||||
|
this._level = level;
|
||||||
|
this._state = state;
|
||||||
|
this._achievements = achievements;
|
||||||
|
this._perks = perks;
|
||||||
|
this._items = items;
|
||||||
|
}
|
||||||
|
|
||||||
|
public get level(): number
|
||||||
|
{
|
||||||
|
return this._level;
|
||||||
|
}
|
||||||
|
|
||||||
|
public get state(): number
|
||||||
|
{
|
||||||
|
return this._state;
|
||||||
|
}
|
||||||
|
|
||||||
|
public get achievements(): TalentTrackLevelAchievement[]
|
||||||
|
{
|
||||||
|
return this._achievements;
|
||||||
|
}
|
||||||
|
|
||||||
|
public get perks(): string[]
|
||||||
|
{
|
||||||
|
return this._perks;
|
||||||
|
}
|
||||||
|
|
||||||
|
public get items(): TalentTrackLevelItem[]
|
||||||
|
{
|
||||||
|
return this._items;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,49 @@
|
|||||||
|
export class TalentTrackLevelAchievement
|
||||||
|
{
|
||||||
|
private _id: number;
|
||||||
|
private _index: number;
|
||||||
|
private _achievementCode: string;
|
||||||
|
private _state: number;
|
||||||
|
private _progress: number;
|
||||||
|
private _achievementProgress: number;
|
||||||
|
|
||||||
|
constructor(id: number, index: number, achievementCode: string, state: number, progress: number, achievementProgress: number)
|
||||||
|
{
|
||||||
|
this._id = id;
|
||||||
|
this._index = index;
|
||||||
|
this._achievementCode = achievementCode;
|
||||||
|
this._state = state;
|
||||||
|
this._progress = progress;
|
||||||
|
this._achievementProgress = achievementProgress;
|
||||||
|
}
|
||||||
|
|
||||||
|
public get id(): number
|
||||||
|
{
|
||||||
|
return this._id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public get index(): number
|
||||||
|
{
|
||||||
|
return this._index;
|
||||||
|
}
|
||||||
|
|
||||||
|
public get achievementCode(): string
|
||||||
|
{
|
||||||
|
return this._achievementCode;
|
||||||
|
}
|
||||||
|
|
||||||
|
public get state(): number
|
||||||
|
{
|
||||||
|
return this._state;
|
||||||
|
}
|
||||||
|
|
||||||
|
public get progress(): number
|
||||||
|
{
|
||||||
|
return this._progress;
|
||||||
|
}
|
||||||
|
|
||||||
|
public get achievementProgress(): number
|
||||||
|
{
|
||||||
|
return this._achievementProgress;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,21 @@
|
|||||||
|
export class TalentTrackLevelItem
|
||||||
|
{
|
||||||
|
private _name: string;
|
||||||
|
private _unknownInt: number;
|
||||||
|
|
||||||
|
constructor(name: string, unknownInt: number)
|
||||||
|
{
|
||||||
|
this._name = name;
|
||||||
|
this._unknownInt = unknownInt;
|
||||||
|
}
|
||||||
|
|
||||||
|
public get name(): string
|
||||||
|
{
|
||||||
|
return this._name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public get unknownInt(): number
|
||||||
|
{
|
||||||
|
return this._unknownInt;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,3 @@
|
|||||||
|
export * from './TalentTrackLevel';
|
||||||
|
export * from './TalentTrackLevelAchievement';
|
||||||
|
export * from './TalentTrackLevelItem';
|
@ -1 +1,3 @@
|
|||||||
export * from './CallForHelpResultMessageParser';
|
export * from './CallForHelpResultMessageParser';
|
||||||
|
export * from './common';
|
||||||
|
export * from './TalentTrackParser';
|
||||||
|
Loading…
Reference in New Issue
Block a user