mirror of
https://github.com/ApfelTeeSaft/Reload-Backend.git
synced 2026-08-26 19:33:26 +00:00
Added Battle Pass and working on Challenges 👀
This commit is contained in:
@@ -0,0 +1,3 @@
|
||||
ClientSettings/
|
||||
*.Sav
|
||||
node_modules/
|
||||
@@ -0,0 +1,36 @@
|
||||
[OnlineSubsystemMcp.Xmpp]
|
||||
bUseSSL=false
|
||||
ServerAddr="ws://127.0.0.1:80"
|
||||
ServerPort=80
|
||||
|
||||
[OnlineSubsystemMcp.Xmpp Prod]
|
||||
bUseSSL=false
|
||||
ServerAddr="ws://127.0.0.1:80"
|
||||
ServerPort=80
|
||||
|
||||
[OnlineSubsystemMcp]
|
||||
bUsePartySystemV2=false
|
||||
|
||||
[OnlineSubsystemMcp.OnlinePartySystemMcpAdapter]
|
||||
bUsePartySystemV2=false
|
||||
|
||||
[CrashContextProperties]
|
||||
CrashReportClientRichText=NSLOCTEXT("FortGlobals", "FortniteCrashReportClientText", "Fortnite has crashed.")
|
||||
|
||||
[/Script/Qos.QosRegionManager]
|
||||
NumTestsPerRegion=1
|
||||
PingTimeout=3.0
|
||||
!RegionDefinitions=ClearArray
|
||||
+RegionDefinitions=(DisplayName="Na-East", RegionId="NAE", bEnabled=false, bVisible=false, bAutoAssignable=false)
|
||||
+RegionDefinitions=(DisplayName="Na-West", RegionId="NAW", bEnabled=false, bVisible=false, bAutoAssignable=false)
|
||||
+RegionDefinitions=(DisplayName="Oceania", RegionId="OCE", bEnabled=false, bVisible=false, bAutoAssignable=false)
|
||||
+RegionDefinitions=(DisplayName="Europe", RegionId="EU", bEnabled=true, bVisible=true, bAutoAssignable=true)
|
||||
+RegionDefinitions=(DisplayName="Me", RegionId="ME", bEnabled=false, bVisible=false, bAutoAssignable=false)
|
||||
+RegionDefinitions=(DisplayName="Brazil", RegionId="BR", bEnabled=false, bVisible=false, bAutoAssignable=false)
|
||||
|
||||
[XMPP]
|
||||
bEnableWebsockets=true
|
||||
|
||||
# Double Pump
|
||||
;[ConsoleVariables]
|
||||
;Weapon.TryToFireRestrictedByTypeCooldowns=0
|
||||
@@ -0,0 +1,61 @@
|
||||
[/Script/EngineSettings.GeneralProjectSettings]
|
||||
ProjectID=(A=-2011270876,B=1182903154,C=-965786730,D=-1399474123)
|
||||
ProjectName=Fortnite
|
||||
ProjectDisplayedTitle=NSLOCTEXT("", "FortniteMainWindowTitle", "Fortnite")
|
||||
ProjectVersion=1.0.0
|
||||
CompanyName=Epic Games, Inc.
|
||||
CompanyDistinguishedName="CN=Epic Games, O=Epic Games, L=Cary, S=North Carolina, C=US"
|
||||
CopyrightNotice=Copyright Epic Games, Inc. All Rights Reserved.
|
||||
bUseBorderlessWindow=True
|
||||
|
||||
[/Script/FortniteGame.FortGlobals]
|
||||
bAllowLogout=false
|
||||
|
||||
### Turbo build
|
||||
;[/Script/FortniteGame.FortPlayerController]
|
||||
;TurboBuildInterval=0.015f
|
||||
;TurboBuildFirstInterval=0.015f
|
||||
;bClientSideEditPrediction=false
|
||||
|
||||
[/Script/FortniteGame.FortTextHotfixConfig]
|
||||
+TextReplacements=(Category=Game, bIsMinimalPatch=True, Namespace="LoadingScreen", Key="Connecting", NativeString="CONNECTING", LocalizedStrings=(("en","CONNECTING TO Reload")))
|
||||
+TextReplacements=(Category=Game, bIsMinimalPatch=True, Namespace="FortLoginStatus", Key="LoggingIn", NativeString="Logging In...", LocalizedStrings=(("ar","تسجيل الدخول إلى Reload..."),("en","Logging Into Reload..."),("de","Bei Reload anmelden..."),("es","Iniciando sesión en Reload..."),("es-419","Iniciando sesión en Reload..."),("fr","Connexion à Reload..."),("it","Accesso a Reload..."),("ja","Reload にログインしています..."),("ko","Reload에 로그인하는 중..."),("pl","Logowanie do Reload..."),("pt-BR","Iniciando sesión en Reload..."),("ru","Вход в Reload..."),("tr","Reload'ye Giriş Yapılıyor..."),("zh-CN","Ngena ngemvume ku-Reload..."),("zh-Hant","Ngena ngemvume ku-Reload...")))
|
||||
+TextReplacements=(Category=Game, bIsMinimalPatch=True, Namespace="OnlineAccount", Key="DoQosPingTests", NativeString="Checking connection to datacenters...", LocalizedStrings=(("ar","جارٍ التحقق من الاتصال بـ Reload..."),("en","Checking connection to Reload..."),("de","Verbindung zu Reload wird überprüft..."),("es","Comprobando conexión a Reload..."),("es-419","Comprobando conexión a Reload..."),("fr","Vérification de la connexion à Reload..."),("it","Controllo della connessione a Reload..."),("ja","Reload への接続を確認しています..."),("ko","Reload 연결을 확인하는 중..."),("pl","Sprawdzam połączenie z Reload..."),("pt-BR","Comprobando conexión a Reload..."),("ru","Проверка подключения к Reload..."),("tr","Reload bağlantısı kontrol ediliyor..."),("zh-CN","Ihlola ukuxhumeka ku-Reload..."),("zh-Hant","Ihlola ukuxhumeka ku-Reload...")))
|
||||
+TextReplacements=(Category=Game, bIsMinimalPatch=True, Namespace="", Key="37020CCD402F073607D9D4A9561EF035", NativeString="PLAY", LocalizedStrings=(("ar","لعب Reload"),("en","Play Reload"),("de","Spielen Reload"),("es","Jugar Reload"),("es-419","Jugar Reload"),("fr","Jouer Reload"),("it","Gioca Reload"),("ja","プレイ Reload"),("ko","플레이 Reload"),("pl","Graj Reload"),("pt-BR","Jogar Reload"),("ru","Играть Reload"),("tr","Oyna Reload"),("zh-CN","玩 Reload"),("zh-Hant","玩 Reload")))
|
||||
+TextReplacements=(Category=Game, bIsMinimalPatch=True, Namespace="", Key="C8C6606D4ED4B816D4A358A42DFBDD59", NativeString="PLAY", LocalizedStrings=(("ar","لعب Reload"),("en","Play Reload"),("de","Spielen Reload"),("es","Jugar Reload"),("es-419","Jugar Reload"),("fr","Jouer Reload"),("it","Gioca Reload"),("ja","プレイ Reload"),("ko","플레이 Reload"),("pl","Graj Reload"),("pt-BR","Jogar Reload"),("ru","Играть Reload"),("tr","Oyna Reload"),("zh-CN","玩 Reload"),("zh-Hant","玩 Reload")))
|
||||
+TextReplacements=(Category=Game, bIsMinimalPatch=True, Namespace="", Key="03875FFD49212D2F37B01788C09086B5", NativeString="Quit", LocalizedStrings=(("ar","قم بإنهاء برنامج Reload"),("en","Quit Reload"),("de","Beenden Sie Reload"),("es","Salir de Reload"),("es-419","Salir de Reload"),("fr","Quitter Reload"),("it","Uscendo da Reload"),("ja","Reload を終了する"),("ko","Reload 종료"),("pl","Opuść Reload"),("pt-BR","Salir de Reload"),("ru","Выйти из Reload"),("tr","Reload'den çık"),("zh-CN","Yeka i-Reload"),("zh-Hant","Yeka i-Reload")))
|
||||
+TextReplacements=(Category=Game, bIsMinimalPatch=True, Namespace="", Key="1D20854C403FDD474AE7C8B929815DA2", NativeString="Quit", LocalizedStrings=(("ar","قم بإنهاء برنامج Reload"),("en","Quit Reload"),("de","Beenden Sie Reload"),("es","Salir de Reload"),("es-419","Salir de Reload"),("fr","Quitter Reload"),("it","Uscendo da Reload"),("ja","Reload を終了する"),("ko","Reload 종료"),("pl","Opuść Reload"),("pt-BR","Salir de Reload"),("ru","Выйти из Reload"),("tr","Reload'den çık"),("zh-CN","Yeka i-Reload"),("zh-Hant","Yeka i-Reload")))
|
||||
+TextReplacements=(Category=Game, bIsMinimalPatch=True, Namespace="", Key="1FB7052F40BE8B647B5CA5A362BE8F21", NativeString="Quit", LocalizedStrings=(("ar","قم بإنهاء برنامج Reload"),("en","Quit Reload"),("de","Beenden Sie Reload"),("es"," Salir de Reload"),("es-419","Salir de Reload"),("fr","Quitter Reload"),("it","Uscendo da Reload"),("ja","Reload を終了する"),("ko","Reload 종료"),("pl","Opuść Reload"),("pt-BR","Salir de Reload"),("ru","Выйти из Reload"),("tr","Reload'den çık"),("zh-CN","Yeka i-Reload"),("zh-Hant","Yeka i-Reload")))
|
||||
+TextReplacements=(Category=Game, bIsMinimalPatch=True, Namespace="", Key="2E42C9FB4F551A859C05BF99F7E36FB1", NativeString="Quit", LocalizedStrings=(("ar","قم بإنهاء برنامج Reload"),("en","Quit Reload"),("de","Beenden Sie Reload"),("es","Salir de Reload"),("es-419","Salir de Reload"),("fr","Quitter Reload"),("it","Uscendo da Reload"),("ja","Reload を終了する"),("ko","Reload 종료"),("pl","Opuść Reload"),("pt-BR","Salir de Reload"),("ru","Выйти из Reload"),("tr","Reload'den çık"),("zh-CN","Yeka i-Reload"),("zh-Hant","Yeka i-Reload")))
|
||||
+TextReplacements=(Category=Game, bIsMinimalPatch=True, Namespace="", Key="370415344EEEA09D8C01A48F4B8148D7", NativeString="Quit", LocalizedStrings=(("ar","قم بإنهاء برنامج Reload"),("en","Quit Reload"),("de","Beenden Sie Reload"),("es","Salir de Reload"),("es-419","Salir de Reload"),("fr","Quitter Reload"),("it","Uscendo da Reload"),("ja","Reload を終了する"),("ko","Reload 종료"),("pl","Opuść Reload"),("pt-BR","Salir de Reload"),("ru","Выйти из Reload"),("tr","Reload'den çık"),("zh-CN","Yeka i-Reload"),("zh-Hant","Yeka i-Reload")))
|
||||
+TextReplacements=(Category=Game, bIsMinimalPatch=True, Namespace="", Key="538BD1FD46BCEFA4813E2FAFAA07E1A2", NativeString="Quit", LocalizedStrings=(("ar","قم بإنهاء برنامج Reload"),("en","Quit Reload"),("de","Beenden Sie Reload"),("es","Salir de Reload"),("es-419","Salir de Reload"),("fr","Quitter Reload"),("it","Uscendo da Reload"),("ja","Reload を終了する"),("ko","Reload 종료"),("pl","Opuść Reload"),("pt-BR","Salir de Reload"),("ru","Выйти из Reload"),("tr","Reload'den çık"),("zh-CN","Yeka i-Reload"),("zh-Hant","Yeka i-Reload")))
|
||||
+TextReplacements=(Category=Game, bIsMinimalPatch=True, Namespace="FortTeamMemberPedestalNameplate", Key="NotReady", NativeString="Not Ready", LocalizedStrings=(("ar","غير جاهز"),("en","Not Ready"),("de","Nicht bereit"),("es","No listo"),("es-419","No listo"),("fr","Pas prêt"),("it","Non Pronto"),("ja","準備ができていない"),("ko","준비되지 않음"),("pl","Nie gotowy"),("pt-BR","No listo"),("ru","Не готов"),("tr","Hazır değil"),("zh-CN","Not Ready"),("zh-Hant","Not Ready")))
|
||||
|
||||
+TextReplacements=(Category=Game, bIsMinimalPatch=True, Namespace="OnlineAccount", Key="TokenExpired", NativeString="Login Expired or Logged In Elsewhere", LocalizedStrings=(("ar","تمت إعادة تشغيل الواجهة الخلفية... أعد تشغيل لعبتك"),("en","Backend Restarted... Restart your game"),("de","Backend neu gestartet... Starten Sie Ihr Spiel neu"),("es","Backend reiniciado... Reinicia tu juego"),("es-419","Backend reiniciado... Reinicia tu juego"),("fr","Backend redémarré... Redémarrez votre jeu"),("it","Backend riavviato... Riavvia il gioco"),("ja","バックエンドが再起動されました... ゲームを再起動します"),("ko","백엔드가 다시 시작되었습니다... 게임을 다시 시작하세요"),("pl","Backend został uruchomiony ponownie... Uruchom ponownie grę"),("pt-BR","Backend reiniciado... Reinicia tu juego"),("ru","Серверная часть перезапущена... Перезапустите игру."),("tr","Arka Uç Yeniden Başlatıldı... Oyununuzu yeniden başlatın"),("zh-CN","Okwasemuva Kuqaliswe kabusha... Qala kabusha igeyimu yakho"),("zh-Hant","Okwasemuva Kuqaliswe kabusha... Qala kabusha igeyimu yakho")))
|
||||
|
||||
+TextReplacements=(Category=Game, bIsMinimalPatch=True, Namespace="Fortnite.FortAthenaMatchmakingWidget", Key="Message.CanMatchmakeSolo", NativeString="PLAY!", LocalizedStrings=(("ar","برونتو"),("en","READY"),("de","BEREIT"),("es","LISTO"),("es-419","LISTO"),("fr","PRÊT"),("it","PRONTO"),("ja","準備ができて"),("ko","준비가 된"),("pl","GOTOWY"),("pt-BR","LISTO"),("ru","ГОТОВЫЙ"),("tr","HAZIR"),("zh-CN","LUNGILE"),("zh-Hant","READY")))
|
||||
|
||||
+TextReplacements=(Category=Game, bIsMinimalPatch=True, Namespace="FortOnlineAccount", Key="CreatingParty", NativeString="Creating party...", LocalizedStrings=(("en","Welcome to Reload")))
|
||||
|
||||
+TextReplacements=(Category=Game, bIsMinimalPatch=True, Namespace="", Key="2A1C56D243E8C4418146029BA30A18F4", NativeString="Battle Pass", LocalizedStrings=(("en","Reload Battle Pass")))
|
||||
|
||||
+TextReplacements=(Category=Game, bIsMinimalPatch=True, Namespace="PartyContext", Key="BattleRoyaleInLobby", NativeString="Battle Royale - In Lobby", LocalizedStrings=(("ar","Reload - Lobby"),("en","Reload - Lobby"),("de","Reload - Lobby"),("es","Reload - Lobby"),("es-419","Reload - Lobby"),("fr","Reload - Lobby"),("it","Reload - Lobby"),("ja","Reload - Lobby"),("ko","Reload - Lobby"),("pl","Reload - Lobby"),("pt-BR","Reload - Lobby"),("ru","Reload - Lobby"),("tr","Reload - Lobby"),("zh-CN","Reload - Lobby"),("zh-Hant","Reload - Lobby")))
|
||||
|
||||
+TextReplacements=(Category=Game, bIsMinimalPatch=True, Namespace="", Key="30C8C9204EAF7FF602BF51BA2914EF27", NativeString="EPIC PASSWORD", LocalizedStrings=(("en","Reload Password")))
|
||||
+TextReplacements=(Category=Game, bIsMinimalPatch=True, Namespace="", Key="CA2EC1714F23111FDBE6439EBC961404", NativeString="EMAIL", LocalizedStrings=(("en","Reload Email")))
|
||||
|
||||
+TextReplacements=(Category=Game, bIsMinimalPatch=True, Namespace="", Key="40D1ADD648EDBD000A8F7E88E8D90341", NativeString="ITEM SHOP", LocalizedStrings=(("en","Item Shop")))
|
||||
|
||||
[/Script/FortniteGame.FortGameInstance]
|
||||
!FrontEndPlaylistData=ClearArray
|
||||
+FrontEndPlaylistData=(PlaylistName=Playlist_DefaultSolo, PlaylistAccess=(bEnabled=True, bIsDefaultPlaylist=true, bVisibleWhenDisabled=false, bDisplayAsNew=false, CategoryIndex=0, bDisplayAsLimitedTime=false, DisplayPriority=0))
|
||||
+FrontEndPlaylistData=(PlaylistName=Playlist_DefaultDuo, PlaylistAccess=(bEnabled=False, bIsDefaultPlaylist=false, bVisibleWhenDisabled=false, bDisplayAsNew=false, CategoryIndex=0, bDisplayAsLimitedTime=false, DisplayPriority=1))
|
||||
+FrontEndPlaylistData=(PlaylistName=Playlist_Trios, PlaylistAccess=(bEnabled=False, bIsDefaultPlaylist=false, bVisibleWhenDisabled=false, bDisplayAsNew=false, CategoryIndex=0, bDisplayAsLimitedTime=false, DisplayPriority=2))
|
||||
+FrontEndPlaylistData=(PlaylistName=Playlist_DefaultSquad, PlaylistAccess=(bEnabled=False, bIsDefaultPlaylist=false, bVisibleWhenDisabled=false, bDisplayAsNew=false, CategoryIndex=0, bDisplayAsLimitedTime=false, DisplayPriority=3))
|
||||
+FrontEndPlaylistData=(PlaylistName=Playlist_Playground, PlaylistAccess=(bEnabled=False, bIsDefaultPlaylist=false, bVisibleWhenDisabled=false, bDisplayAsNew=false, CategoryIndex=1, bDisplayAsLimitedTime=true, DisplayPriority=0))
|
||||
|
||||
[/Script/FortniteGame.FortChatManager]
|
||||
bShouldRequestGeneralChatRooms=true
|
||||
bShouldJoinGlobalChat=true
|
||||
bShouldJoinFounderChat=false
|
||||
bIsAthenaGlobalChatEnabled=true
|
||||
@@ -0,0 +1,3 @@
|
||||
[/Script/Engine.InputSettings]
|
||||
+ConsoleKeys=Tilde
|
||||
+ConsoleKeys=F8
|
||||
@@ -0,0 +1,8 @@
|
||||
[/Script/FortniteGame.FortRuntimeOptions]
|
||||
bEnableGlobalChat=false
|
||||
bDisableGifting=false
|
||||
bDisableGiftingPC=false
|
||||
bDisableGiftingPS4=false
|
||||
bDisableGiftingXB=false
|
||||
!ExperimentalCohortPercent=ClearArray
|
||||
+ExperimentalCohortPercent=(CohortPercent=100,ExperimentNum=20)
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,520 @@
|
||||
{
|
||||
"created": "2022-01-08T22:58:06.983Z",
|
||||
"updated": "2022-01-08T22:58:57.261Z",
|
||||
"rvn": 1,
|
||||
"wipeNumber": 1,
|
||||
"accountId": "",
|
||||
"profileId": "athena",
|
||||
"version": "no_version",
|
||||
"items": {
|
||||
"sandbox_loadout": {
|
||||
"templateId": "CosmeticLocker:cosmeticlocker_athena",
|
||||
"attributes": {
|
||||
"locker_slots_data": {
|
||||
"slots": {
|
||||
"Pickaxe": {
|
||||
"items": [
|
||||
"AthenaPickaxe:DefaultPickaxe"
|
||||
],
|
||||
"activeVariants": []
|
||||
},
|
||||
"Dance": {
|
||||
"items": [
|
||||
"AthenaDance:EID_BoogieDown",
|
||||
"AthenaDance:EID_DanceMoves",
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
""
|
||||
]
|
||||
},
|
||||
"Glider": {
|
||||
"items": [
|
||||
"AthenaGlider:DefaultGlider"
|
||||
]
|
||||
},
|
||||
"Character": {
|
||||
"items": [
|
||||
"AthenaCharacter:CID_001_Athena_Commando_F_Default"
|
||||
],
|
||||
"activeVariants": [
|
||||
{
|
||||
"variants": []
|
||||
}
|
||||
]
|
||||
},
|
||||
"Backpack": {
|
||||
"items": [
|
||||
""
|
||||
],
|
||||
"activeVariants": [
|
||||
{
|
||||
"variants": []
|
||||
}
|
||||
]
|
||||
},
|
||||
"ItemWrap": {
|
||||
"items": [
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
""
|
||||
],
|
||||
"activeVariants": [
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null
|
||||
]
|
||||
},
|
||||
"LoadingScreen": {
|
||||
"items": [
|
||||
""
|
||||
],
|
||||
"activeVariants": [
|
||||
null
|
||||
]
|
||||
},
|
||||
"MusicPack": {
|
||||
"items": [
|
||||
""
|
||||
],
|
||||
"activeVariants": [
|
||||
null
|
||||
]
|
||||
},
|
||||
"SkyDiveContrail": {
|
||||
"items": [
|
||||
""
|
||||
],
|
||||
"activeVariants": [
|
||||
null
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
"use_count": 1,
|
||||
"banner_icon_template": "",
|
||||
"locker_name": "",
|
||||
"banner_color_template": "",
|
||||
"item_seen": false,
|
||||
"favorite": false
|
||||
},
|
||||
"quantity": 1
|
||||
},
|
||||
"momentum0-loadout": {
|
||||
"templateId": "CosmeticLocker:cosmeticlocker_athena",
|
||||
"attributes": {
|
||||
"locker_slots_data": {
|
||||
"slots": {
|
||||
"Pickaxe": {
|
||||
"items": [
|
||||
""
|
||||
],
|
||||
"activeVariants": []
|
||||
},
|
||||
"Dance": {
|
||||
"items": [
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
""
|
||||
]
|
||||
},
|
||||
"Glider": {
|
||||
"items": [
|
||||
""
|
||||
]
|
||||
},
|
||||
"Character": {
|
||||
"items": [
|
||||
""
|
||||
],
|
||||
"activeVariants": [
|
||||
{
|
||||
"variants": []
|
||||
}
|
||||
]
|
||||
},
|
||||
"Backpack": {
|
||||
"items": [
|
||||
""
|
||||
],
|
||||
"activeVariants": [
|
||||
{
|
||||
"variants": []
|
||||
}
|
||||
]
|
||||
},
|
||||
"ItemWrap": {
|
||||
"items": [
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
""
|
||||
],
|
||||
"activeVariants": [
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null
|
||||
]
|
||||
},
|
||||
"LoadingScreen": {
|
||||
"items": [
|
||||
""
|
||||
],
|
||||
"activeVariants": [
|
||||
null
|
||||
]
|
||||
},
|
||||
"MusicPack": {
|
||||
"items": [
|
||||
""
|
||||
],
|
||||
"activeVariants": [
|
||||
null
|
||||
]
|
||||
},
|
||||
"SkyDiveContrail": {
|
||||
"items": [
|
||||
""
|
||||
],
|
||||
"activeVariants": [
|
||||
null
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
"use_count": 1,
|
||||
"banner_icon_template": "",
|
||||
"locker_name": "MOMENTUM",
|
||||
"banner_color_template": "",
|
||||
"item_seen": false,
|
||||
"favorite": false
|
||||
},
|
||||
"quantity": 1
|
||||
},
|
||||
"AthenaCharacter:CID_001_Athena_Commando_F_Default": {
|
||||
"attributes": {
|
||||
"favorite": false,
|
||||
"item_seen": true,
|
||||
"level": 0,
|
||||
"max_level_bonus": 0,
|
||||
"rnd_sel_cnt": 0,
|
||||
"variants": [],
|
||||
"xp": 0
|
||||
},
|
||||
"templateId": "AthenaCharacter:CID_001_Athena_Commando_F_Default"
|
||||
},
|
||||
"AthenaCharacter:CID_002_Athena_Commando_F_Default": {
|
||||
"attributes": {
|
||||
"favorite": false,
|
||||
"item_seen": true,
|
||||
"level": 0,
|
||||
"max_level_bonus": 0,
|
||||
"rnd_sel_cnt": 0,
|
||||
"variants": [],
|
||||
"xp": 0
|
||||
},
|
||||
"templateId": "AthenaCharacter:CID_002_Athena_Commando_F_Default"
|
||||
},
|
||||
"AthenaCharacter:CID_003_Athena_Commando_F_Default": {
|
||||
"attributes": {
|
||||
"favorite": false,
|
||||
"item_seen": true,
|
||||
"level": 0,
|
||||
"max_level_bonus": 0,
|
||||
"rnd_sel_cnt": 0,
|
||||
"variants": [],
|
||||
"xp": 0
|
||||
},
|
||||
"templateId": "AthenaCharacter:CID_003_Athena_Commando_F_Default"
|
||||
},
|
||||
"AthenaCharacter:CID_004_Athena_Commando_F_Default": {
|
||||
"attributes": {
|
||||
"favorite": false,
|
||||
"item_seen": true,
|
||||
"level": 0,
|
||||
"max_level_bonus": 0,
|
||||
"rnd_sel_cnt": 0,
|
||||
"variants": [],
|
||||
"xp": 0
|
||||
},
|
||||
"templateId": "AthenaCharacter:CID_004_Athena_Commando_F_Default"
|
||||
},
|
||||
"AthenaCharacter:CID_005_Athena_Commando_M_Default": {
|
||||
"attributes": {
|
||||
"favorite": false,
|
||||
"item_seen": true,
|
||||
"level": 0,
|
||||
"max_level_bonus": 0,
|
||||
"rnd_sel_cnt": 0,
|
||||
"variants": [],
|
||||
"xp": 0
|
||||
},
|
||||
"templateId": "AthenaCharacter:CID_005_Athena_Commando_M_Default"
|
||||
},
|
||||
"AthenaCharacter:CID_006_Athena_Commando_M_Default": {
|
||||
"attributes": {
|
||||
"favorite": false,
|
||||
"item_seen": true,
|
||||
"level": 0,
|
||||
"max_level_bonus": 0,
|
||||
"rnd_sel_cnt": 0,
|
||||
"variants": [],
|
||||
"xp": 0
|
||||
},
|
||||
"templateId": "AthenaCharacter:CID_006_Athena_Commando_M_Default"
|
||||
},
|
||||
"AthenaCharacter:CID_007_Athena_Commando_M_Default": {
|
||||
"attributes": {
|
||||
"favorite": false,
|
||||
"item_seen": true,
|
||||
"level": 0,
|
||||
"max_level_bonus": 0,
|
||||
"rnd_sel_cnt": 0,
|
||||
"variants": [],
|
||||
"xp": 0
|
||||
},
|
||||
"templateId": "AthenaCharacter:CID_007_Athena_Commando_M_Default"
|
||||
},
|
||||
"AthenaCharacter:CID_008_Athena_Commando_M_Default": {
|
||||
"attributes": {
|
||||
"favorite": false,
|
||||
"item_seen": true,
|
||||
"level": 0,
|
||||
"max_level_bonus": 0,
|
||||
"rnd_sel_cnt": 0,
|
||||
"variants": [],
|
||||
"xp": 0
|
||||
},
|
||||
"templateId": "AthenaCharacter:CID_008_Athena_Commando_M_Default"
|
||||
},
|
||||
"AthenaCharacter:CID_556_Athena_Commando_F_RebirthDefaultA": {
|
||||
"attributes": {
|
||||
"favorite": false,
|
||||
"item_seen": true,
|
||||
"level": 0,
|
||||
"max_level_bonus": 0,
|
||||
"rnd_sel_cnt": 0,
|
||||
"variants": [],
|
||||
"xp": 0
|
||||
},
|
||||
"templateId": "AthenaCharacter:CID_556_Athena_Commando_F_RebirthDefaultA"
|
||||
},
|
||||
"AthenaCharacter:CID_557_Athena_Commando_F_RebirthDefaultB": {
|
||||
"attributes": {
|
||||
"favorite": false,
|
||||
"item_seen": true,
|
||||
"level": 0,
|
||||
"max_level_bonus": 0,
|
||||
"rnd_sel_cnt": 0,
|
||||
"variants": [],
|
||||
"xp": 0
|
||||
},
|
||||
"templateId": "AthenaCharacter:CID_557_Athena_Commando_F_RebirthDefaultB"
|
||||
},
|
||||
"AthenaCharacter:CID_558_Athena_Commando_F_RebirthDefaultC": {
|
||||
"attributes": {
|
||||
"favorite": false,
|
||||
"item_seen": true,
|
||||
"level": 0,
|
||||
"max_level_bonus": 0,
|
||||
"rnd_sel_cnt": 0,
|
||||
"variants": [],
|
||||
"xp": 0
|
||||
},
|
||||
"templateId": "AthenaCharacter:CID_558_Athena_Commando_F_RebirthDefaultC"
|
||||
},
|
||||
"AthenaCharacter:CID_559_Athena_Commando_F_RebirthDefaultD": {
|
||||
"attributes": {
|
||||
"favorite": false,
|
||||
"item_seen": true,
|
||||
"level": 0,
|
||||
"max_level_bonus": 0,
|
||||
"rnd_sel_cnt": 0,
|
||||
"variants": [],
|
||||
"xp": 0
|
||||
},
|
||||
"templateId": "AthenaCharacter:CID_559_Athena_Commando_F_RebirthDefaultD"
|
||||
},
|
||||
"AthenaCharacter:CID_560_Athena_Commando_M_RebirthDefaultA": {
|
||||
"attributes": {
|
||||
"favorite": false,
|
||||
"item_seen": true,
|
||||
"level": 0,
|
||||
"max_level_bonus": 0,
|
||||
"rnd_sel_cnt": 0,
|
||||
"variants": [],
|
||||
"xp": 0
|
||||
},
|
||||
"templateId": "AthenaCharacter:CID_560_Athena_Commando_M_RebirthDefaultA"
|
||||
},
|
||||
"AthenaCharacter:CID_561_Athena_Commando_M_RebirthDefaultB": {
|
||||
"attributes": {
|
||||
"favorite": false,
|
||||
"item_seen": true,
|
||||
"level": 0,
|
||||
"max_level_bonus": 0,
|
||||
"rnd_sel_cnt": 0,
|
||||
"variants": [],
|
||||
"xp": 0
|
||||
},
|
||||
"templateId": "AthenaCharacter:CID_561_Athena_Commando_M_RebirthDefaultB"
|
||||
},
|
||||
"AthenaCharacter:CID_562_Athena_Commando_M_RebirthDefaultC": {
|
||||
"attributes": {
|
||||
"favorite": false,
|
||||
"item_seen": true,
|
||||
"level": 0,
|
||||
"max_level_bonus": 0,
|
||||
"rnd_sel_cnt": 0,
|
||||
"variants": [],
|
||||
"xp": 0
|
||||
},
|
||||
"templateId": "AthenaCharacter:CID_562_Athena_Commando_M_RebirthDefaultC"
|
||||
},
|
||||
"AthenaCharacter:CID_563_Athena_Commando_M_RebirthDefaultD": {
|
||||
"attributes": {
|
||||
"favorite": false,
|
||||
"item_seen": true,
|
||||
"level": 0,
|
||||
"max_level_bonus": 0,
|
||||
"rnd_sel_cnt": 0,
|
||||
"variants": [],
|
||||
"xp": 0
|
||||
},
|
||||
"templateId": "AthenaCharacter:CID_563_Athena_Commando_M_RebirthDefaultD"
|
||||
},
|
||||
"AthenaCharacter:cid_a_272_athena_commando_f_prime": {
|
||||
"attributes": {
|
||||
"favorite": false,
|
||||
"item_seen": true,
|
||||
"level": 0,
|
||||
"max_level_bonus": 0,
|
||||
"rnd_sel_cnt": 0,
|
||||
"variants": [],
|
||||
"xp": 0
|
||||
},
|
||||
"templateId": "AthenaCharacter:cid_a_272_athena_commando_f_prime"
|
||||
},
|
||||
"AthenaPickaxe:DefaultPickaxe": {
|
||||
"attributes": {
|
||||
"favorite": false,
|
||||
"item_seen": true,
|
||||
"level": 0,
|
||||
"max_level_bonus": 0,
|
||||
"rnd_sel_cnt": 0,
|
||||
"variants": [],
|
||||
"xp": 0
|
||||
},
|
||||
"templateId": "AthenaPickaxe:DefaultPickaxe"
|
||||
},
|
||||
"AthenaGlider:DefaultGlider": {
|
||||
"attributes": {
|
||||
"favorite": false,
|
||||
"item_seen": true,
|
||||
"level": 0,
|
||||
"max_level_bonus": 0,
|
||||
"rnd_sel_cnt": 0,
|
||||
"variants": [],
|
||||
"xp": 0
|
||||
},
|
||||
"templateId": "AthenaGlider:DefaultGlider"
|
||||
},
|
||||
"AthenaDance:EID_DanceMoves": {
|
||||
"attributes": {
|
||||
"favorite": false,
|
||||
"item_seen": true,
|
||||
"level": 0,
|
||||
"max_level_bonus": 0,
|
||||
"rnd_sel_cnt": 0,
|
||||
"variants": [],
|
||||
"xp": 0
|
||||
},
|
||||
"templateId": "AthenaDance:EID_DanceMoves"
|
||||
},
|
||||
"AthenaDance:EID_BoogieDown": {
|
||||
"attributes": {
|
||||
"favorite": false,
|
||||
"item_seen": true,
|
||||
"level": 0,
|
||||
"max_level_bonus": 0,
|
||||
"rnd_sel_cnt": 0,
|
||||
"variants": [],
|
||||
"xp": 0
|
||||
},
|
||||
"templateId": "AthenaDance:EID_BoogieDown"
|
||||
}
|
||||
},
|
||||
"stats": {
|
||||
"attributes": {
|
||||
"season_match_boost": 0,
|
||||
"loadouts": [
|
||||
"sandbox_loadout",
|
||||
"momentum0-loadout"
|
||||
],
|
||||
"rested_xp_overflow": 0,
|
||||
"mfa_reward_claimed": true,
|
||||
"quest_manager": {
|
||||
"dailyLoginInterval": "0001-01-01T00:00:00.000Z",
|
||||
"dailyQuestRerolls": 1
|
||||
},
|
||||
"book_level": 1,
|
||||
"season_num": 16,
|
||||
"season_update": 1,
|
||||
"book_xp": 1,
|
||||
"permissions": [],
|
||||
"book_purchased": false,
|
||||
"lifetime_wins": 0,
|
||||
"party_assist_quest": "",
|
||||
"purchased_battle_pass_tier_offers": [],
|
||||
"rested_xp_exchange": 0.333,
|
||||
"level": 1,
|
||||
"xp_overflow": 0,
|
||||
"rested_xp": 0,
|
||||
"rested_xp_mult": 0,
|
||||
"accountLevel": 0,
|
||||
"competitive_identity": {},
|
||||
"inventory_limit_bonus": 0,
|
||||
"last_applied_loadout": "sandbox_loadout",
|
||||
"daily_rewards": {},
|
||||
"xp": 0,
|
||||
"season_friend_match_boost": 1,
|
||||
"active_loadout_index": 1,
|
||||
"favorite_musicpack": "",
|
||||
"favorite_glider": "",
|
||||
"favorite_pickaxe": "",
|
||||
"favorite_skydivecontrail": "",
|
||||
"favorite_backpack": "",
|
||||
"pinned_quest": "",
|
||||
"favorite_dance": [
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
""
|
||||
],
|
||||
"favorite_itemwraps": [],
|
||||
"favorite_character": "",
|
||||
"favorite_loadingscreen": ""
|
||||
}
|
||||
},
|
||||
"commandRevision": 5
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
{
|
||||
"created": "",
|
||||
"updated": "",
|
||||
"rvn": 0,
|
||||
"wipeNumber": 1,
|
||||
"accountId": "",
|
||||
"profileId": "campaign",
|
||||
"version": "no_version",
|
||||
"items": {
|
||||
"Token:reloadbackend": {
|
||||
"templateId": "Token:reloadbackend",
|
||||
"attributes": {
|
||||
"item_seen": true
|
||||
},
|
||||
"quantity": 1
|
||||
}
|
||||
},
|
||||
"stats": {
|
||||
"attributes": {
|
||||
"inventory_limit_bonus": 0
|
||||
}
|
||||
},
|
||||
"commandRevision": 0
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
{
|
||||
"created": "",
|
||||
"updated": "",
|
||||
"rvn": 0,
|
||||
"wipeNumber": 1,
|
||||
"accountId": "",
|
||||
"profileId": "collection_book_people0",
|
||||
"version": "no_version",
|
||||
"items": {
|
||||
"Token:reloadbackend": {
|
||||
"templateId": "Token:reloadbackend",
|
||||
"attributes": {
|
||||
"item_seen": true
|
||||
},
|
||||
"quantity": 1
|
||||
}
|
||||
},
|
||||
"stats": {
|
||||
"attributes": {
|
||||
"inventory_limit_bonus": 0
|
||||
}
|
||||
},
|
||||
"commandRevision": 0
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
{
|
||||
"created": "",
|
||||
"updated": "",
|
||||
"rvn": 0,
|
||||
"wipeNumber": 1,
|
||||
"accountId": "",
|
||||
"profileId": "collection_book_schematics0",
|
||||
"version": "no_version",
|
||||
"items": {
|
||||
"Token:reloadbackend": {
|
||||
"templateId": "Token:reloadbackend",
|
||||
"attributes": {
|
||||
"item_seen": true
|
||||
},
|
||||
"quantity": 1
|
||||
}
|
||||
},
|
||||
"stats": {
|
||||
"attributes": {
|
||||
"inventory_limit_bonus": 0
|
||||
}
|
||||
},
|
||||
"commandRevision": 0
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
{
|
||||
"created": "",
|
||||
"updated": "",
|
||||
"rvn": 0,
|
||||
"wipeNumber": 1,
|
||||
"accountId": "",
|
||||
"profileId": "collections",
|
||||
"version": "no_version",
|
||||
"items": {
|
||||
"Token:reloadbackend": {
|
||||
"templateId": "Token:reloadbackend",
|
||||
"attributes": {
|
||||
"item_seen": true
|
||||
},
|
||||
"quantity": 1
|
||||
}
|
||||
},
|
||||
"stats": {
|
||||
"attributes": {
|
||||
"inventory_limit_bonus": 0
|
||||
}
|
||||
},
|
||||
"commandRevision": 0
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,24 @@
|
||||
{
|
||||
"created": "",
|
||||
"updated": "",
|
||||
"rvn": 0,
|
||||
"wipeNumber": 1,
|
||||
"accountId": "",
|
||||
"profileId": "common_public",
|
||||
"version": "no_version",
|
||||
"items": {
|
||||
"Token:reloadbackend": {
|
||||
"templateId": "Token:reloadbackend",
|
||||
"attributes": {
|
||||
"item_seen": true
|
||||
},
|
||||
"quantity": 1
|
||||
}
|
||||
},
|
||||
"stats": {
|
||||
"attributes": {
|
||||
"inventory_limit_bonus": 0
|
||||
}
|
||||
},
|
||||
"commandRevision": 0
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
{
|
||||
"created": "",
|
||||
"updated": "",
|
||||
"rvn": 0,
|
||||
"wipeNumber": 1,
|
||||
"accountId": "",
|
||||
"profileId": "creative",
|
||||
"version": "no_version",
|
||||
"items": {
|
||||
"Token:reloadbackend": {
|
||||
"templateId": "Token:reloadbackend",
|
||||
"attributes": {
|
||||
"item_seen": true
|
||||
},
|
||||
"quantity": 1
|
||||
}
|
||||
},
|
||||
"stats": {
|
||||
"attributes": {
|
||||
"inventory_limit_bonus": 0
|
||||
}
|
||||
},
|
||||
"commandRevision": 0
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
{
|
||||
"created": "",
|
||||
"updated": "",
|
||||
"rvn": 0,
|
||||
"wipeNumber": 1,
|
||||
"accountId": "",
|
||||
"profileId": "metadata",
|
||||
"version": "no_version",
|
||||
"items": {
|
||||
"Token:reloadbackend": {
|
||||
"templateId": "Token:reloadbackend",
|
||||
"attributes": {
|
||||
"item_seen": true
|
||||
},
|
||||
"quantity": 1
|
||||
}
|
||||
},
|
||||
"stats": {
|
||||
"attributes": {
|
||||
"inventory_limit_bonus": 0
|
||||
}
|
||||
},
|
||||
"commandRevision": 0
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
{
|
||||
"created": "",
|
||||
"updated": "",
|
||||
"rvn": 0,
|
||||
"wipeNumber": 1,
|
||||
"accountId": "",
|
||||
"profileId": "outpost0",
|
||||
"version": "no_version",
|
||||
"items": {
|
||||
"Token:reloadbackend": {
|
||||
"templateId": "Token:reloadbackend",
|
||||
"attributes": {
|
||||
"item_seen": true
|
||||
},
|
||||
"quantity": 1
|
||||
}
|
||||
},
|
||||
"stats": {
|
||||
"attributes": {
|
||||
"inventory_limit_bonus": 0
|
||||
}
|
||||
},
|
||||
"commandRevision": 0
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,24 @@
|
||||
{
|
||||
"created": "",
|
||||
"updated": "",
|
||||
"rvn": 0,
|
||||
"wipeNumber": 1,
|
||||
"accountId": "",
|
||||
"profileId": "theater0",
|
||||
"version": "no_version",
|
||||
"items": {
|
||||
"Token:reloadbackend": {
|
||||
"templateId": "Token:reloadbackend",
|
||||
"attributes": {
|
||||
"item_seen": true
|
||||
},
|
||||
"quantity": 1
|
||||
}
|
||||
},
|
||||
"stats": {
|
||||
"attributes": {
|
||||
"inventory_limit_bonus": 0
|
||||
}
|
||||
},
|
||||
"commandRevision": 0
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
{
|
||||
"//": "BR Item Shop Config",
|
||||
"daily1": {
|
||||
"itemGrants": [""],
|
||||
"price": 0
|
||||
},
|
||||
"daily2": {
|
||||
"itemGrants": [""],
|
||||
"price": 0
|
||||
},
|
||||
"daily3": {
|
||||
"itemGrants": [""],
|
||||
"price": 0
|
||||
},
|
||||
"daily4": {
|
||||
"itemGrants": [""],
|
||||
"price": 0
|
||||
},
|
||||
"daily5": {
|
||||
"itemGrants": [""],
|
||||
"price": 0
|
||||
},
|
||||
"daily6": {
|
||||
"itemGrants": [""],
|
||||
"price": 0
|
||||
},
|
||||
"featured1": {
|
||||
"itemGrants": [""],
|
||||
"price": 0
|
||||
},
|
||||
"featured2": {
|
||||
"itemGrants": [""],
|
||||
"price": 0
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
{
|
||||
"moderators": ["discordId"],
|
||||
"discord": {
|
||||
"bot_token": ""
|
||||
},
|
||||
"mongodb": {
|
||||
"database": "mongodb://127.0.0.1/Reload"
|
||||
},
|
||||
"chat": {
|
||||
"//": "Disabling global chat can help the server to perform faster as less resources are used.",
|
||||
"EnableGlobalChat": false
|
||||
},
|
||||
|
||||
"port": 3551,
|
||||
"matchmakerIP": "127.0.0.1:80",
|
||||
"gameServerIP": "127.0.0.1:7777",
|
||||
|
||||
"//": "For 'BattlePassSeason' enter only the number of your season (from 2 to 10)",
|
||||
"EnableBattlepass": false,
|
||||
"BattlePassSeason": 2,
|
||||
|
||||
"//": "If bCompletedSeasonalQuests is set to 'true' it will set all quests except daily quests as completed",
|
||||
"bCompletedSeasonalQuests": false
|
||||
}
|
||||
@@ -0,0 +1,60 @@
|
||||
const path = require("path");
|
||||
const fs = require("fs");
|
||||
const Users = require('../../../model/user.js');
|
||||
const Profiles = require('../../../model/profiles.js');
|
||||
const destr = require("destr");
|
||||
const config = require('../../../Config/config.json')
|
||||
|
||||
module.exports = {
|
||||
commandInfo: {
|
||||
name: "addall",
|
||||
description: "Allows you to give a user all cosmetics. Note: This will reset all your lockers to default",
|
||||
options: [
|
||||
{
|
||||
name: "user",
|
||||
description: "The user you want to give the cosmetic to",
|
||||
required: true,
|
||||
type: 6
|
||||
}
|
||||
]
|
||||
},
|
||||
execute: async (interaction) => {
|
||||
|
||||
if (!config.moderators.includes(interaction.user.id)) {
|
||||
console.log("User does not have moderator permissions.");
|
||||
return interaction.reply({ content: "You do not have moderator permissions.", ephemeral: true });
|
||||
}
|
||||
|
||||
await interaction.deferReply({ ephemeral: true });
|
||||
|
||||
const selectedUser = interaction.options.getUser('user');
|
||||
const selectedUserId = selectedUser?.id;
|
||||
try {
|
||||
const targetUser = await Users.findOne({ discordId: selectedUserId });
|
||||
if (!targetUser) {
|
||||
return interaction.editReply({ content: "That user does not own an account" });
|
||||
}
|
||||
|
||||
const profile = await Profiles.findOne({ accountId: targetUser.accountId });
|
||||
if (!profile) {
|
||||
return interaction.editReply({ content: "That user does not have a profile" });
|
||||
}
|
||||
|
||||
const allItems = destr(fs.readFileSync(path.join(__dirname, "../../../Config/DefaultProfiles/allathena.json"), 'utf8'));
|
||||
if (!allItems) {
|
||||
return interaction.editReply({ content: "Failed to parse allathena.json" });
|
||||
}
|
||||
|
||||
Profiles.findOneAndUpdate({ accountId: targetUser.accountId }, { $set: { "profiles.athena.items": allItems.items } }, { new: true }, (err, doc) => {
|
||||
if (err) {
|
||||
return interaction.editReply({ content: "There was an error updating the profile." });
|
||||
}
|
||||
});
|
||||
|
||||
await interaction.editReply({ content: "Successfully added all skins to the selected account" });
|
||||
} catch (error) {
|
||||
console.error("An error occurred:", error);
|
||||
interaction.editReply({ content: "An error occurred while processing the request." });
|
||||
}
|
||||
}
|
||||
};
|
||||
@@ -0,0 +1,43 @@
|
||||
const Users = require('../../../model/user');
|
||||
const Profiles = require('../../../model/profiles');
|
||||
const config = require('../../../Config/config.json')
|
||||
|
||||
module.exports = {
|
||||
commandInfo: {
|
||||
name: "addvbucks",
|
||||
description: "Lets you change a users amount of vbucks",
|
||||
options: [
|
||||
{
|
||||
name: "user",
|
||||
description: "The user you want to change the vbucks of",
|
||||
required: true,
|
||||
type: 6
|
||||
},
|
||||
{
|
||||
name: "vbucks",
|
||||
description: "The amount of vbucks you want to give (Can be a negative number to take vbucks)",
|
||||
required: true,
|
||||
type: 4
|
||||
}
|
||||
]
|
||||
},
|
||||
execute: async (interaction) => {
|
||||
|
||||
if (!config.moderators.includes(interaction.user.id)) {
|
||||
console.log("User does not have moderator permissions.");
|
||||
return interaction.reply({ content: "You do not have moderator permissions.", ephemeral: true });
|
||||
}
|
||||
|
||||
const selectedUser = interaction.options.getUser('user');
|
||||
const selectedUserId = selectedUser?.id;
|
||||
const user = await Users.findOne({ discordId: selectedUserId });
|
||||
if (!user)
|
||||
return interaction.reply({ content: "That user does not own an account", ephemeral: true });
|
||||
const vbucks = parseInt(interaction.options.getInteger('vbucks'));
|
||||
const profile = await Profiles.findOneAndUpdate({ accountId: user.accountId }, { $inc: { 'profiles.common_core.items.Currency:MtxPurchased.quantity': vbucks } });
|
||||
if (!profile)
|
||||
return interaction.reply({ content: "That user does not own an account", ephemeral: true });
|
||||
|
||||
await interaction.reply({ content: "Successfully changed the amount of vbucks for <@" + selectedUserId + "> by **" + vbucks + "**", ephemeral: true });
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,57 @@
|
||||
const User = require("../../../model/user.js");
|
||||
const functions = require("../../../structs/functions.js");
|
||||
const fs = require("fs");
|
||||
const config = JSON.parse(fs.readFileSync("./Config/config.json").toString());
|
||||
|
||||
module.exports = {
|
||||
commandInfo: {
|
||||
name: "ban",
|
||||
description: "Ban a user from the backend by their username.",
|
||||
options: [
|
||||
{
|
||||
name: "username",
|
||||
description: "Target username.",
|
||||
required: true,
|
||||
type: 3 // string
|
||||
}
|
||||
]
|
||||
},
|
||||
execute: async (interaction) => {
|
||||
await interaction.deferReply({ ephemeral: true });
|
||||
|
||||
const userRoles = interaction.member.roles.cache.map(role => role.id);
|
||||
const hasModeratorRole = userRoles.some(roleId => config.realmoderatorsrole && config.realmoderatorsrole.includes(roleId));
|
||||
|
||||
if (!config.moderators.includes(interaction.user.id) && !hasModeratorRole) {
|
||||
return interaction.editReply({ content: "You do not have moderator permissions.", ephemeral: true });
|
||||
}
|
||||
|
||||
const { options } = interaction;
|
||||
const targetUser = await User.findOne({ username_lower: (options.get("username").value).toLowerCase() });
|
||||
|
||||
if (!targetUser) return interaction.editReply({ content: "The account username you entered does not exist.", ephemeral: true });
|
||||
else if (targetUser.banned) return interaction.editReply({ content: "This account is already banned.", ephemeral: true });
|
||||
|
||||
await targetUser.updateOne({ $set: { banned: true } });
|
||||
|
||||
let refreshToken = global.refreshTokens.findIndex(i => i.accountId == targetUser.accountId);
|
||||
if (refreshToken != -1) global.refreshTokens.splice(refreshToken, 1);
|
||||
|
||||
let accessToken = global.accessTokens.findIndex(i => i.accountId == targetUser.accountId);
|
||||
if (accessToken != -1) {
|
||||
global.accessTokens.splice(accessToken, 1);
|
||||
|
||||
let xmppClient = global.Clients.find(client => client.accountId == targetUser.accountId);
|
||||
if (xmppClient) xmppClient.client.close();
|
||||
}
|
||||
|
||||
if (accessToken != -1 || refreshToken != -1) functions.UpdateTokens();
|
||||
|
||||
interaction.editReply({ content: `Successfully banned ${targetUser.username}`, ephemeral: true });
|
||||
|
||||
const logChannel = interaction.client.channels.cache.get(config.logChannelBanId);
|
||||
if (logChannel) {
|
||||
logChannel.send(`<@${interaction.user.id}> / ${interaction.user.tag} has banned **${targetUser.username}**`);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,50 @@
|
||||
const { MessageEmbed, PermissionFlagsBits, SlashCommandBuilder } = require("discord.js");
|
||||
const Users = require('../../../model/user.js');
|
||||
const Profiles = require('../../../model/profiles.js');
|
||||
const config = require('../../../Config/config.json')
|
||||
|
||||
module.exports = {
|
||||
commandInfo: {
|
||||
name: "delete",
|
||||
description: "Deletes a users account",
|
||||
options: [
|
||||
{
|
||||
name: "username",
|
||||
description: "Target username.",
|
||||
required: true,
|
||||
type: 6
|
||||
}
|
||||
]
|
||||
},
|
||||
execute: async (interaction) => {
|
||||
|
||||
if (!config.moderators.includes(interaction.user.id)) {
|
||||
console.log("User does not have moderator permissions.");
|
||||
return interaction.reply({ content: "You do not have moderator permissions.", ephemeral: true });
|
||||
}
|
||||
|
||||
const discordId = interaction.options.getUser('username').id;
|
||||
const user = interaction.options.getUser('username');
|
||||
const deleteAccount = await Users.findOne({ discordId: discordId })
|
||||
|
||||
if (deleteAccount == null) {
|
||||
await interaction.reply({ content: "The selected user does not have **an account**", ephemeral: true });
|
||||
return;
|
||||
}
|
||||
|
||||
await Users.deleteOne({ discordId: discordId })
|
||||
await Profiles.deleteOne({ discordId: discordId })
|
||||
|
||||
const embed = new MessageEmbed()
|
||||
.setTitle("Account deleted")
|
||||
.setDescription("The account has been **deleted**")
|
||||
.setColor("GREEN")
|
||||
.setFooter({
|
||||
text: "Reload Backend",
|
||||
iconURL: "https://cdn.discordapp.com/attachments/1252374830225948672/1263993256136675378/IMG_1736.png?ex=669c40f4&is=669aef74&hm=5ded3e4588c05a56f271e0a07f7631317a3ebd72eae7497c4de5ee712a4db6dd&"
|
||||
})
|
||||
.setTimestamp();
|
||||
await interaction.reply({ embeds: [embed], ephemeral: true });
|
||||
await interaction.options.getUser('username').send({ content: "Your account has been deleted by an **administrator**" });
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,58 @@
|
||||
const User = require("../../../model/user.js");
|
||||
const functions = require("../../../structs/functions.js");
|
||||
const fs = require("fs");
|
||||
const config = JSON.parse(fs.readFileSync("./Config/config.json").toString());
|
||||
|
||||
module.exports = {
|
||||
commandInfo: {
|
||||
name: "kick",
|
||||
description: "Kick someone out of their current session by their username.",
|
||||
options: [
|
||||
{
|
||||
name: "username",
|
||||
description: "Target username.",
|
||||
required: true,
|
||||
type: 3 // string
|
||||
}
|
||||
]
|
||||
},
|
||||
execute: async (interaction) => {
|
||||
await interaction.deferReply({ ephemeral: true });
|
||||
|
||||
const userRoles = interaction.member.roles.cache.map(role => role.id);
|
||||
const hasModeratorRole = userRoles.includes(config.realmoderatorsrole);
|
||||
|
||||
if (!hasModeratorRole) {
|
||||
return interaction.editReply({ content: "You must have the moderator role to execute this command.", ephemeral: true });
|
||||
}
|
||||
|
||||
const { options } = interaction;
|
||||
const targetUser = await User.findOne({ username_lower: (options.get("username").value).toLowerCase() });
|
||||
|
||||
if (!targetUser) return interaction.editReply({ content: "The account username you entered does not exist.", ephemeral: true });
|
||||
|
||||
let refreshToken = global.refreshTokens.findIndex(i => i.accountId == targetUser.accountId);
|
||||
if (refreshToken != -1) global.refreshTokens.splice(refreshToken, 1);
|
||||
|
||||
let accessToken = global.accessTokens.findIndex(i => i.accountId == targetUser.accountId);
|
||||
if (accessToken != -1) {
|
||||
global.accessTokens.splice(accessToken, 1);
|
||||
|
||||
let xmppClient = global.Clients.find(client => client.accountId == targetUser.accountId);
|
||||
if (xmppClient) xmppClient.client.close();
|
||||
}
|
||||
|
||||
if (accessToken != -1 || refreshToken != -1) {
|
||||
functions.UpdateTokens();
|
||||
|
||||
const logChannel = interaction.client.channels.cache.get(config.logChannelKickId);
|
||||
if (logChannel) {
|
||||
logChannel.send(`<@${interaction.user.id}> / ${interaction.user.tag} has kicked **${targetUser.username}**`);
|
||||
}
|
||||
|
||||
return interaction.editReply({ content: `Successfully kicked ${targetUser.username}`, ephemeral: true });
|
||||
}
|
||||
|
||||
interaction.editReply({ content: `There are no current active sessions by ${targetUser.username}`, ephemeral: true });
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
const Users = require('../../../model/user');
|
||||
const Profiles = require('../../../model/profiles');
|
||||
const config = require('../../../Config/config.json')
|
||||
|
||||
module.exports = {
|
||||
commandInfo: {
|
||||
name: "removevbucks",
|
||||
description: "Lets you change a users amount of vbucks",
|
||||
options: [
|
||||
{
|
||||
name: "user",
|
||||
description: "The user you want to change the vbucks of",
|
||||
required: true,
|
||||
type: 6
|
||||
},
|
||||
{
|
||||
name: "vbucks",
|
||||
description: "The amount of vbucks you want to remove (Can be a negative number to take vbucks)",
|
||||
required: true,
|
||||
type: 4
|
||||
}
|
||||
]
|
||||
},
|
||||
execute: async (interaction) => {
|
||||
|
||||
if (!config.moderators.includes(interaction.user.id)) {
|
||||
console.log("User does not have moderator permissions.");
|
||||
return interaction.reply({ content: "You do not have moderator permissions.", ephemeral: true });
|
||||
}
|
||||
|
||||
const selectedUser = interaction.options.getUser('user');
|
||||
const selectedUserId = selectedUser?.id;
|
||||
const user = await Users.findOne({ discordId: selectedUserId });
|
||||
if (!user)
|
||||
return interaction.reply({ content: "That user does not own an account", ephemeral: true });
|
||||
const vbucks = parseInt(interaction.options.getInteger('vbucks'));
|
||||
const profile = await Profiles.findOneAndUpdate({ accountId: user.accountId }, { $inc: { 'profiles.common_core.items.Currency:MtxPurchased.quantity': - vbucks } });
|
||||
if (!profile)
|
||||
return interaction.reply({ content: "That user does not own an account", ephemeral: true });
|
||||
|
||||
await interaction.reply({ content: "have been successfully removed **" + vbucks + "** vbucks for <@" + selectedUserId + ">", ephemeral: true });
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
const User = require("../../../model/user.js");
|
||||
const fs = require("fs");
|
||||
const config = JSON.parse(fs.readFileSync("./Config/config.json").toString());
|
||||
|
||||
module.exports = {
|
||||
commandInfo: {
|
||||
name: "unban",
|
||||
description: "Unban a user from the backend by their username.",
|
||||
options: [
|
||||
{
|
||||
name: "username",
|
||||
description: "Target username.",
|
||||
required: true,
|
||||
type: 3 // string
|
||||
}
|
||||
]
|
||||
},
|
||||
execute: async (interaction) => {
|
||||
await interaction.deferReply({ ephemeral: true });
|
||||
|
||||
if (!config.moderators.includes(interaction.user.id)) return interaction.editReply({ content: "You do not have moderator permissions.", ephemeral: true });
|
||||
|
||||
const { options } = interaction;
|
||||
const targetUser = await User.findOne({ username_lower: (options.get("username").value).toLowerCase() });
|
||||
|
||||
if (!targetUser) return interaction.editReply({ content: "The account username you entered does not exist.", ephemeral: true });
|
||||
else if (!targetUser.banned) return interaction.editReply({ content: "This account is already unbanned.", ephemeral: true });
|
||||
|
||||
await targetUser.updateOne({ $set: { banned: false } });
|
||||
|
||||
interaction.editReply({ content: `Successfully unbanned ${targetUser.username}`, ephemeral: true });
|
||||
|
||||
const logChannel = interaction.client.channels.cache.get(config.logChannelUnbanId);
|
||||
if (logChannel) {
|
||||
logChannel.send(`<@${interaction.user.id}> / ${interaction.user.tag} has unbanned **${targetUser.username}**`);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
const { MessageEmbed } = require("discord.js");
|
||||
const Users = require('../../../model/user.js');
|
||||
|
||||
module.exports = {
|
||||
commandInfo: {
|
||||
name: "change-email",
|
||||
description: "Allows you to change your email",
|
||||
options: [
|
||||
{
|
||||
name: "email",
|
||||
description: "Your desired email.",
|
||||
required: true,
|
||||
type: 3
|
||||
}
|
||||
]
|
||||
},
|
||||
execute: async (interaction) => {
|
||||
const user = await Users.findOne({ discordId: interaction.user.id });
|
||||
if (!user)
|
||||
return interaction.reply({ content: "You are not registered!", ephemeral: true });
|
||||
const plainEmail = interaction.options.getString('email');
|
||||
|
||||
const emailFilter = /^([a-zA-Z0-9_\.\-])+\@(([a-zA-Z0-9\-])+\.)+([a-zA-Z0-9]{2,4})+$/;
|
||||
if (!emailFilter.test(plainEmail)) {
|
||||
return interaction.editReply({ content: "You did not provide a valid email address!", ephemeral: true });
|
||||
}
|
||||
|
||||
const existingUser = await Users.findOne({ email: plainEmail });
|
||||
if (existingUser) {
|
||||
return interaction.reply({ content: "Email is already in use, please choose another one.", ephemeral: true });
|
||||
}
|
||||
|
||||
await user.updateOne({ $set: { email: plainEmail } });
|
||||
const embed = new MessageEmbed()
|
||||
.setTitle("Email changed")
|
||||
.setDescription("Your account email has been changed")
|
||||
.setColor("GREEN")
|
||||
.setFooter({
|
||||
text: "Reload Backend",
|
||||
iconURL: "https://cdn.discordapp.com/attachments/1252374830225948672/1263993256136675378/IMG_1736.png?ex=669c40f4&is=669aef74&hm=5ded3e4588c05a56f271e0a07f7631317a3ebd72eae7497c4de5ee712a4db6dd&",
|
||||
})
|
||||
.setTimestamp();
|
||||
await interaction.reply({ embeds: [embed], ephemeral: true });
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
const User = require("../../../model/user.js");
|
||||
const bcrypt = require("bcrypt");
|
||||
|
||||
module.exports = {
|
||||
commandInfo: {
|
||||
name: "change-password",
|
||||
description: "Change your password.",
|
||||
options: [
|
||||
{
|
||||
name: "password",
|
||||
description: "Your new password.",
|
||||
required: true,
|
||||
type: 3 // string
|
||||
}
|
||||
]
|
||||
},
|
||||
execute: async (interaction) => {
|
||||
await interaction.deferReply({ ephemeral: true });
|
||||
|
||||
const user = await User.findOne({ discordId: interaction.user.id });
|
||||
if (!user) return interaction.editReply({ content: "You do not have a registered account!", ephemeral: true });
|
||||
|
||||
const { options } = interaction;
|
||||
|
||||
let plainPassword = options.get("password").value;
|
||||
|
||||
if (plainPassword.length >= 128) return interaction.editReply({ content: "Your password must be less than 128 characters long.", ephemeral: true });
|
||||
if (plainPassword.length < 8) return interaction.editReply({ content: "Your password must be atleast 8 characters long.", ephemeral: true });
|
||||
|
||||
let hashedPassword = await bcrypt.hash(plainPassword, 10);
|
||||
|
||||
await user.updateOne({ $set: { password: hashedPassword } });
|
||||
|
||||
interaction.editReply({ content: `Successfully changed your password.`, ephemeral: true });
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,61 @@
|
||||
const { MessageEmbed } = require("discord.js");
|
||||
const User = require("../../../model/user.js");
|
||||
const Badwords = require("bad-words");
|
||||
|
||||
const badwords = new Badwords();
|
||||
|
||||
module.exports = {
|
||||
commandInfo: {
|
||||
name: "change-username",
|
||||
description: "Change your username.",
|
||||
options: [
|
||||
{
|
||||
name: "username",
|
||||
description: "Your new username.",
|
||||
required: true,
|
||||
type: 3 // string
|
||||
}
|
||||
]
|
||||
},
|
||||
execute: async (interaction) => {
|
||||
await interaction.deferReply({ ephemeral: true });
|
||||
|
||||
const user = await User.findOne({ discordId: interaction.user.id });
|
||||
if (!user)
|
||||
return interaction.editReply({ content: "You are not registered!", ephemeral: true });
|
||||
|
||||
const validUsernameRegex = /^[a-zA-Z0-9]+$/;
|
||||
const username = interaction.options.getString('username');
|
||||
if (!validUsernameRegex.test(username) || badwords.isProfane(username)) {
|
||||
return interaction.editReply({ content: "Invalid username. Username must contain only letters and numbers, and no spaces or special characters. Additionally, it should not contain inappropriate language." });
|
||||
}
|
||||
|
||||
const plainUsername = interaction.options.getString('username');
|
||||
|
||||
if (plainUsername.length < 3) {
|
||||
return interaction.editReply({ content: "Invalid username. Username must have at least 3 characters." });
|
||||
}
|
||||
|
||||
if (plainUsername.length > 20) {
|
||||
return interaction.editReply({ content: "Invalid username. Username must be 20 characters or less" });
|
||||
}
|
||||
|
||||
const existingUser = await User.findOne({ username: plainUsername });
|
||||
if (existingUser) {
|
||||
return interaction.editReply({ content: "Username already exists. Please choose a different one." });
|
||||
}
|
||||
|
||||
await user.updateOne({ $set: { username: username, username_lower: username.toLowerCase() } });
|
||||
|
||||
const embed = new MessageEmbed()
|
||||
.setTitle("Username changed")
|
||||
.setDescription(`Your account username has been changed to **${username}**`)
|
||||
.setColor("GREEN")
|
||||
.setFooter({
|
||||
text: "Reload Backend",
|
||||
iconURL: "https://cdn.discordapp.com/attachments/1252374830225948672/1263993256136675378/IMG_1736.png?ex=669c40f4&is=669aef74&hm=5ded3e4588c05a56f271e0a07f7631317a3ebd72eae7497c4de5ee712a4db6dd&",
|
||||
})
|
||||
.setTimestamp();
|
||||
await interaction.editReply({ embeds: [embed], ephemeral: true });
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,65 @@
|
||||
const { MessageEmbed } = require("discord.js");
|
||||
const functions = require("../../../structs/functions.js");
|
||||
|
||||
module.exports = {
|
||||
commandInfo: {
|
||||
name: "create",
|
||||
description: "Creates an account on Lawin.",
|
||||
options: [
|
||||
{
|
||||
name: "email",
|
||||
description: "Your email.",
|
||||
required: true,
|
||||
type: 3
|
||||
},
|
||||
{
|
||||
name: "username",
|
||||
description: "Your username.",
|
||||
required: true,
|
||||
type: 3
|
||||
},
|
||||
{
|
||||
name: "password",
|
||||
description: "Your password.",
|
||||
required: true,
|
||||
type: 3
|
||||
}
|
||||
],
|
||||
},
|
||||
execute: async (interaction) => {
|
||||
await interaction.deferReply({ ephemeral: true });
|
||||
|
||||
const { options } = interaction;
|
||||
|
||||
const discordId = interaction.user.id;
|
||||
const email = options.get("email").value;
|
||||
const username = options.get("username").value;
|
||||
const password = options.get("password").value;
|
||||
|
||||
await functions.registerUser(discordId, username, email, password).then(resp => {
|
||||
let embed = new MessageEmbed()
|
||||
.setColor(resp.status >= 400 ? "#ff0000" : "#56ff00")
|
||||
.setThumbnail(interaction.user.avatarURL({ format: 'png', dynamic: true, size: 256 }))
|
||||
.addFields({
|
||||
name: "Message",
|
||||
value: "Successfully created an account.",
|
||||
}, {
|
||||
name: "Username",
|
||||
value: username,
|
||||
}, {
|
||||
name: "Discord Tag",
|
||||
value: interaction.user.tag,
|
||||
})
|
||||
.setTimestamp()
|
||||
.setFooter({
|
||||
text: "Reload Backend",
|
||||
iconURL: "https://cdn.discordapp.com/attachments/1252374830225948672/1263993256136675378/IMG_1736.png?ex=669c40f4&is=669aef74&hm=5ded3e4588c05a56f271e0a07f7631317a3ebd72eae7497c4de5ee712a4db6dd&"
|
||||
})
|
||||
|
||||
if (resp.status >= 400) return interaction.editReply({ embeds: [embed], ephemeral: true });
|
||||
|
||||
(interaction.channel ? interaction.channel : interaction.user).send({ embeds: [embed] });
|
||||
interaction.editReply({ content: "You successfully created an account!", ephemeral: true });
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
const { MessageEmbed } = require("discord.js");
|
||||
const User = require("../../../model/user.js");
|
||||
|
||||
module.exports = {
|
||||
commandInfo: {
|
||||
name: "details",
|
||||
description: "Retrieves your account info."
|
||||
},
|
||||
execute: async (interaction) => {
|
||||
await interaction.deferReply({ ephemeral: true });
|
||||
|
||||
const user = await User.findOne({ discordId: interaction.user.id }).lean();
|
||||
if (!user) return interaction.editReply({ content: "You do not have a registered account!", ephemeral: true });
|
||||
|
||||
//let onlineStatus = global.Clients.some(i => i.accountId == user.accountId);
|
||||
|
||||
let embed = new MessageEmbed()
|
||||
.setColor("GREEN")
|
||||
.setDescription("These are your account details")
|
||||
//.setAuthor({ name: interaction.user.tag, iconURL: interaction.user.avatarURL() })
|
||||
.setFields(
|
||||
//{ name: "Created", value: `${new Date(user.created)}`.substring(0, 15) },
|
||||
{ name: 'Username', value: user.username },
|
||||
{ name: 'Email', value: `${user.email}` },
|
||||
//{ name: "Online", value: `${onlineStatus ? "Yes" : "No"}` },
|
||||
{ name: "Banned", value: `${user.banned ? "Yes" : "No"}` },
|
||||
{ name: "Account ID", value: user.accountId })
|
||||
.setTimestamp()
|
||||
.setThumbnail(interaction.user.avatarURL())
|
||||
.setFooter({
|
||||
text: "Reload Backend",
|
||||
iconURL: "https://cdn.discordapp.com/attachments/1252374830225948672/1263993256136675378/IMG_1736.png?ex=669c40f4&is=669aef74&hm=5ded3e4588c05a56f271e0a07f7631317a3ebd72eae7497c4de5ee712a4db6dd&"
|
||||
})
|
||||
|
||||
interaction.editReply({ embeds: [embed], ephemeral: true });
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
const { MessageEmbed } = require("discord.js");
|
||||
const User = require("../../../model/user.js");
|
||||
const functions = require("../../../structs/functions.js");
|
||||
|
||||
module.exports = {
|
||||
commandInfo: {
|
||||
name: "exchange-code",
|
||||
description: "Generates an exchange code for login. (One time use and expires after 5 mins if unused)."
|
||||
},
|
||||
execute: async (interaction) => {
|
||||
await interaction.deferReply({ ephemeral: true });
|
||||
|
||||
const user = await User.findOne({ discordId: interaction.user.id }).lean();
|
||||
if (!user) return interaction.editReply({ content: "You do not have a registered account!", ephemeral: true });
|
||||
|
||||
let exchange_code = functions.MakeID().replace(/-/ig, "");
|
||||
|
||||
global.exchangeCodes.push({
|
||||
accountId: user.accountId,
|
||||
exchange_code: exchange_code,
|
||||
creatingClientId: ""
|
||||
});
|
||||
|
||||
setTimeout(() => {
|
||||
let exchangeCode = global.exchangeCodes.findIndex(i => i.exchange_code == exchange_code);
|
||||
|
||||
if (exchangeCode != -1) global.exchangeCodes.splice(exchangeCode, 1);
|
||||
}, 300000) // remove exchange code in 5 minutes if unused
|
||||
|
||||
let embed = new MessageEmbed()
|
||||
.setColor("#56ff00")
|
||||
.setAuthor({ name: interaction.user.tag, iconURL: interaction.user.avatarURL() })
|
||||
.setFields(
|
||||
{ name: "Exchange Code", value: exchange_code }
|
||||
)
|
||||
.setTimestamp()
|
||||
.setFooter({
|
||||
text: "Reload Backend",
|
||||
iconURL: "https://cdn.discordapp.com/attachments/1252374830225948672/1263993256136675378/IMG_1736.png?ex=669c40f4&is=669aef74&hm=5ded3e4588c05a56f271e0a07f7631317a3ebd72eae7497c4de5ee712a4db6dd&"
|
||||
})
|
||||
|
||||
interaction.editReply({ content: "Successfully generated an exchange code.", embeds: [embed], ephemeral: true });
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
const { MessageEmbed } = require("discord.js");
|
||||
const Users = require("../../../model/user.js");
|
||||
|
||||
module.exports = {
|
||||
commandInfo: {
|
||||
name: "lookup",
|
||||
description: "Search for a Discord user\'s ID by providing their in-game username.",
|
||||
options: [
|
||||
{
|
||||
name: "user",
|
||||
description: "Target username.",
|
||||
required: true,
|
||||
type: 3
|
||||
}
|
||||
]
|
||||
},
|
||||
execute: async (interaction) => {
|
||||
|
||||
await interaction.deferReply({ ephemeral: true });
|
||||
|
||||
const { options } = interaction;
|
||||
|
||||
const user = await Users.findOne({ username_lower: (options.get("user").value).toLowerCase() }).lean();
|
||||
if (!user) return interaction.editReply({ content: "The account username you entered does not exist.", ephemeral: true });
|
||||
|
||||
let onlineStatus = global.Clients.some(i => i.accountId == user.accountId);
|
||||
|
||||
let embed = new MessageEmbed()
|
||||
.setColor("GREEN")
|
||||
.setDescription(`**User Information:**\n- **Discord User:** <@${user.discordId}>\n- **DiscordID:** ${user.discordId}\n- **In-Game Username:** ${user.username}\n- **Banned:** ${user.banned ? "Yes" : "No"}\n- **Online:** ${onlineStatus ? "Yes" : "No"}`)
|
||||
.setFooter({
|
||||
text: "Reload Backend",
|
||||
iconURL: "https://cdn.discordapp.com/attachments/1252374830225948672/1263993256136675378/IMG_1736.png?ex=669c40f4&is=669aef74&hm=5ded3e4588c05a56f271e0a07f7631317a3ebd72eae7497c4de5ee712a4db6dd&"
|
||||
})
|
||||
|
||||
interaction.editReply({ embeds: [embed], ephemeral: true });
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
const User = require("../../../model/user.js");
|
||||
const functions = require("../../../structs/functions.js");
|
||||
|
||||
module.exports = {
|
||||
commandInfo: {
|
||||
name: "sign-out-of-all-sessions",
|
||||
description: "Signs you out if you have an active session."
|
||||
},
|
||||
execute: async (interaction) => {
|
||||
await interaction.deferReply({ ephemeral: true });
|
||||
|
||||
const targetUser = await User.findOne({ discordId: interaction.user.id }).lean();
|
||||
if (!targetUser) return interaction.editReply({ content: "You do not have a registered account!", ephemeral: true });
|
||||
|
||||
let refreshToken = global.refreshTokens.findIndex(i => i.accountId == targetUser.accountId);
|
||||
if (refreshToken != -1) global.refreshTokens.splice(refreshToken, 1);
|
||||
|
||||
let accessToken = global.accessTokens.findIndex(i => i.accountId == targetUser.accountId);
|
||||
if (accessToken != -1) {
|
||||
global.accessTokens.splice(accessToken, 1);
|
||||
|
||||
let xmppClient = global.Clients.find(client => client.accountId == targetUser.accountId);
|
||||
if (xmppClient) xmppClient.client.close();
|
||||
}
|
||||
|
||||
if (accessToken != -1 || refreshToken != -1) {
|
||||
functions.UpdateTokens();
|
||||
|
||||
return interaction.editReply({ content: `Successfully signed out of all sessions!`, ephemeral: true });
|
||||
}
|
||||
|
||||
interaction.editReply({ content: `You have no current active sessions.`, ephemeral: true });
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
const { MessageEmbed } = require("discord.js");
|
||||
const Profiles = require('../../../model/profiles.js');
|
||||
const Users = require('../../../model/user.js');
|
||||
|
||||
module.exports = {
|
||||
commandInfo: {
|
||||
name: "vbucksamount",
|
||||
description: "Displays your current V-Bucks balance.",
|
||||
},
|
||||
execute: async (interaction) => {
|
||||
|
||||
await interaction.deferReply({ ephemeral: true })
|
||||
|
||||
const currentuser = await Users.findOne({ discordId: interaction.user.id });
|
||||
const vbucksamount = await Profiles.findOne({ accountId: currentuser?.accountId });
|
||||
const currency = vbucksamount?.profiles.common_core.items["Currency:MtxPurchased"].quantity;
|
||||
if (!currentuser)
|
||||
{
|
||||
return interaction.editReply({ content: "You are not registered!", ephemeral: true });
|
||||
}
|
||||
const embed = new MessageEmbed()
|
||||
.setTitle("V-Bucks Count:")
|
||||
.setDescription(`You currently have **` + currency + " V-Bucks** in your Account!")
|
||||
.setTimestamp()
|
||||
.setThumbnail('https://cdn.discordapp.com/attachments/1248740944648605747/1249460527688585236/vbucks-removebg-preview.png?ex=6667624b&is=666610cb&hm=27c9fb9569124ab504f53d6a1cf758a1cfacc6a13f9165a61ce4d758ad3e5f0d&')
|
||||
.setFooter({
|
||||
text: "Reload Backend",
|
||||
iconURL: "https://cdn.discordapp.com/attachments/1252374830225948672/1263993256136675378/IMG_1736.png?ex=669c40f4&is=669aef74&hm=5ded3e4588c05a56f271e0a07f7631317a3ebd72eae7497c4de5ee712a4db6dd&"
|
||||
})
|
||||
.setColor("WHITE")
|
||||
await interaction.editReply({ embeds: [embed], ephemeral: true });
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,49 @@
|
||||
const { Client, Intents, ActivityType } = require("discord.js");
|
||||
const client = new Client({ intents: [Intents.FLAGS.GUILDS, Intents.FLAGS.GUILD_MESSAGES, Intents.FLAGS.GUILD_MEMBERS] });
|
||||
const fs = require("fs");
|
||||
const path = require("path");
|
||||
const config = JSON.parse(fs.readFileSync("./Config/config.json").toString());
|
||||
const log = require("../structs/log.js");
|
||||
|
||||
client.once("ready", () => {
|
||||
log.bot("Bot is up and running!");
|
||||
|
||||
let commands = client.application.commands;
|
||||
|
||||
const loadCommands = (dir) => {
|
||||
fs.readdirSync(dir).forEach(file => {
|
||||
const filePath = path.join(dir, file);
|
||||
if (fs.lstatSync(filePath).isDirectory()) {
|
||||
loadCommands(filePath);
|
||||
} else if (file.endsWith(".js")) {
|
||||
const command = require(filePath);
|
||||
commands.create(command.commandInfo);
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
loadCommands(path.join(__dirname, "commands"));
|
||||
});
|
||||
|
||||
client.on("interactionCreate", async interaction => {
|
||||
if (!interaction.isApplicationCommand()) return;
|
||||
|
||||
const executeCommand = (dir, commandName) => {
|
||||
const commandPath = path.join(dir, commandName + ".js");
|
||||
if (fs.existsSync(commandPath)) {
|
||||
require(commandPath).execute(interaction);
|
||||
return true;
|
||||
}
|
||||
const subdirectories = fs.readdirSync(dir).filter(subdir => fs.lstatSync(path.join(dir, subdir)).isDirectory());
|
||||
for (const subdir of subdirectories) {
|
||||
if (executeCommand(path.join(dir, subdir), commandName)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
};
|
||||
|
||||
executeCommand(path.join(__dirname, "commands"), interaction.commandName);
|
||||
});
|
||||
|
||||
client.login(config.discord.bot_token);
|
||||
@@ -0,0 +1,674 @@
|
||||
GNU GENERAL PUBLIC LICENSE
|
||||
Version 3, 29 June 2007
|
||||
|
||||
Copyright (C) 2007 Free Software Foundation, Inc. <https://fsf.org/>
|
||||
Everyone is permitted to copy and distribute verbatim copies
|
||||
of this license document, but changing it is not allowed.
|
||||
|
||||
Preamble
|
||||
|
||||
The GNU General Public License is a free, copyleft license for
|
||||
software and other kinds of works.
|
||||
|
||||
The licenses for most software and other practical works are designed
|
||||
to take away your freedom to share and change the works. By contrast,
|
||||
the GNU General Public License is intended to guarantee your freedom to
|
||||
share and change all versions of a program--to make sure it remains free
|
||||
software for all its users. We, the Free Software Foundation, use the
|
||||
GNU General Public License for most of our software; it applies also to
|
||||
any other work released this way by its authors. You can apply it to
|
||||
your programs, too.
|
||||
|
||||
When we speak of free software, we are referring to freedom, not
|
||||
price. Our General Public Licenses are designed to make sure that you
|
||||
have the freedom to distribute copies of free software (and charge for
|
||||
them if you wish), that you receive source code or can get it if you
|
||||
want it, that you can change the software or use pieces of it in new
|
||||
free programs, and that you know you can do these things.
|
||||
|
||||
To protect your rights, we need to prevent others from denying you
|
||||
these rights or asking you to surrender the rights. Therefore, you have
|
||||
certain responsibilities if you distribute copies of the software, or if
|
||||
you modify it: responsibilities to respect the freedom of others.
|
||||
|
||||
For example, if you distribute copies of such a program, whether
|
||||
gratis or for a fee, you must pass on to the recipients the same
|
||||
freedoms that you received. You must make sure that they, too, receive
|
||||
or can get the source code. And you must show them these terms so they
|
||||
know their rights.
|
||||
|
||||
Developers that use the GNU GPL protect your rights with two steps:
|
||||
(1) assert copyright on the software, and (2) offer you this License
|
||||
giving you legal permission to copy, distribute and/or modify it.
|
||||
|
||||
For the developers' and authors' protection, the GPL clearly explains
|
||||
that there is no warranty for this free software. For both users' and
|
||||
authors' sake, the GPL requires that modified versions be marked as
|
||||
changed, so that their problems will not be attributed erroneously to
|
||||
authors of previous versions.
|
||||
|
||||
Some devices are designed to deny users access to install or run
|
||||
modified versions of the software inside them, although the manufacturer
|
||||
can do so. This is fundamentally incompatible with the aim of
|
||||
protecting users' freedom to change the software. The systematic
|
||||
pattern of such abuse occurs in the area of products for individuals to
|
||||
use, which is precisely where it is most unacceptable. Therefore, we
|
||||
have designed this version of the GPL to prohibit the practice for those
|
||||
products. If such problems arise substantially in other domains, we
|
||||
stand ready to extend this provision to those domains in future versions
|
||||
of the GPL, as needed to protect the freedom of users.
|
||||
|
||||
Finally, every program is threatened constantly by software patents.
|
||||
States should not allow patents to restrict development and use of
|
||||
software on general-purpose computers, but in those that do, we wish to
|
||||
avoid the special danger that patents applied to a free program could
|
||||
make it effectively proprietary. To prevent this, the GPL assures that
|
||||
patents cannot be used to render the program non-free.
|
||||
|
||||
The precise terms and conditions for copying, distribution and
|
||||
modification follow.
|
||||
|
||||
TERMS AND CONDITIONS
|
||||
|
||||
0. Definitions.
|
||||
|
||||
"This License" refers to version 3 of the GNU General Public License.
|
||||
|
||||
"Copyright" also means copyright-like laws that apply to other kinds of
|
||||
works, such as semiconductor masks.
|
||||
|
||||
"The Program" refers to any copyrightable work licensed under this
|
||||
License. Each licensee is addressed as "you". "Licensees" and
|
||||
"recipients" may be individuals or organizations.
|
||||
|
||||
To "modify" a work means to copy from or adapt all or part of the work
|
||||
in a fashion requiring copyright permission, other than the making of an
|
||||
exact copy. The resulting work is called a "modified version" of the
|
||||
earlier work or a work "based on" the earlier work.
|
||||
|
||||
A "covered work" means either the unmodified Program or a work based
|
||||
on the Program.
|
||||
|
||||
To "propagate" a work means to do anything with it that, without
|
||||
permission, would make you directly or secondarily liable for
|
||||
infringement under applicable copyright law, except executing it on a
|
||||
computer or modifying a private copy. Propagation includes copying,
|
||||
distribution (with or without modification), making available to the
|
||||
public, and in some countries other activities as well.
|
||||
|
||||
To "convey" a work means any kind of propagation that enables other
|
||||
parties to make or receive copies. Mere interaction with a user through
|
||||
a computer network, with no transfer of a copy, is not conveying.
|
||||
|
||||
An interactive user interface displays "Appropriate Legal Notices"
|
||||
to the extent that it includes a convenient and prominently visible
|
||||
feature that (1) displays an appropriate copyright notice, and (2)
|
||||
tells the user that there is no warranty for the work (except to the
|
||||
extent that warranties are provided), that licensees may convey the
|
||||
work under this License, and how to view a copy of this License. If
|
||||
the interface presents a list of user commands or options, such as a
|
||||
menu, a prominent item in the list meets this criterion.
|
||||
|
||||
1. Source Code.
|
||||
|
||||
The "source code" for a work means the preferred form of the work
|
||||
for making modifications to it. "Object code" means any non-source
|
||||
form of a work.
|
||||
|
||||
A "Standard Interface" means an interface that either is an official
|
||||
standard defined by a recognized standards body, or, in the case of
|
||||
interfaces specified for a particular programming language, one that
|
||||
is widely used among developers working in that language.
|
||||
|
||||
The "System Libraries" of an executable work include anything, other
|
||||
than the work as a whole, that (a) is included in the normal form of
|
||||
packaging a Major Component, but which is not part of that Major
|
||||
Component, and (b) serves only to enable use of the work with that
|
||||
Major Component, or to implement a Standard Interface for which an
|
||||
implementation is available to the public in source code form. A
|
||||
"Major Component", in this context, means a major essential component
|
||||
(kernel, window system, and so on) of the specific operating system
|
||||
(if any) on which the executable work runs, or a compiler used to
|
||||
produce the work, or an object code interpreter used to run it.
|
||||
|
||||
The "Corresponding Source" for a work in object code form means all
|
||||
the source code needed to generate, install, and (for an executable
|
||||
work) run the object code and to modify the work, including scripts to
|
||||
control those activities. However, it does not include the work's
|
||||
System Libraries, or general-purpose tools or generally available free
|
||||
programs which are used unmodified in performing those activities but
|
||||
which are not part of the work. For example, Corresponding Source
|
||||
includes interface definition files associated with source files for
|
||||
the work, and the source code for shared libraries and dynamically
|
||||
linked subprograms that the work is specifically designed to require,
|
||||
such as by intimate data communication or control flow between those
|
||||
subprograms and other parts of the work.
|
||||
|
||||
The Corresponding Source need not include anything that users
|
||||
can regenerate automatically from other parts of the Corresponding
|
||||
Source.
|
||||
|
||||
The Corresponding Source for a work in source code form is that
|
||||
same work.
|
||||
|
||||
2. Basic Permissions.
|
||||
|
||||
All rights granted under this License are granted for the term of
|
||||
copyright on the Program, and are irrevocable provided the stated
|
||||
conditions are met. This License explicitly affirms your unlimited
|
||||
permission to run the unmodified Program. The output from running a
|
||||
covered work is covered by this License only if the output, given its
|
||||
content, constitutes a covered work. This License acknowledges your
|
||||
rights of fair use or other equivalent, as provided by copyright law.
|
||||
|
||||
You may make, run and propagate covered works that you do not
|
||||
convey, without conditions so long as your license otherwise remains
|
||||
in force. You may convey covered works to others for the sole purpose
|
||||
of having them make modifications exclusively for you, or provide you
|
||||
with facilities for running those works, provided that you comply with
|
||||
the terms of this License in conveying all material for which you do
|
||||
not control copyright. Those thus making or running the covered works
|
||||
for you must do so exclusively on your behalf, under your direction
|
||||
and control, on terms that prohibit them from making any copies of
|
||||
your copyrighted material outside their relationship with you.
|
||||
|
||||
Conveying under any other circumstances is permitted solely under
|
||||
the conditions stated below. Sublicensing is not allowed; section 10
|
||||
makes it unnecessary.
|
||||
|
||||
3. Protecting Users' Legal Rights From Anti-Circumvention Law.
|
||||
|
||||
No covered work shall be deemed part of an effective technological
|
||||
measure under any applicable law fulfilling obligations under article
|
||||
11 of the WIPO copyright treaty adopted on 20 December 1996, or
|
||||
similar laws prohibiting or restricting circumvention of such
|
||||
measures.
|
||||
|
||||
When you convey a covered work, you waive any legal power to forbid
|
||||
circumvention of technological measures to the extent such circumvention
|
||||
is effected by exercising rights under this License with respect to
|
||||
the covered work, and you disclaim any intention to limit operation or
|
||||
modification of the work as a means of enforcing, against the work's
|
||||
users, your or third parties' legal rights to forbid circumvention of
|
||||
technological measures.
|
||||
|
||||
4. Conveying Verbatim Copies.
|
||||
|
||||
You may convey verbatim copies of the Program's source code as you
|
||||
receive it, in any medium, provided that you conspicuously and
|
||||
appropriately publish on each copy an appropriate copyright notice;
|
||||
keep intact all notices stating that this License and any
|
||||
non-permissive terms added in accord with section 7 apply to the code;
|
||||
keep intact all notices of the absence of any warranty; and give all
|
||||
recipients a copy of this License along with the Program.
|
||||
|
||||
You may charge any price or no price for each copy that you convey,
|
||||
and you may offer support or warranty protection for a fee.
|
||||
|
||||
5. Conveying Modified Source Versions.
|
||||
|
||||
You may convey a work based on the Program, or the modifications to
|
||||
produce it from the Program, in the form of source code under the
|
||||
terms of section 4, provided that you also meet all of these conditions:
|
||||
|
||||
a) The work must carry prominent notices stating that you modified
|
||||
it, and giving a relevant date.
|
||||
|
||||
b) The work must carry prominent notices stating that it is
|
||||
released under this License and any conditions added under section
|
||||
7. This requirement modifies the requirement in section 4 to
|
||||
"keep intact all notices".
|
||||
|
||||
c) You must license the entire work, as a whole, under this
|
||||
License to anyone who comes into possession of a copy. This
|
||||
License will therefore apply, along with any applicable section 7
|
||||
additional terms, to the whole of the work, and all its parts,
|
||||
regardless of how they are packaged. This License gives no
|
||||
permission to license the work in any other way, but it does not
|
||||
invalidate such permission if you have separately received it.
|
||||
|
||||
d) If the work has interactive user interfaces, each must display
|
||||
Appropriate Legal Notices; however, if the Program has interactive
|
||||
interfaces that do not display Appropriate Legal Notices, your
|
||||
work need not make them do so.
|
||||
|
||||
A compilation of a covered work with other separate and independent
|
||||
works, which are not by their nature extensions of the covered work,
|
||||
and which are not combined with it such as to form a larger program,
|
||||
in or on a volume of a storage or distribution medium, is called an
|
||||
"aggregate" if the compilation and its resulting copyright are not
|
||||
used to limit the access or legal rights of the compilation's users
|
||||
beyond what the individual works permit. Inclusion of a covered work
|
||||
in an aggregate does not cause this License to apply to the other
|
||||
parts of the aggregate.
|
||||
|
||||
6. Conveying Non-Source Forms.
|
||||
|
||||
You may convey a covered work in object code form under the terms
|
||||
of sections 4 and 5, provided that you also convey the
|
||||
machine-readable Corresponding Source under the terms of this License,
|
||||
in one of these ways:
|
||||
|
||||
a) Convey the object code in, or embodied in, a physical product
|
||||
(including a physical distribution medium), accompanied by the
|
||||
Corresponding Source fixed on a durable physical medium
|
||||
customarily used for software interchange.
|
||||
|
||||
b) Convey the object code in, or embodied in, a physical product
|
||||
(including a physical distribution medium), accompanied by a
|
||||
written offer, valid for at least three years and valid for as
|
||||
long as you offer spare parts or customer support for that product
|
||||
model, to give anyone who possesses the object code either (1) a
|
||||
copy of the Corresponding Source for all the software in the
|
||||
product that is covered by this License, on a durable physical
|
||||
medium customarily used for software interchange, for a price no
|
||||
more than your reasonable cost of physically performing this
|
||||
conveying of source, or (2) access to copy the
|
||||
Corresponding Source from a network server at no charge.
|
||||
|
||||
c) Convey individual copies of the object code with a copy of the
|
||||
written offer to provide the Corresponding Source. This
|
||||
alternative is allowed only occasionally and noncommercially, and
|
||||
only if you received the object code with such an offer, in accord
|
||||
with subsection 6b.
|
||||
|
||||
d) Convey the object code by offering access from a designated
|
||||
place (gratis or for a charge), and offer equivalent access to the
|
||||
Corresponding Source in the same way through the same place at no
|
||||
further charge. You need not require recipients to copy the
|
||||
Corresponding Source along with the object code. If the place to
|
||||
copy the object code is a network server, the Corresponding Source
|
||||
may be on a different server (operated by you or a third party)
|
||||
that supports equivalent copying facilities, provided you maintain
|
||||
clear directions next to the object code saying where to find the
|
||||
Corresponding Source. Regardless of what server hosts the
|
||||
Corresponding Source, you remain obligated to ensure that it is
|
||||
available for as long as needed to satisfy these requirements.
|
||||
|
||||
e) Convey the object code using peer-to-peer transmission, provided
|
||||
you inform other peers where the object code and Corresponding
|
||||
Source of the work are being offered to the general public at no
|
||||
charge under subsection 6d.
|
||||
|
||||
A separable portion of the object code, whose source code is excluded
|
||||
from the Corresponding Source as a System Library, need not be
|
||||
included in conveying the object code work.
|
||||
|
||||
A "User Product" is either (1) a "consumer product", which means any
|
||||
tangible personal property which is normally used for personal, family,
|
||||
or household purposes, or (2) anything designed or sold for incorporation
|
||||
into a dwelling. In determining whether a product is a consumer product,
|
||||
doubtful cases shall be resolved in favor of coverage. For a particular
|
||||
product received by a particular user, "normally used" refers to a
|
||||
typical or common use of that class of product, regardless of the status
|
||||
of the particular user or of the way in which the particular user
|
||||
actually uses, or expects or is expected to use, the product. A product
|
||||
is a consumer product regardless of whether the product has substantial
|
||||
commercial, industrial or non-consumer uses, unless such uses represent
|
||||
the only significant mode of use of the product.
|
||||
|
||||
"Installation Information" for a User Product means any methods,
|
||||
procedures, authorization keys, or other information required to install
|
||||
and execute modified versions of a covered work in that User Product from
|
||||
a modified version of its Corresponding Source. The information must
|
||||
suffice to ensure that the continued functioning of the modified object
|
||||
code is in no case prevented or interfered with solely because
|
||||
modification has been made.
|
||||
|
||||
If you convey an object code work under this section in, or with, or
|
||||
specifically for use in, a User Product, and the conveying occurs as
|
||||
part of a transaction in which the right of possession and use of the
|
||||
User Product is transferred to the recipient in perpetuity or for a
|
||||
fixed term (regardless of how the transaction is characterized), the
|
||||
Corresponding Source conveyed under this section must be accompanied
|
||||
by the Installation Information. But this requirement does not apply
|
||||
if neither you nor any third party retains the ability to install
|
||||
modified object code on the User Product (for example, the work has
|
||||
been installed in ROM).
|
||||
|
||||
The requirement to provide Installation Information does not include a
|
||||
requirement to continue to provide support service, warranty, or updates
|
||||
for a work that has been modified or installed by the recipient, or for
|
||||
the User Product in which it has been modified or installed. Access to a
|
||||
network may be denied when the modification itself materially and
|
||||
adversely affects the operation of the network or violates the rules and
|
||||
protocols for communication across the network.
|
||||
|
||||
Corresponding Source conveyed, and Installation Information provided,
|
||||
in accord with this section must be in a format that is publicly
|
||||
documented (and with an implementation available to the public in
|
||||
source code form), and must require no special password or key for
|
||||
unpacking, reading or copying.
|
||||
|
||||
7. Additional Terms.
|
||||
|
||||
"Additional permissions" are terms that supplement the terms of this
|
||||
License by making exceptions from one or more of its conditions.
|
||||
Additional permissions that are applicable to the entire Program shall
|
||||
be treated as though they were included in this License, to the extent
|
||||
that they are valid under applicable law. If additional permissions
|
||||
apply only to part of the Program, that part may be used separately
|
||||
under those permissions, but the entire Program remains governed by
|
||||
this License without regard to the additional permissions.
|
||||
|
||||
When you convey a copy of a covered work, you may at your option
|
||||
remove any additional permissions from that copy, or from any part of
|
||||
it. (Additional permissions may be written to require their own
|
||||
removal in certain cases when you modify the work.) You may place
|
||||
additional permissions on material, added by you to a covered work,
|
||||
for which you have or can give appropriate copyright permission.
|
||||
|
||||
Notwithstanding any other provision of this License, for material you
|
||||
add to a covered work, you may (if authorized by the copyright holders of
|
||||
that material) supplement the terms of this License with terms:
|
||||
|
||||
a) Disclaiming warranty or limiting liability differently from the
|
||||
terms of sections 15 and 16 of this License; or
|
||||
|
||||
b) Requiring preservation of specified reasonable legal notices or
|
||||
author attributions in that material or in the Appropriate Legal
|
||||
Notices displayed by works containing it; or
|
||||
|
||||
c) Prohibiting misrepresentation of the origin of that material, or
|
||||
requiring that modified versions of such material be marked in
|
||||
reasonable ways as different from the original version; or
|
||||
|
||||
d) Limiting the use for publicity purposes of names of licensors or
|
||||
authors of the material; or
|
||||
|
||||
e) Declining to grant rights under trademark law for use of some
|
||||
trade names, trademarks, or service marks; or
|
||||
|
||||
f) Requiring indemnification of licensors and authors of that
|
||||
material by anyone who conveys the material (or modified versions of
|
||||
it) with contractual assumptions of liability to the recipient, for
|
||||
any liability that these contractual assumptions directly impose on
|
||||
those licensors and authors.
|
||||
|
||||
All other non-permissive additional terms are considered "further
|
||||
restrictions" within the meaning of section 10. If the Program as you
|
||||
received it, or any part of it, contains a notice stating that it is
|
||||
governed by this License along with a term that is a further
|
||||
restriction, you may remove that term. If a license document contains
|
||||
a further restriction but permits relicensing or conveying under this
|
||||
License, you may add to a covered work material governed by the terms
|
||||
of that license document, provided that the further restriction does
|
||||
not survive such relicensing or conveying.
|
||||
|
||||
If you add terms to a covered work in accord with this section, you
|
||||
must place, in the relevant source files, a statement of the
|
||||
additional terms that apply to those files, or a notice indicating
|
||||
where to find the applicable terms.
|
||||
|
||||
Additional terms, permissive or non-permissive, may be stated in the
|
||||
form of a separately written license, or stated as exceptions;
|
||||
the above requirements apply either way.
|
||||
|
||||
8. Termination.
|
||||
|
||||
You may not propagate or modify a covered work except as expressly
|
||||
provided under this License. Any attempt otherwise to propagate or
|
||||
modify it is void, and will automatically terminate your rights under
|
||||
this License (including any patent licenses granted under the third
|
||||
paragraph of section 11).
|
||||
|
||||
However, if you cease all violation of this License, then your
|
||||
license from a particular copyright holder is reinstated (a)
|
||||
provisionally, unless and until the copyright holder explicitly and
|
||||
finally terminates your license, and (b) permanently, if the copyright
|
||||
holder fails to notify you of the violation by some reasonable means
|
||||
prior to 60 days after the cessation.
|
||||
|
||||
Moreover, your license from a particular copyright holder is
|
||||
reinstated permanently if the copyright holder notifies you of the
|
||||
violation by some reasonable means, this is the first time you have
|
||||
received notice of violation of this License (for any work) from that
|
||||
copyright holder, and you cure the violation prior to 30 days after
|
||||
your receipt of the notice.
|
||||
|
||||
Termination of your rights under this section does not terminate the
|
||||
licenses of parties who have received copies or rights from you under
|
||||
this License. If your rights have been terminated and not permanently
|
||||
reinstated, you do not qualify to receive new licenses for the same
|
||||
material under section 10.
|
||||
|
||||
9. Acceptance Not Required for Having Copies.
|
||||
|
||||
You are not required to accept this License in order to receive or
|
||||
run a copy of the Program. Ancillary propagation of a covered work
|
||||
occurring solely as a consequence of using peer-to-peer transmission
|
||||
to receive a copy likewise does not require acceptance. However,
|
||||
nothing other than this License grants you permission to propagate or
|
||||
modify any covered work. These actions infringe copyright if you do
|
||||
not accept this License. Therefore, by modifying or propagating a
|
||||
covered work, you indicate your acceptance of this License to do so.
|
||||
|
||||
10. Automatic Licensing of Downstream Recipients.
|
||||
|
||||
Each time you convey a covered work, the recipient automatically
|
||||
receives a license from the original licensors, to run, modify and
|
||||
propagate that work, subject to this License. You are not responsible
|
||||
for enforcing compliance by third parties with this License.
|
||||
|
||||
An "entity transaction" is a transaction transferring control of an
|
||||
organization, or substantially all assets of one, or subdividing an
|
||||
organization, or merging organizations. If propagation of a covered
|
||||
work results from an entity transaction, each party to that
|
||||
transaction who receives a copy of the work also receives whatever
|
||||
licenses to the work the party's predecessor in interest had or could
|
||||
give under the previous paragraph, plus a right to possession of the
|
||||
Corresponding Source of the work from the predecessor in interest, if
|
||||
the predecessor has it or can get it with reasonable efforts.
|
||||
|
||||
You may not impose any further restrictions on the exercise of the
|
||||
rights granted or affirmed under this License. For example, you may
|
||||
not impose a license fee, royalty, or other charge for exercise of
|
||||
rights granted under this License, and you may not initiate litigation
|
||||
(including a cross-claim or counterclaim in a lawsuit) alleging that
|
||||
any patent claim is infringed by making, using, selling, offering for
|
||||
sale, or importing the Program or any portion of it.
|
||||
|
||||
11. Patents.
|
||||
|
||||
A "contributor" is a copyright holder who authorizes use under this
|
||||
License of the Program or a work on which the Program is based. The
|
||||
work thus licensed is called the contributor's "contributor version".
|
||||
|
||||
A contributor's "essential patent claims" are all patent claims
|
||||
owned or controlled by the contributor, whether already acquired or
|
||||
hereafter acquired, that would be infringed by some manner, permitted
|
||||
by this License, of making, using, or selling its contributor version,
|
||||
but do not include claims that would be infringed only as a
|
||||
consequence of further modification of the contributor version. For
|
||||
purposes of this definition, "control" includes the right to grant
|
||||
patent sublicenses in a manner consistent with the requirements of
|
||||
this License.
|
||||
|
||||
Each contributor grants you a non-exclusive, worldwide, royalty-free
|
||||
patent license under the contributor's essential patent claims, to
|
||||
make, use, sell, offer for sale, import and otherwise run, modify and
|
||||
propagate the contents of its contributor version.
|
||||
|
||||
In the following three paragraphs, a "patent license" is any express
|
||||
agreement or commitment, however denominated, not to enforce a patent
|
||||
(such as an express permission to practice a patent or covenant not to
|
||||
sue for patent infringement). To "grant" such a patent license to a
|
||||
party means to make such an agreement or commitment not to enforce a
|
||||
patent against the party.
|
||||
|
||||
If you convey a covered work, knowingly relying on a patent license,
|
||||
and the Corresponding Source of the work is not available for anyone
|
||||
to copy, free of charge and under the terms of this License, through a
|
||||
publicly available network server or other readily accessible means,
|
||||
then you must either (1) cause the Corresponding Source to be so
|
||||
available, or (2) arrange to deprive yourself of the benefit of the
|
||||
patent license for this particular work, or (3) arrange, in a manner
|
||||
consistent with the requirements of this License, to extend the patent
|
||||
license to downstream recipients. "Knowingly relying" means you have
|
||||
actual knowledge that, but for the patent license, your conveying the
|
||||
covered work in a country, or your recipient's use of the covered work
|
||||
in a country, would infringe one or more identifiable patents in that
|
||||
country that you have reason to believe are valid.
|
||||
|
||||
If, pursuant to or in connection with a single transaction or
|
||||
arrangement, you convey, or propagate by procuring conveyance of, a
|
||||
covered work, and grant a patent license to some of the parties
|
||||
receiving the covered work authorizing them to use, propagate, modify
|
||||
or convey a specific copy of the covered work, then the patent license
|
||||
you grant is automatically extended to all recipients of the covered
|
||||
work and works based on it.
|
||||
|
||||
A patent license is "discriminatory" if it does not include within
|
||||
the scope of its coverage, prohibits the exercise of, or is
|
||||
conditioned on the non-exercise of one or more of the rights that are
|
||||
specifically granted under this License. You may not convey a covered
|
||||
work if you are a party to an arrangement with a third party that is
|
||||
in the business of distributing software, under which you make payment
|
||||
to the third party based on the extent of your activity of conveying
|
||||
the work, and under which the third party grants, to any of the
|
||||
parties who would receive the covered work from you, a discriminatory
|
||||
patent license (a) in connection with copies of the covered work
|
||||
conveyed by you (or copies made from those copies), or (b) primarily
|
||||
for and in connection with specific products or compilations that
|
||||
contain the covered work, unless you entered into that arrangement,
|
||||
or that patent license was granted, prior to 28 March 2007.
|
||||
|
||||
Nothing in this License shall be construed as excluding or limiting
|
||||
any implied license or other defenses to infringement that may
|
||||
otherwise be available to you under applicable patent law.
|
||||
|
||||
12. No Surrender of Others' Freedom.
|
||||
|
||||
If conditions are imposed on you (whether by court order, agreement or
|
||||
otherwise) that contradict the conditions of this License, they do not
|
||||
excuse you from the conditions of this License. If you cannot convey a
|
||||
covered work so as to satisfy simultaneously your obligations under this
|
||||
License and any other pertinent obligations, then as a consequence you may
|
||||
not convey it at all. For example, if you agree to terms that obligate you
|
||||
to collect a royalty for further conveying from those to whom you convey
|
||||
the Program, the only way you could satisfy both those terms and this
|
||||
License would be to refrain entirely from conveying the Program.
|
||||
|
||||
13. Use with the GNU Affero General Public License.
|
||||
|
||||
Notwithstanding any other provision of this License, you have
|
||||
permission to link or combine any covered work with a work licensed
|
||||
under version 3 of the GNU Affero General Public License into a single
|
||||
combined work, and to convey the resulting work. The terms of this
|
||||
License will continue to apply to the part which is the covered work,
|
||||
but the special requirements of the GNU Affero General Public License,
|
||||
section 13, concerning interaction through a network will apply to the
|
||||
combination as such.
|
||||
|
||||
14. Revised Versions of this License.
|
||||
|
||||
The Free Software Foundation may publish revised and/or new versions of
|
||||
the GNU General Public License from time to time. Such new versions will
|
||||
be similar in spirit to the present version, but may differ in detail to
|
||||
address new problems or concerns.
|
||||
|
||||
Each version is given a distinguishing version number. If the
|
||||
Program specifies that a certain numbered version of the GNU General
|
||||
Public License "or any later version" applies to it, you have the
|
||||
option of following the terms and conditions either of that numbered
|
||||
version or of any later version published by the Free Software
|
||||
Foundation. If the Program does not specify a version number of the
|
||||
GNU General Public License, you may choose any version ever published
|
||||
by the Free Software Foundation.
|
||||
|
||||
If the Program specifies that a proxy can decide which future
|
||||
versions of the GNU General Public License can be used, that proxy's
|
||||
public statement of acceptance of a version permanently authorizes you
|
||||
to choose that version for the Program.
|
||||
|
||||
Later license versions may give you additional or different
|
||||
permissions. However, no additional obligations are imposed on any
|
||||
author or copyright holder as a result of your choosing to follow a
|
||||
later version.
|
||||
|
||||
15. Disclaimer of Warranty.
|
||||
|
||||
THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
|
||||
APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
|
||||
HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
|
||||
OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
|
||||
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
|
||||
IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
|
||||
ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
|
||||
|
||||
16. Limitation of Liability.
|
||||
|
||||
IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
|
||||
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
|
||||
THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
|
||||
GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
|
||||
USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
|
||||
DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
|
||||
PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
|
||||
EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
|
||||
SUCH DAMAGES.
|
||||
|
||||
17. Interpretation of Sections 15 and 16.
|
||||
|
||||
If the disclaimer of warranty and limitation of liability provided
|
||||
above cannot be given local legal effect according to their terms,
|
||||
reviewing courts shall apply local law that most closely approximates
|
||||
an absolute waiver of all civil liability in connection with the
|
||||
Program, unless a warranty or assumption of liability accompanies a
|
||||
copy of the Program in return for a fee.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
How to Apply These Terms to Your New Programs
|
||||
|
||||
If you develop a new program, and you want it to be of the greatest
|
||||
possible use to the public, the best way to achieve this is to make it
|
||||
free software which everyone can redistribute and change under these terms.
|
||||
|
||||
To do so, attach the following notices to the program. It is safest
|
||||
to attach them to the start of each source file to most effectively
|
||||
state the exclusion of warranty; and each file should have at least
|
||||
the "copyright" line and a pointer to where the full notice is found.
|
||||
|
||||
<one line to give the program's name and a brief idea of what it does.>
|
||||
Copyright (C) <year> <name of author>
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
Also add information on how to contact you by electronic and paper mail.
|
||||
|
||||
If the program does terminal interaction, make it output a short
|
||||
notice like this when it starts in an interactive mode:
|
||||
|
||||
<program> Copyright (C) <year> <name of author>
|
||||
This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
|
||||
This is free software, and you are welcome to redistribute it
|
||||
under certain conditions; type `show c' for details.
|
||||
|
||||
The hypothetical commands `show w' and `show c' should show the appropriate
|
||||
parts of the General Public License. Of course, your program's commands
|
||||
might be different; for a GUI interface, you would use an "about box".
|
||||
|
||||
You should also get your employer (if you work as a programmer) or school,
|
||||
if any, to sign a "copyright disclaimer" for the program, if necessary.
|
||||
For more information on this, and how to apply and follow the GNU GPL, see
|
||||
<https://www.gnu.org/licenses/>.
|
||||
|
||||
The GNU General Public License does not permit incorporating your program
|
||||
into proprietary programs. If your program is a subroutine library, you
|
||||
may consider it more useful to permit linking proprietary applications with
|
||||
the library. If this is what you want to do, use the GNU Lesser General
|
||||
Public License instead of this License. But first, please read
|
||||
<https://www.gnu.org/licenses/why-not-lgpl.html>.
|
||||
@@ -0,0 +1,3 @@
|
||||
# Reload Backend
|
||||
|
||||
Reload Backend is a universal Fortnite private server backend written in JavaScript, made by Burlone.
|
||||
@@ -0,0 +1,85 @@
|
||||
const express = require("express");
|
||||
const app = express();
|
||||
const mongoose = require("mongoose");
|
||||
const fs = require("fs");
|
||||
const rateLimit = require("express-rate-limit");
|
||||
const jwt = require("jsonwebtoken");
|
||||
const config = JSON.parse(fs.readFileSync("./Config/config.json").toString());
|
||||
|
||||
const log = require("./structs/log.js");
|
||||
const error = require("./structs/error.js");
|
||||
const functions = require("./structs/functions.js");
|
||||
|
||||
if (!fs.existsSync("./ClientSettings")) fs.mkdirSync("./ClientSettings");
|
||||
|
||||
global.JWT_SECRET = functions.MakeID();
|
||||
const PORT = config.port;
|
||||
|
||||
console.log('Welcome to Reload Backend\n')
|
||||
|
||||
const tokens = JSON.parse(fs.readFileSync("./tokenManager/tokens.json").toString());
|
||||
|
||||
for (let tokenType in tokens) {
|
||||
for (let tokenIndex in tokens[tokenType]) {
|
||||
let decodedToken = jwt.decode(tokens[tokenType][tokenIndex].token.replace("eg1~", ""));
|
||||
|
||||
if (DateAddHours(new Date(decodedToken.creation_date), decodedToken.hours_expire).getTime() <= new Date().getTime()) {
|
||||
tokens[tokenType].splice(Number(tokenIndex), 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fs.writeFileSync("./tokenManager/tokens.json", JSON.stringify(tokens, null, 2));
|
||||
|
||||
global.accessTokens = tokens.accessTokens;
|
||||
global.refreshTokens = tokens.refreshTokens;
|
||||
global.clientTokens = tokens.clientTokens;
|
||||
|
||||
global.exchangeCodes = [];
|
||||
|
||||
mongoose.connect(config.mongodb.database, () => {
|
||||
log.backend("App successfully connected to MongoDB!");
|
||||
});
|
||||
|
||||
mongoose.connection.on("error", err => {
|
||||
log.error("MongoDB failed to connect, please make sure you have MongoDB installed and running.");
|
||||
throw err;
|
||||
});
|
||||
|
||||
app.use(rateLimit({ windowMs: 0.5 * 60 * 1000, max: 45 }));
|
||||
app.use(express.json());
|
||||
app.use(express.urlencoded({ extended: true }));
|
||||
|
||||
fs.readdirSync("./routes").forEach(fileName => {
|
||||
app.use(require(`./routes/${fileName}`));
|
||||
});
|
||||
|
||||
app.listen(PORT, () => {
|
||||
|
||||
log.backend(`App started listening on port ${PORT}`);
|
||||
|
||||
require("./xmpp/xmpp.js");
|
||||
require("./DiscordBot");
|
||||
}).on("error", async (err) => {
|
||||
if (err.code == "EADDRINUSE") {
|
||||
log.error(`Port ${PORT} is already in use!\nClosing in 3 seconds...`);
|
||||
await functions.sleep(3000)
|
||||
process.exit(0);
|
||||
} else throw err;
|
||||
});
|
||||
|
||||
// if endpoint not found, return this error
|
||||
app.use((req, res, next) => {
|
||||
error.createError(
|
||||
"errors.com.epicgames.common.not_found",
|
||||
"Sorry the resource you were trying to find could not be found",
|
||||
undefined, 1004, undefined, 404, res
|
||||
);
|
||||
});
|
||||
|
||||
function DateAddHours(pdate, number) {
|
||||
let date = pdate;
|
||||
date.setHours(date.getHours() + number);
|
||||
|
||||
return date;
|
||||
}
|
||||
@@ -0,0 +1,2 @@
|
||||
npm i
|
||||
pause
|
||||
@@ -0,0 +1,72 @@
|
||||
const functions = require("../structs/functions.js");
|
||||
|
||||
module.exports = async (ws) => {
|
||||
// create hashes
|
||||
const ticketId = functions.MakeID().replace(/-/ig, "");
|
||||
const matchId = functions.MakeID().replace(/-/ig, "");
|
||||
const sessionId = functions.MakeID().replace(/-/ig, "");
|
||||
|
||||
Connecting();
|
||||
await functions.sleep(800);
|
||||
Waiting();
|
||||
await functions.sleep(1000);
|
||||
Queued();
|
||||
await functions.sleep(4000);
|
||||
SessionAssignment();
|
||||
await functions.sleep(2000);
|
||||
Join();
|
||||
|
||||
function Connecting() {
|
||||
ws.send(JSON.stringify({
|
||||
"payload": {
|
||||
"state": "Connecting"
|
||||
},
|
||||
"name": "StatusUpdate"
|
||||
}));
|
||||
}
|
||||
|
||||
function Waiting() {
|
||||
ws.send(JSON.stringify({
|
||||
"payload": {
|
||||
"totalPlayers": 1,
|
||||
"connectedPlayers": 1,
|
||||
"state": "Waiting"
|
||||
},
|
||||
"name": "StatusUpdate"
|
||||
}));
|
||||
}
|
||||
|
||||
function Queued() {
|
||||
ws.send(JSON.stringify({
|
||||
"payload": {
|
||||
"ticketId": ticketId,
|
||||
"queuedPlayers": 0,
|
||||
"estimatedWaitSec": 0,
|
||||
"status": {},
|
||||
"state": "Queued"
|
||||
},
|
||||
"name": "StatusUpdate"
|
||||
}));
|
||||
}
|
||||
|
||||
function SessionAssignment() {
|
||||
ws.send(JSON.stringify({
|
||||
"payload": {
|
||||
"matchId": matchId,
|
||||
"state": "SessionAssignment"
|
||||
},
|
||||
"name": "StatusUpdate"
|
||||
}));
|
||||
}
|
||||
|
||||
function Join() {
|
||||
ws.send(JSON.stringify({
|
||||
"payload": {
|
||||
"matchId": matchId,
|
||||
"sessionId": sessionId,
|
||||
"joinDelaySec": 1
|
||||
},
|
||||
"name": "Play"
|
||||
}));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
const mongoose = require("mongoose");
|
||||
|
||||
const FriendsSchema = new mongoose.Schema(
|
||||
{
|
||||
created: { type: Date, required: true },
|
||||
accountId: { type: String, required: true, unique: true },
|
||||
list: { type: Object, default: { accepted: [], incoming: [], outgoing: [], blocked: [] } }
|
||||
},
|
||||
{
|
||||
collection: "friends"
|
||||
}
|
||||
)
|
||||
|
||||
const model = mongoose.model('FriendsSchema', FriendsSchema);
|
||||
|
||||
module.exports = model;
|
||||
@@ -0,0 +1,16 @@
|
||||
const mongoose = require("mongoose");
|
||||
|
||||
const ProfilesSchema = new mongoose.Schema(
|
||||
{
|
||||
created: { type: Date, required: true },
|
||||
accountId: { type: String, required: true, unique: true },
|
||||
profiles: { type: Object, required: true }
|
||||
},
|
||||
{
|
||||
collection: "profiles"
|
||||
}
|
||||
)
|
||||
|
||||
const model = mongoose.model('ProfilesSchema', ProfilesSchema);
|
||||
|
||||
module.exports = model;
|
||||
@@ -0,0 +1,21 @@
|
||||
const mongoose = require("mongoose");
|
||||
|
||||
const UserSchema = new mongoose.Schema(
|
||||
{
|
||||
created: { type: Date, required: true },
|
||||
banned: { type: Boolean, default: false },
|
||||
discordId: { type: String, required: true, unique: true },
|
||||
accountId: { type: String, required: true, unique: true },
|
||||
username: { type: String, required: true, unique: true },
|
||||
username_lower: { type: String, required: true, unique: true },
|
||||
email: { type: String, required: true, unique: true },
|
||||
password: { type: String, required: true }
|
||||
},
|
||||
{
|
||||
collection: "users"
|
||||
}
|
||||
)
|
||||
|
||||
const model = mongoose.model('UserSchema', UserSchema);
|
||||
|
||||
module.exports = model;
|
||||
Generated
+3202
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,42 @@
|
||||
{
|
||||
"name": "reloadbackend",
|
||||
"version": "1.0.0",
|
||||
"description": "Created by Burlone, This is a modded backend, all main backend credits to lawin",
|
||||
"main": "index.js",
|
||||
"dependencies": {
|
||||
"bad-words": "^3.0.4",
|
||||
"bcrypt": "^5.1.0",
|
||||
"destr": "^2.0.3",
|
||||
"discord.js": "^13.7.0",
|
||||
"dotenv": "^16.0.3",
|
||||
"express": "^4.18.2",
|
||||
"express-rate-limit": "^6.7.0",
|
||||
"jsonwebtoken": "^8.5.1",
|
||||
"mongoose": "^6.6.5",
|
||||
"path": "^0.12.7",
|
||||
"uuid": "^9.0.0",
|
||||
"ws": "^8.9.0",
|
||||
"xml-parser": "^1.2.1",
|
||||
"xmlbuilder": "^15.1.1"
|
||||
},
|
||||
"scripts": {
|
||||
"test": "echo \"Error: no test specified\" && exit 1"
|
||||
},
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "git+https://github.com/Lawin0129/LawinServerV2.git"
|
||||
},
|
||||
"keywords": [
|
||||
"fortnite",
|
||||
"backend",
|
||||
"node",
|
||||
"server",
|
||||
"v2"
|
||||
],
|
||||
"author": "Lawin0129",
|
||||
"license": "GPL-3.0",
|
||||
"bugs": {
|
||||
"url": "https://github.com/Lawin0129/LawinServerV2/issues"
|
||||
},
|
||||
"homepage": "https://github.com/Lawin0129/LawinServerV2#readme"
|
||||
}
|
||||
@@ -0,0 +1,461 @@
|
||||
{
|
||||
"battleBundleOfferId": "259920BC42F0AAC7C8672D856C9B622C",
|
||||
"battlePassOfferId": "2E43CCD24C3BE8F5ABBDF28E233B9350",
|
||||
"tierOfferId": "AF1B7AC14A5F6A9ED255B88902120757",
|
||||
"paidRewards": [
|
||||
{
|
||||
"Token:athenaseasonxpboost": 50,
|
||||
"Token:athenaseasonfriendxpboost": 60,
|
||||
"AthenaCharacter:cid_486_athena_commando_f_streetracerdrift": 1,
|
||||
"AthenaCharacter:cid_488_athena_commando_m_rustremix": 1,
|
||||
"Token:athenaseasonmergedxpboosts": 1,
|
||||
"ChallengeBundleSchedule:season10_seasonx_schedule": 1,
|
||||
"ChallengeBundleSchedule:season10_blackknight_schedule": 1,
|
||||
"ChallengeBundleSchedule:season10_djyonger_schedule": 1,
|
||||
"ChallengeBundleSchedule:season10_drift_schedule": 1,
|
||||
"ChallengeBundleSchedule:season10_rustlord_schedule": 1,
|
||||
"ChallengeBundleSchedule:season10_sparkle_schedule": 1,
|
||||
"ChallengeBundleSchedule:season10_teknique_schedule": 1,
|
||||
"ChallengeBundleSchedule:season10_voyager_schedule": 1,
|
||||
"ChallengeBundleSchedule:season10_mission_schedule": 1,
|
||||
"ChallengeBundleSchedule:season10_seasonlevel_mission_schedule": 1
|
||||
},
|
||||
{
|
||||
"Token:athenaseasonxpboost": 10,
|
||||
"Token:athenanextseasonxpboost": 30
|
||||
},
|
||||
{
|
||||
"AthenaDance:emoji_redknight": 1
|
||||
},
|
||||
{
|
||||
"Currency:mtxgiveaway": 100
|
||||
},
|
||||
{
|
||||
"AthenaItemWrap:wrap_107_graffitiremix": 1
|
||||
},
|
||||
{
|
||||
"HomebaseBannerIcon:brs10dragonegg": 1
|
||||
},
|
||||
{
|
||||
"AthenaGlider:glider_id_166_rustlordremix": 1
|
||||
},
|
||||
{
|
||||
"AthenaDance:spid_150_icedragon": 1
|
||||
},
|
||||
{
|
||||
"Token:athenaseasonfriendxpboost": 10
|
||||
},
|
||||
{
|
||||
"AthenaLoadingScreen:lsid_161_h7outfitsa": 1
|
||||
},
|
||||
{
|
||||
"Currency:mtxgiveaway": 100
|
||||
},
|
||||
{
|
||||
"AthenaMusicPack:musicpack_024_showdown": 1
|
||||
},
|
||||
{
|
||||
"HomebaseBannerIcon:brs10medievalknight": 1
|
||||
},
|
||||
{
|
||||
"AthenaDance:spid_140_moistymire": 1
|
||||
},
|
||||
{
|
||||
"AthenaPickaxe:pickaxe_id_245_voyagerremix1h": 1
|
||||
},
|
||||
{
|
||||
"AthenaLoadingScreen:lsid_155_akdrift": 1
|
||||
},
|
||||
{
|
||||
"Token:athenaseasonxpboost": 10
|
||||
},
|
||||
{
|
||||
"AthenaDance:emoji_crackshot": 1
|
||||
},
|
||||
{
|
||||
"Currency:mtxgiveaway": 100
|
||||
},
|
||||
{
|
||||
"AthenaDance:spid_149_fireice": 1
|
||||
},
|
||||
{
|
||||
"AthenaSkyDiveContrail:trails_id_074_driftlightning": 1
|
||||
},
|
||||
{
|
||||
"AthenaLoadingScreen:lsid_151_jmsparkle": 1
|
||||
},
|
||||
{
|
||||
"AthenaCharacter:cid_483_athena_commando_f_graffitiremix": 1
|
||||
},
|
||||
{
|
||||
"Token:athenaseasonfriendxpboost": 10
|
||||
},
|
||||
{
|
||||
"AthenaDance:emoji_popcorn": 1
|
||||
},
|
||||
{
|
||||
"HomebaseBannerIcon:brs10kevincube": 1
|
||||
},
|
||||
{
|
||||
"Currency:mtxgiveaway": 100
|
||||
},
|
||||
{
|
||||
"AthenaBackpack:petcarrier_012_drift_fox": 1
|
||||
},
|
||||
{
|
||||
"AthenaLoadingScreen:lsid_154_ijcuddle": 1
|
||||
},
|
||||
{
|
||||
"AthenaDance:emoji_lifepreserver": 1
|
||||
},
|
||||
{
|
||||
"AthenaDance:eid_jaywalking": 1
|
||||
},
|
||||
{
|
||||
"Token:athenaseasonxpboost": 10
|
||||
},
|
||||
{
|
||||
"HomebaseBannerIcon:brs10astronaut": 1
|
||||
},
|
||||
{
|
||||
"Currency:mtxgiveaway": 100
|
||||
},
|
||||
{
|
||||
"AthenaItemWrap:wrap_106_djremix": 1
|
||||
},
|
||||
{
|
||||
"AthenaLoadingScreen:lsid_158_ntdurrr": 1
|
||||
},
|
||||
{
|
||||
"AthenaDance:toy_015_bottle": 1
|
||||
},
|
||||
{
|
||||
"AthenaDance:spid_138_sparklespecialist": 1
|
||||
},
|
||||
{
|
||||
"AthenaGlider:glider_id_163_djremix": 1
|
||||
},
|
||||
{
|
||||
"Token:athenaseasonfriendxpboost": 10
|
||||
},
|
||||
{
|
||||
"AthenaLoadingScreen:lsid_175_jmtomato": 1
|
||||
},
|
||||
{
|
||||
"Currency:mtxgiveaway": 100
|
||||
},
|
||||
{
|
||||
"AthenaSkyDiveContrail:trails_id_065_djremix": 1
|
||||
},
|
||||
{
|
||||
"AthenaDance:emoji_coolpepper": 1
|
||||
},
|
||||
{
|
||||
"CosmeticVariantToken:vtid_286_petcarrier_driftfox_styleb": 1
|
||||
},
|
||||
{
|
||||
"AthenaLoadingScreen:lsid_160_ktvendetta": 1
|
||||
},
|
||||
{
|
||||
"AthenaCharacter:cid_487_athena_commando_m_djremix": 1
|
||||
},
|
||||
{
|
||||
"Token:athenaseasonxpboost": 10
|
||||
},
|
||||
{
|
||||
"AthenaDance:spid_135_riskyreels": 1
|
||||
},
|
||||
{
|
||||
"HomebaseBannerIcon:brs10britebomber": 1
|
||||
},
|
||||
{
|
||||
"Currency:mtxgiveaway": 100
|
||||
},
|
||||
{
|
||||
"AthenaLoadingScreen:lsid_156_akbrite": 1
|
||||
},
|
||||
{
|
||||
"AthenaDance:toy_020_bottle_fancy": 1
|
||||
},
|
||||
{
|
||||
"CosmeticVariantToken:vtid_288_djremix_headgearb": 1
|
||||
},
|
||||
{
|
||||
"AthenaPickaxe:pickaxe_id_242_sparkleremix": 1
|
||||
},
|
||||
{
|
||||
"Token:athenaseasonfriendxpboost": 10
|
||||
},
|
||||
{
|
||||
"AthenaLoadingScreen:lsid_162_h7outfitsb": 1
|
||||
},
|
||||
{
|
||||
"AthenaDance:emoji_crossswords": 1
|
||||
},
|
||||
{
|
||||
"Currency:mtxgiveaway": 100
|
||||
},
|
||||
{
|
||||
"AthenaItemWrap:wrap_105_cube": 1
|
||||
},
|
||||
{
|
||||
"HomebaseBannerIcon:brs10grid": 1
|
||||
},
|
||||
{
|
||||
"AthenaDance:spid_139_tiltedmap": 1
|
||||
},
|
||||
{
|
||||
"AthenaDance:eid_treadmilldance": 1
|
||||
},
|
||||
{
|
||||
"Token:athenaseasonxpboost": 10
|
||||
},
|
||||
{
|
||||
"CosmeticVariantToken:vtid_287_petcarrier_driftfox_stylec": 1
|
||||
},
|
||||
{
|
||||
"AthenaLoadingScreen:lsid_164_smcrackshot": 1
|
||||
},
|
||||
{
|
||||
"AthenaSkyDiveContrail:trails_id_066_tacticalhud": 1
|
||||
},
|
||||
{
|
||||
"HomebaseBannerIcon:brs10westernhats": 1
|
||||
},
|
||||
{
|
||||
"Currency:mtxgiveaway": 100
|
||||
},
|
||||
{
|
||||
"AthenaCharacter:cid_485_athena_commando_f_sparkleremix": 1
|
||||
},
|
||||
{
|
||||
"AthenaBackpack:bid_318_sparkleremix": 1
|
||||
},
|
||||
{
|
||||
"AthenaDance:spid_134_dustydepot": 1
|
||||
},
|
||||
{
|
||||
"Token:athenaseasonfriendxpboost": 10
|
||||
},
|
||||
{
|
||||
"AthenaLoadingScreen:lsid_159_ktfirewalker": 1
|
||||
},
|
||||
{
|
||||
"CosmeticVariantToken:vtid_290_sparkleremix_hairstyleb": 1
|
||||
},
|
||||
{
|
||||
"Currency:mtxgiveaway": 100
|
||||
},
|
||||
{
|
||||
"AthenaGlider:glider_id_169_voyagerremix": 1
|
||||
},
|
||||
{
|
||||
"HomebaseBannerIcon:brs10boombox": 1
|
||||
},
|
||||
{
|
||||
"AthenaDance:eid_breakdance2": 1
|
||||
},
|
||||
{
|
||||
"AthenaLoadingScreen:lsid_177_ijllama": 1
|
||||
},
|
||||
{
|
||||
"Token:athenaseasonxpboost": 10
|
||||
},
|
||||
{
|
||||
"AthenaSkyDiveContrail:trails_id_075_celestial": 1
|
||||
},
|
||||
{
|
||||
"Currency:mtxgiveaway": 100
|
||||
},
|
||||
{
|
||||
"AthenaItemWrap:wrap_109_rustremix": 1
|
||||
},
|
||||
{
|
||||
"HomebaseBannerIcon:brs10doublepump": 1
|
||||
},
|
||||
{
|
||||
"AthenaLoadingScreen:lsid_176_smvolcano": 1
|
||||
},
|
||||
{
|
||||
"AthenaCharacter:cid_489_athena_commando_m_voyagerremix": 1
|
||||
},
|
||||
{
|
||||
"Token:athenaseasonfriendxpboost": 10
|
||||
},
|
||||
{
|
||||
"AthenaDance:emoji_sweaty": 1
|
||||
},
|
||||
{
|
||||
"Currency:mtxgiveaway": 100
|
||||
},
|
||||
{
|
||||
"AthenaMusicPack:musicpack_022_daydream": 1
|
||||
},
|
||||
{
|
||||
"AthenaDance:spid_132_blackknight": 1
|
||||
},
|
||||
{
|
||||
"CosmeticVariantToken:vtid_291_voyagerremix_stageb": 1
|
||||
},
|
||||
{
|
||||
"AthenaLoadingScreen:lsid_152_jmluxe": 1
|
||||
},
|
||||
{
|
||||
"AthenaGlider:glider_id_165_knightremix": 1
|
||||
},
|
||||
{
|
||||
"Token:athenaseasonxpboost": 10
|
||||
},
|
||||
{
|
||||
"AthenaItemWrap:wrap_110_streetracerdriftremix": 1
|
||||
},
|
||||
{
|
||||
"Currency:mtxgiveaway": 100
|
||||
},
|
||||
{
|
||||
"CosmeticVariantToken:vtid_289_djremix_headgearc": 1
|
||||
},
|
||||
{
|
||||
"AthenaCharacter:cid_484_athena_commando_m_knightremix": 1,
|
||||
"AthenaBackpack:bid_317_knightremix": 1
|
||||
}
|
||||
],
|
||||
"freeRewards": [
|
||||
{},
|
||||
{
|
||||
"AthenaDance:spid_136_rocketlaunch": 1
|
||||
},
|
||||
{},
|
||||
{
|
||||
"AthenaLoadingScreen:lsid_163_smrocketride": 1
|
||||
},
|
||||
{},
|
||||
{
|
||||
"AthenaSkyDiveContrail:trails_id_068_popcorn": 1
|
||||
},
|
||||
{},
|
||||
{
|
||||
"AthenaDance:emoji_boogiebomb": 1
|
||||
},
|
||||
{},
|
||||
{},
|
||||
{
|
||||
"Currency:mtxgiveaway": 100
|
||||
},
|
||||
{},
|
||||
{},
|
||||
{
|
||||
"AthenaDance:eid_happyskipping": 1
|
||||
},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{
|
||||
"HomebaseBannerIcon:brs10rift": 1
|
||||
},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{
|
||||
"AthenaItemWrap:wrap_108_knightremix": 1
|
||||
},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{
|
||||
"AthenaDance:spid_133_butterfly": 1
|
||||
},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{
|
||||
"AthenaGlider:glider_id_164_graffitiremix": 1
|
||||
},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{
|
||||
"Currency:mtxgiveaway": 100
|
||||
},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{
|
||||
"AthenaBackpack:bid_320_rustlordremix": 1
|
||||
},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{
|
||||
"HomebaseBannerIcon:brs1080sllama": 1
|
||||
},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{
|
||||
"AthenaDance:eid_blowingbubbles": 1
|
||||
},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{
|
||||
"AthenaMusicPack:musicpack_023_og": 1
|
||||
},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{
|
||||
"HomebaseBannerIcon:brs10shades": 1
|
||||
},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{
|
||||
"AthenaDance:spid_142_cuberune": 1
|
||||
},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{
|
||||
"AthenaLoadingScreen:lsid_153_ijdriftboard": 1
|
||||
},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{}
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,318 @@
|
||||
{
|
||||
"battlePassOfferId": "C3BA14F04F4D56FC1D490F8011B56553",
|
||||
"tierOfferId": "F86AC2ED4B3EA4B2D65EF1B2629572A0",
|
||||
"paidRewards": [
|
||||
{
|
||||
"Token:athenaseasonxpboost": 50,
|
||||
"Token:athenaseasonfriendxpboost": 10,
|
||||
"AthenaCharacter:cid_032_athena_commando_m_medieval": 1,
|
||||
"AthenaBackpack:bid_001_bluesquire": 1
|
||||
},
|
||||
{
|
||||
"Token:athenaseasonxpboost": 10,
|
||||
"Token:athenanextseasontierboost": 5
|
||||
},
|
||||
{
|
||||
"HomebaseBannerIcon:brseason02bush": 1
|
||||
},
|
||||
{
|
||||
"Currency:mtxgiveaway": 100
|
||||
},
|
||||
{
|
||||
"AthenaDance:emoji_clapping": 1
|
||||
},
|
||||
{
|
||||
"AccountResource:athenaseasonalxp": 1000
|
||||
},
|
||||
{
|
||||
"AthenaPickaxe:pickaxe_id_012_district": 1
|
||||
},
|
||||
{
|
||||
"AccountResource:athenaseasonalxp": 1000
|
||||
},
|
||||
{
|
||||
"Token:athenaseasonfriendxpboost": 5
|
||||
},
|
||||
{
|
||||
"HomebaseBannerIcon:brseason02lionherald": 1
|
||||
},
|
||||
{
|
||||
"Currency:mtxgiveaway": 100
|
||||
},
|
||||
{
|
||||
"AthenaDance:emoji_rip": 1
|
||||
},
|
||||
{
|
||||
"AccountResource:athenaseasonalxp": 1000
|
||||
},
|
||||
{
|
||||
"AthenaGlider:glider_id_004_disco": 1
|
||||
},
|
||||
{
|
||||
"HomebaseBannerIcon:brseason02catsoldier": 1
|
||||
},
|
||||
{
|
||||
"Token:athenaseasonxpboost": 10
|
||||
},
|
||||
{
|
||||
"HomebaseBannerIcon:brseason02dragon": 1
|
||||
},
|
||||
{
|
||||
"Currency:mtxgiveaway": 100
|
||||
},
|
||||
{
|
||||
"AthenaDance:emoji_rage": 1
|
||||
},
|
||||
{
|
||||
"AccountResource:athenaseasonalxp": 1000
|
||||
},
|
||||
{
|
||||
"AthenaCharacter:cid_033_athena_commando_f_medieval": 1,
|
||||
"AthenaBackpack:bid_002_royaleknight": 1
|
||||
},
|
||||
{
|
||||
"AthenaDance:emoji_peacesign": 1
|
||||
},
|
||||
{
|
||||
"Token:athenaseasonfriendxpboost": 5
|
||||
},
|
||||
{
|
||||
"HomebaseBannerIcon:brseason02planet": 1
|
||||
},
|
||||
{
|
||||
"Currency:mtxgiveaway": 100
|
||||
},
|
||||
{
|
||||
"AthenaDance:emoji_disco": 1
|
||||
},
|
||||
{
|
||||
"AccountResource:athenaseasonalxp": 1000
|
||||
},
|
||||
{
|
||||
"AthenaDance:eid_worm": 1
|
||||
},
|
||||
{
|
||||
"HomebaseBannerIcon:brseason02bowling": 1
|
||||
},
|
||||
{
|
||||
"Token:athenaseasonxpboost": 10
|
||||
},
|
||||
{
|
||||
"HomebaseBannerIcon:brseason02monstertruck": 1
|
||||
},
|
||||
{
|
||||
"Currency:mtxgiveaway": 100
|
||||
},
|
||||
{
|
||||
"AthenaDance:emoji_exclamation": 1
|
||||
},
|
||||
{
|
||||
"AccountResource:athenaseasonalxp": 1000
|
||||
},
|
||||
{
|
||||
"AthenaPickaxe:pickaxe_id_011_medieval": 1
|
||||
},
|
||||
{
|
||||
"AthenaDance:emoji_armflex": 1
|
||||
},
|
||||
{
|
||||
"Token:athenaseasonfriendxpboost": 5
|
||||
},
|
||||
{
|
||||
"HomebaseBannerIcon:brseason02icecream": 1
|
||||
},
|
||||
{
|
||||
"Currency:mtxgiveaway": 100
|
||||
},
|
||||
{
|
||||
"AthenaDance:emoji_mvp": 1
|
||||
},
|
||||
{
|
||||
"AccountResource:athenaseasonalxp": 1000
|
||||
},
|
||||
{
|
||||
"AthenaGlider:glider_id_003_district": 1
|
||||
},
|
||||
{
|
||||
"AccountResource:athenaseasonalxp": 1000
|
||||
},
|
||||
{
|
||||
"Token:athenaseasonxpboost": 10
|
||||
},
|
||||
{
|
||||
"HomebaseBannerIcon:brseason02log": 1
|
||||
},
|
||||
{
|
||||
"Currency:mtxgiveaway": 100
|
||||
},
|
||||
{
|
||||
"AthenaDance:emoji_baited": 1
|
||||
},
|
||||
{
|
||||
"AccountResource:athenaseasonalxp": 1000
|
||||
},
|
||||
{
|
||||
"AthenaDance:eid_floss": 1
|
||||
},
|
||||
{
|
||||
"HomebaseBannerIcon:brseason02cake": 1
|
||||
},
|
||||
{
|
||||
"Token:athenaseasonfriendxpboost": 5
|
||||
},
|
||||
{
|
||||
"HomebaseBannerIcon:brseason02tank": 1
|
||||
},
|
||||
{
|
||||
"Currency:mtxgiveaway": 100
|
||||
},
|
||||
{
|
||||
"AthenaDance:emoji_salty": 1
|
||||
},
|
||||
{
|
||||
"AccountResource:athenaseasonalxp": 1000
|
||||
},
|
||||
{
|
||||
"AthenaCharacter:cid_039_athena_commando_f_disco": 1
|
||||
},
|
||||
{
|
||||
"AthenaDance:emoji_stealthy": 1
|
||||
},
|
||||
{
|
||||
"Token:athenaseasonxpboost": 10
|
||||
},
|
||||
{
|
||||
"HomebaseBannerIcon:brseason02gasmask": 1
|
||||
},
|
||||
{
|
||||
"Currency:mtxgiveaway": 100
|
||||
},
|
||||
{
|
||||
"AthenaDance:emoji_potatoaim": 1
|
||||
},
|
||||
{
|
||||
"AccountResource:athenaseasonalxp": 1000
|
||||
},
|
||||
{
|
||||
"AthenaPickaxe:pickaxe_id_013_teslacoil": 1
|
||||
},
|
||||
{
|
||||
"AccountResource:athenaseasonalxp": 1000
|
||||
},
|
||||
{
|
||||
"Token:athenaseasonxpboost": 10
|
||||
},
|
||||
{
|
||||
"HomebaseBannerIcon:brseason02vulture": 1
|
||||
},
|
||||
{
|
||||
"Currency:mtxgiveaway": 100
|
||||
},
|
||||
{
|
||||
"AthenaDance:emoji_onfire": 1
|
||||
},
|
||||
{
|
||||
"AccountResource:athenaseasonalxp": 1000
|
||||
},
|
||||
{
|
||||
"AthenaCharacter:cid_035_athena_commando_m_medieval": 1,
|
||||
"AthenaBackpack:bid_004_blackknight": 1
|
||||
}
|
||||
],
|
||||
"freeRewards": [
|
||||
{},
|
||||
{
|
||||
"AthenaDance:emoji_lol": 1
|
||||
},
|
||||
{},
|
||||
{},
|
||||
{
|
||||
"AthenaDance:eid_wave": 1
|
||||
},
|
||||
{},
|
||||
{},
|
||||
{
|
||||
"HomebaseBannerIcon:brseason02salt": 1
|
||||
},
|
||||
{},
|
||||
{},
|
||||
{
|
||||
"AthenaDance:emoji_hearthands": 1
|
||||
},
|
||||
{},
|
||||
{},
|
||||
{
|
||||
"Currency:mtxgiveaway": 100
|
||||
},
|
||||
{},
|
||||
{},
|
||||
{
|
||||
"AthenaDance:emoji_bullseye": 1
|
||||
},
|
||||
{},
|
||||
{},
|
||||
{
|
||||
"AthenaDance:eid_ridethepony_athena": 1
|
||||
},
|
||||
{},
|
||||
{},
|
||||
{
|
||||
"AccountResource:athenaseasonalxp": 1000
|
||||
},
|
||||
{},
|
||||
{},
|
||||
{
|
||||
"HomebaseBannerIcon:brseason02crosshair": 1
|
||||
},
|
||||
{},
|
||||
{},
|
||||
{
|
||||
"Currency:mtxgiveaway": 100
|
||||
},
|
||||
{},
|
||||
{},
|
||||
{
|
||||
"HomebaseBannerIcon:brseason02shark": 1
|
||||
},
|
||||
{},
|
||||
{},
|
||||
{
|
||||
"AthenaGlider:glider_id_002_medieval": 1
|
||||
},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{}
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,442 @@
|
||||
{
|
||||
"battleBundleOfferId": "70487F4C4673CC98F2FEBEBB26505F44",
|
||||
"battlePassOfferId": "2331626809474871A3A44C47C1D8742E",
|
||||
"tierOfferId": "E2D7975EFEC54A45900D8D9A6D9D273C",
|
||||
"paidRewards": [
|
||||
{
|
||||
"Token:athenaseasonxpboost": 50,
|
||||
"Token:athenaseasonfriendxpboost": 10,
|
||||
"AthenaCharacter:cid_080_athena_commando_m_space": 1,
|
||||
"ChallengeBundleSchedule:season3_challenge_schedule": 1
|
||||
},
|
||||
{
|
||||
"Token:athenaseasonxpboost": 10,
|
||||
"Token:athenanextseasontierboost": 5
|
||||
},
|
||||
{
|
||||
"HomebaseBannerIcon:brseason03egg": 1
|
||||
},
|
||||
{
|
||||
"Currency:mtxgiveaway": 100
|
||||
},
|
||||
{
|
||||
"AthenaDance:emoji_wow": 1
|
||||
},
|
||||
{
|
||||
"AthenaLoadingScreen:lsid_005_suppressedpistol": 1
|
||||
},
|
||||
{
|
||||
"AthenaPickaxe:pickaxe_id_027_scavenger": 1
|
||||
},
|
||||
{
|
||||
"AthenaDance:emoji_thief": 1
|
||||
},
|
||||
{
|
||||
"Token:athenaseasonfriendxpboost": 5
|
||||
},
|
||||
{
|
||||
"HomebaseBannerIcon:brseason03bee": 1
|
||||
},
|
||||
{
|
||||
"Currency:mtxgiveaway": 100
|
||||
},
|
||||
{
|
||||
"AthenaLoadingScreen:lsid_003_pickaxes": 1
|
||||
},
|
||||
{
|
||||
"HomebaseBannerIcon:brseason03worm": 1
|
||||
},
|
||||
{
|
||||
"AthenaDance:emoji_heartbroken": 1
|
||||
},
|
||||
{
|
||||
"AthenaGlider:glider_id_015_brite": 1
|
||||
},
|
||||
{
|
||||
"HomebaseBannerIcon:brseason03paw": 1
|
||||
},
|
||||
{
|
||||
"Token:athenaseasonxpboost": 10
|
||||
},
|
||||
{
|
||||
"AthenaDance:emoji_boombox": 1
|
||||
},
|
||||
{
|
||||
"Currency:mtxgiveaway": 100
|
||||
},
|
||||
{
|
||||
"AthenaSkyDiveContrail:trails_id_002_rainbow": 1
|
||||
},
|
||||
{
|
||||
"HomebaseBannerIcon:brseason03sun": 1
|
||||
},
|
||||
{
|
||||
"AthenaDance:emoji_rocketride": 1
|
||||
},
|
||||
{
|
||||
"AthenaCharacter:cid_082_athena_commando_m_scavenger": 1
|
||||
},
|
||||
{
|
||||
"HomebaseBannerIcon:brseason03falcon": 1
|
||||
},
|
||||
{
|
||||
"Token:athenaseasonfriendxpboost": 5
|
||||
},
|
||||
{
|
||||
"HomebaseBannerIcon:brseason03chick": 1
|
||||
},
|
||||
{
|
||||
"Currency:mtxgiveaway": 100
|
||||
},
|
||||
{
|
||||
"AthenaLoadingScreen:lsid_004_tacticalshotgun": 1
|
||||
},
|
||||
{
|
||||
"HomebaseBannerIcon:brseason03dogcollar": 1
|
||||
},
|
||||
{
|
||||
"AthenaDance:emoji_bush": 1
|
||||
},
|
||||
{
|
||||
"AthenaDance:eid_takethel": 1
|
||||
},
|
||||
{
|
||||
"AccountResource:athenaseasonalxp": 1000
|
||||
},
|
||||
{
|
||||
"Token:athenaseasonxpboost": 10
|
||||
},
|
||||
{
|
||||
"HomebaseBannerIcon:brseason03crescentmoon": 1
|
||||
},
|
||||
{
|
||||
"Currency:mtxgiveaway": 100
|
||||
},
|
||||
{
|
||||
"AthenaSkyDiveContrail:trails_id_004_bluestreak": 1
|
||||
},
|
||||
{
|
||||
"AccountResource:athenaseasonalxp": 1000
|
||||
},
|
||||
{
|
||||
"AthenaDance:emoji_awww": 1
|
||||
},
|
||||
{
|
||||
"AthenaGlider:glider_id_016_tactical": 1
|
||||
},
|
||||
{
|
||||
"HomebaseBannerIcon:brseason03crab": 1
|
||||
},
|
||||
{
|
||||
"Token:athenaseasonfriendxpboost": 5
|
||||
},
|
||||
{
|
||||
"HomebaseBannerIcon:brseason03tophat": 1
|
||||
},
|
||||
{
|
||||
"Currency:mtxgiveaway": 100
|
||||
},
|
||||
{
|
||||
"AthenaLoadingScreen:lsid_001_brite": 1
|
||||
},
|
||||
{
|
||||
"AccountResource:athenaseasonalxp": 1000
|
||||
},
|
||||
{
|
||||
"AthenaDance:emoji_thumbsup": 1
|
||||
},
|
||||
{
|
||||
"AthenaBackpack:bid_024_space": 1
|
||||
},
|
||||
{
|
||||
"AthenaDance:emoji_thumbsdown": 1
|
||||
},
|
||||
{
|
||||
"Token:athenaseasonxpboost": 10
|
||||
},
|
||||
{
|
||||
"AthenaSkyDiveContrail:trails_id_001_disco": 1
|
||||
},
|
||||
{
|
||||
"Currency:mtxgiveaway": 100
|
||||
},
|
||||
{
|
||||
"AthenaDance:emoji_1hp": 1
|
||||
},
|
||||
{
|
||||
"AccountResource:athenaseasonalxp": 1000
|
||||
},
|
||||
{
|
||||
"HomebaseBannerIcon:brseason03wing": 1
|
||||
},
|
||||
{
|
||||
"AthenaCharacter:cid_081_athena_commando_f_space": 1
|
||||
},
|
||||
{
|
||||
"AccountResource:athenaseasonalxp": 1000
|
||||
},
|
||||
{
|
||||
"Token:athenaseasonfriendxpboost": 5
|
||||
},
|
||||
{
|
||||
"AthenaDance:emoji_hotdawg": 1
|
||||
},
|
||||
{
|
||||
"Currency:mtxgiveaway": 100
|
||||
},
|
||||
{
|
||||
"AthenaLoadingScreen:lsid_006_minigun": 1
|
||||
},
|
||||
{
|
||||
"AccountResource:athenaseasonalxp": 1000
|
||||
},
|
||||
{
|
||||
"HomebaseBannerIcon:brseason03snake": 1
|
||||
},
|
||||
{
|
||||
"AthenaDance:eid_bestmates": 1
|
||||
},
|
||||
{
|
||||
"AthenaDance:emoji_hoarder": 1
|
||||
},
|
||||
{
|
||||
"Token:athenaseasonxpboost": 10
|
||||
},
|
||||
{
|
||||
"HomebaseBannerIcon:brseason03teddybear": 1
|
||||
},
|
||||
{
|
||||
"Currency:mtxgiveaway": 100
|
||||
},
|
||||
{
|
||||
"AthenaSkyDiveContrail:trails_id_005_bubbles": 1
|
||||
},
|
||||
{
|
||||
"AccountResource:athenaseasonalxp": 1000
|
||||
},
|
||||
{
|
||||
"AthenaCharacter:cid_088_athena_commando_m_spaceblack": 1
|
||||
},
|
||||
{
|
||||
"AthenaBackpack:bid_028_spaceblack": 1
|
||||
},
|
||||
{
|
||||
"HomebaseBannerIcon:brseason03happycloud": 1
|
||||
},
|
||||
{
|
||||
"Token:athenaseasonfriendxpboost": 5
|
||||
},
|
||||
{
|
||||
"AthenaDance:emoji_200iqplay": 1
|
||||
},
|
||||
{
|
||||
"Currency:mtxgiveaway": 100
|
||||
},
|
||||
{
|
||||
"AthenaLoadingScreen:lsid_002_raptor": 1
|
||||
},
|
||||
{
|
||||
"AccountResource:athenaseasonalxp": 1000
|
||||
},
|
||||
{
|
||||
"HomebaseBannerIcon:brseason03wolf": 1
|
||||
},
|
||||
{
|
||||
"AthenaPickaxe:pickaxe_id_029_assassin": 1
|
||||
},
|
||||
{
|
||||
"AthenaDance:emoji_flamingrage": 1
|
||||
},
|
||||
{
|
||||
"Token:athenaseasonxpboost": 10
|
||||
},
|
||||
{
|
||||
"HomebaseBannerIcon:brseason03whale": 1
|
||||
},
|
||||
{
|
||||
"Currency:mtxgiveaway": 100
|
||||
},
|
||||
{
|
||||
"AthenaSkyDiveContrail:trails_id_003_fire": 1
|
||||
},
|
||||
{
|
||||
"AccountResource:athenaseasonalxp": 1000
|
||||
},
|
||||
{
|
||||
"AthenaDance:emoji_kaboom": 1
|
||||
},
|
||||
{
|
||||
"AthenaCharacter:cid_083_athena_commando_f_tactical": 1
|
||||
},
|
||||
{
|
||||
"HomebaseBannerIcon:brseason03lightning": 1
|
||||
},
|
||||
{
|
||||
"Token:athenaseasonfriendxpboost": 5
|
||||
},
|
||||
{
|
||||
"AthenaDance:emoji_majestic": 1
|
||||
},
|
||||
{
|
||||
"Currency:mtxgiveaway": 100
|
||||
},
|
||||
{
|
||||
"AthenaLoadingScreen:lsid_007_tacticalcommando": 1
|
||||
},
|
||||
{
|
||||
"AccountResource:athenaseasonalxp": 1000
|
||||
},
|
||||
{
|
||||
"HomebaseBannerIcon:brseason03flail": 1
|
||||
},
|
||||
{
|
||||
"AthenaDance:eid_robot": 1
|
||||
},
|
||||
{
|
||||
"Token:athenaseasonxpboost": 10
|
||||
},
|
||||
{
|
||||
"AthenaDance:emoji_number1": 1
|
||||
},
|
||||
{
|
||||
"Currency:mtxgiveaway": 100
|
||||
},
|
||||
{
|
||||
"HomebaseBannerIcon:brseason03dinosaurskull": 1
|
||||
},
|
||||
{
|
||||
"AthenaCharacter:cid_084_athena_commando_m_assassin": 1,
|
||||
"ChallengeBundleSchedule:season3_tier_100_schedule": 1
|
||||
}
|
||||
],
|
||||
"freeRewards": [
|
||||
{},
|
||||
{
|
||||
"ChallengeBundleSchedule:season3_tier_2_schedule": 1
|
||||
},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{
|
||||
"HomebaseBannerIcon:brseason03donut": 1
|
||||
},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{
|
||||
"AthenaDance:eid_salute": 1
|
||||
},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{
|
||||
"AthenaDance:emoji_inlove": 1
|
||||
},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{
|
||||
"Currency:mtxgiveaway": 100
|
||||
},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{
|
||||
"AthenaBackpack:bid_025_tactical": 1
|
||||
},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{
|
||||
"AthenaDance:emoji_goodgame": 1
|
||||
},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{
|
||||
"AthenaLoadingScreen:lsid_008_keyart": 1
|
||||
},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{
|
||||
"Currency:mtxgiveaway": 100
|
||||
},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{
|
||||
"HomebaseBannerIcon:brseason03eagle": 1
|
||||
},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{
|
||||
"AthenaDance:emoji_positivity": 1
|
||||
},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{
|
||||
"AthenaPickaxe:pickaxe_id_028_space": 1
|
||||
},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{
|
||||
"HomebaseBannerIcon:brseason03shootingstar": 1
|
||||
},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{
|
||||
"AthenaDance:emoji_aplus": 1
|
||||
},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{}
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,444 @@
|
||||
{
|
||||
"battleBundleOfferId": "884CE68998C44AC58D85C5A9883DE1A6",
|
||||
"battlePassOfferId": "76EA7FE9787744B09B79FF3FC5E39D0C",
|
||||
"tierOfferId": "E9527AF46F4B4A9CAE98D91F2AA53CB6",
|
||||
"paidRewards": [
|
||||
{
|
||||
"Token:athenaseasonxpboost": 50,
|
||||
"Token:athenaseasonfriendxpboost": 10,
|
||||
"AthenaCharacter:cid_115_athena_commando_m_carbideblue": 1,
|
||||
"AthenaCharacter:cid_125_athena_commando_m_tacticalwoodland": 1,
|
||||
"ChallengeBundleSchedule:season4_challenge_schedule": 1,
|
||||
"Token:athenaseasonmergedxpboosts": 1
|
||||
},
|
||||
{
|
||||
"Token:athenaseasonxpboost": 10,
|
||||
"Token:athenanextseasontierboost": 5
|
||||
},
|
||||
{
|
||||
"AthenaDance:spid_002_xmark": 1
|
||||
},
|
||||
{
|
||||
"Currency:mtxgiveaway": 100
|
||||
},
|
||||
{
|
||||
"AthenaDance:emoji_dynamite": 1
|
||||
},
|
||||
{
|
||||
"AthenaLoadingScreen:lsid_017_carbide": 1
|
||||
},
|
||||
{
|
||||
"AthenaPickaxe:pickaxe_id_045_valor": 1
|
||||
},
|
||||
{
|
||||
"AthenaDance:emoji_camera": 1
|
||||
},
|
||||
{
|
||||
"Token:athenaseasonfriendxpboost": 5
|
||||
},
|
||||
{
|
||||
"AthenaDance:spid_006_rainbow": 1
|
||||
},
|
||||
{
|
||||
"Currency:mtxgiveaway": 100
|
||||
},
|
||||
{
|
||||
"AthenaLoadingScreen:lsid_018_rex": 1
|
||||
},
|
||||
{
|
||||
"HomebaseBannerIcon:brseason04heroemblem": 1
|
||||
},
|
||||
{
|
||||
"AthenaDance:spid_007_smilegg": 1
|
||||
},
|
||||
{
|
||||
"AthenaGlider:glider_id_035_candy": 1
|
||||
},
|
||||
{
|
||||
"HomebaseBannerIcon:brseason04spraycan": 1
|
||||
},
|
||||
{
|
||||
"Token:athenaseasonxpboost": 10
|
||||
},
|
||||
{
|
||||
"AthenaDance:emoji_zzz": 1
|
||||
},
|
||||
{
|
||||
"Currency:mtxgiveaway": 100
|
||||
},
|
||||
{
|
||||
"AthenaSkyDiveContrail:trails_id_010_retroscifi": 1
|
||||
},
|
||||
{
|
||||
"HomebaseBannerIcon:brseason04dogbowl": 1
|
||||
},
|
||||
{
|
||||
"AthenaDance:spid_008_hearts": 1
|
||||
},
|
||||
{
|
||||
"AthenaCharacter:cid_120_athena_commando_f_graffiti": 1
|
||||
},
|
||||
{
|
||||
"AthenaDance:emoji_babyseal": 1
|
||||
},
|
||||
{
|
||||
"Token:athenaseasonfriendxpboost": 5
|
||||
},
|
||||
{
|
||||
"HomebaseBannerIcon:brseason04duck": 1
|
||||
},
|
||||
{
|
||||
"Currency:mtxgiveaway": 100
|
||||
},
|
||||
{
|
||||
"AthenaLoadingScreen:lsid_019_tacticaljungle": 1
|
||||
},
|
||||
{
|
||||
"AthenaDance:spid_004_chalkoutline": 1
|
||||
},
|
||||
{
|
||||
"AccountResource:athenaseasonalxp": 1000
|
||||
},
|
||||
{
|
||||
"AthenaDance:eid_popcorn": 1
|
||||
},
|
||||
{
|
||||
"HomebaseBannerIcon:brseason04fence": 1
|
||||
},
|
||||
{
|
||||
"Token:athenaseasonxpboost": 10
|
||||
},
|
||||
{
|
||||
"AthenaDance:spid_019_circle": 1
|
||||
},
|
||||
{
|
||||
"Currency:mtxgiveaway": 100
|
||||
},
|
||||
{
|
||||
"AthenaSkyDiveContrail:trails_id_012_spraypaint": 1
|
||||
},
|
||||
{
|
||||
"AccountResource:athenaseasonalxp": 1000
|
||||
},
|
||||
{
|
||||
"AthenaDance:spid_011_looted": 1
|
||||
},
|
||||
{
|
||||
"AthenaGlider:glider_id_033_valor": 1
|
||||
},
|
||||
{
|
||||
"HomebaseBannerIcon:brseason04only90skids": 1
|
||||
},
|
||||
{
|
||||
"Token:athenaseasonfriendxpboost": 5
|
||||
},
|
||||
{
|
||||
"AthenaDance:spid_003_arrow": 1
|
||||
},
|
||||
{
|
||||
"Currency:mtxgiveaway": 100
|
||||
},
|
||||
{
|
||||
"AthenaLoadingScreen:lsid_021_leviathan": 1
|
||||
},
|
||||
{
|
||||
"AccountResource:athenaseasonalxp": 1000
|
||||
},
|
||||
{
|
||||
"AthenaDance:emoji_plotting": 1
|
||||
},
|
||||
{
|
||||
"AthenaCharacter:cid_119_athena_commando_f_candy": 1
|
||||
},
|
||||
{
|
||||
"AthenaDance:spid_012_royalstroll": 1
|
||||
},
|
||||
{
|
||||
"Token:athenaseasonxpboost": 10
|
||||
},
|
||||
{
|
||||
"AthenaSkyDiveContrail:trails_id_008_lightning": 1
|
||||
},
|
||||
{
|
||||
"Currency:mtxgiveaway": 100
|
||||
},
|
||||
{
|
||||
"AthenaDance:emoji_chicken": 1
|
||||
},
|
||||
{
|
||||
"AccountResource:athenaseasonalxp": 1000
|
||||
},
|
||||
{
|
||||
"AthenaDance:spid_005_abstract": 1
|
||||
},
|
||||
{
|
||||
"AthenaBackpack:bid_047_candy": 1
|
||||
},
|
||||
{
|
||||
"AthenaDance:spid_021_doit": 1
|
||||
},
|
||||
{
|
||||
"Token:athenaseasonfriendxpboost": 5
|
||||
},
|
||||
{
|
||||
"HomebaseBannerIcon:brseason04pencil": 1
|
||||
},
|
||||
{
|
||||
"Currency:mtxgiveaway": 100
|
||||
},
|
||||
{
|
||||
"AthenaLoadingScreen:lsid_024_graffiti": 1
|
||||
},
|
||||
{
|
||||
"AccountResource:athenaseasonalxp": 1000
|
||||
},
|
||||
{
|
||||
"AthenaDance:spid_020_threellamas": 1
|
||||
},
|
||||
{
|
||||
"AthenaDance:eid_hype": 1
|
||||
},
|
||||
{
|
||||
"AthenaDance:emoji_crabby": 1
|
||||
},
|
||||
{
|
||||
"Token:athenaseasonxpboost": 10
|
||||
},
|
||||
{
|
||||
"AthenaDance:spid_009_window": 1
|
||||
},
|
||||
{
|
||||
"Currency:mtxgiveaway": 100
|
||||
},
|
||||
{
|
||||
"AthenaSkyDiveContrail:trails_id_009_hearts": 1
|
||||
},
|
||||
{
|
||||
"HomebaseBannerIcon:brseason04blitz": 1
|
||||
},
|
||||
{
|
||||
"AthenaDance:spid_013_trapwarning": 1
|
||||
},
|
||||
{
|
||||
"AthenaCharacter:cid_118_athena_commando_f_valor": 1
|
||||
},
|
||||
{
|
||||
"AthenaDance:spid_014_raven": 1
|
||||
},
|
||||
{
|
||||
"Token:athenaseasonfriendxpboost": 5
|
||||
},
|
||||
{
|
||||
"AthenaDance:emoji_rabid": 1
|
||||
},
|
||||
{
|
||||
"Currency:mtxgiveaway": 100
|
||||
},
|
||||
{
|
||||
"AthenaLoadingScreen:lsid_023_candy": 1
|
||||
},
|
||||
{
|
||||
"HomebaseBannerIcon:brseason04filmcamera": 1
|
||||
},
|
||||
{
|
||||
"AthenaDance:spid_015_lips": 1
|
||||
},
|
||||
{
|
||||
"AthenaGlider:glider_id_034_carbideblue": 1
|
||||
},
|
||||
{
|
||||
"AthenaDance:spid_016_ponytail": 1
|
||||
},
|
||||
{
|
||||
"Token:athenaseasonxpboost": 10
|
||||
},
|
||||
{
|
||||
"HomebaseBannerIcon:brseason04bow": 1
|
||||
},
|
||||
{
|
||||
"Currency:mtxgiveaway": 100
|
||||
},
|
||||
{
|
||||
"AthenaSkyDiveContrail:trails_id_013_shootingstar": 1
|
||||
},
|
||||
{
|
||||
"AthenaLoadingScreen:lsid_022_britegunner": 1
|
||||
},
|
||||
{
|
||||
"AthenaDance:spid_017_splattershot": 1
|
||||
},
|
||||
{
|
||||
"AthenaCharacter:cid_117_athena_commando_m_tacticaljungle": 1
|
||||
},
|
||||
{
|
||||
"HomebaseBannerIcon:brseason04seaserpent": 1
|
||||
},
|
||||
{
|
||||
"Token:athenaseasonfriendxpboost": 5
|
||||
},
|
||||
{
|
||||
"AthenaDance:emoji_banana": 1
|
||||
},
|
||||
{
|
||||
"Currency:mtxgiveaway": 100
|
||||
},
|
||||
{
|
||||
"AthenaLoadingScreen:lsid_025_raven": 1
|
||||
},
|
||||
{
|
||||
"HomebaseBannerIcon:brseason04villainemblem": 1
|
||||
},
|
||||
{
|
||||
"AthenaDance:spid_010_tunnel": 1
|
||||
},
|
||||
{
|
||||
"AthenaDance:eid_groovejam": 1
|
||||
},
|
||||
{
|
||||
"Token:athenaseasonxpboost": 10
|
||||
},
|
||||
{
|
||||
"AthenaDance:emoji_celebrate": 1
|
||||
},
|
||||
{
|
||||
"Currency:mtxgiveaway": 100
|
||||
},
|
||||
{
|
||||
"AthenaDance:spid_018_shadowops": 1
|
||||
},
|
||||
{
|
||||
"AthenaCharacter:cid_116_athena_commando_m_carbideblack": 1,
|
||||
"ChallengeBundleSchedule:season4_progressiveb_schedule": 1
|
||||
}
|
||||
],
|
||||
"freeRewards": [
|
||||
{},
|
||||
{
|
||||
"ChallengeBundleSchedule:season4_starterchallenge_schedule": 1
|
||||
},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{
|
||||
"HomebaseBannerIcon:brseason04goo": 1
|
||||
},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{
|
||||
"AthenaBackpack:bid_045_tacticaljungle": 1
|
||||
},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{
|
||||
"AthenaDance:emoji_angel": 1
|
||||
},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{
|
||||
"Currency:mtxgiveaway": 100
|
||||
},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{
|
||||
"AthenaDance:emoji_teamwork": 1
|
||||
},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{
|
||||
"AthenaDance:eid_goodvibes": 1
|
||||
},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{
|
||||
"AthenaLoadingScreen:lsid_020_supplydrop": 1
|
||||
},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{
|
||||
"Currency:mtxgiveaway": 100
|
||||
},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{
|
||||
"HomebaseBannerIcon:brseason04chains": 1
|
||||
},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{
|
||||
"AthenaDance:emoji_rainbow": 1
|
||||
},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{
|
||||
"AthenaPickaxe:pickaxe_id_046_candy": 1
|
||||
},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{
|
||||
"HomebaseBannerIcon:brseason04teef": 1
|
||||
},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{
|
||||
"AthenaDance:eid_kungfusalute": 1
|
||||
},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{}
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,453 @@
|
||||
{
|
||||
"battleBundleOfferId": "FF77356F424644529049280AFC8A795E",
|
||||
"battlePassOfferId": "D51A2F28AAF843C0B208F14197FBFE91",
|
||||
"tierOfferId": "4B2E310BC1AE40B292A16D5AAD747E0A",
|
||||
"paidRewards": [
|
||||
{
|
||||
"Token:athenaseasonxpboost": 50,
|
||||
"Token:athenaseasonfriendxpboost": 10,
|
||||
"AthenaCharacter:cid_163_athena_commando_f_viking": 1,
|
||||
"AthenaCharacter:cid_161_athena_commando_m_drift": 1,
|
||||
"ChallengeBundleSchedule:season5_paid_schedule": 1,
|
||||
"Token:athenaseasonmergedxpboosts": 1,
|
||||
"ChallengeBundleSchedule:season5_progressivea_schedule": 1
|
||||
},
|
||||
{
|
||||
"Token:athenaseasonxpboost": 10,
|
||||
"Token:athenanextseasontierboost": 5
|
||||
},
|
||||
{
|
||||
"HomebaseBannerIcon:brseason05tictactoe": 1
|
||||
},
|
||||
{
|
||||
"Currency:mtxgiveaway": 100
|
||||
},
|
||||
{
|
||||
"AthenaDance:emoji_go": 1
|
||||
},
|
||||
{
|
||||
"AthenaDance:spid_038_sushi": 1
|
||||
},
|
||||
{
|
||||
"AthenaGlider:glider_id_050_streetracercobra": 1
|
||||
},
|
||||
{
|
||||
"HomebaseBannerIcon:brseason05shoppingcart": 1
|
||||
},
|
||||
{
|
||||
"Token:athenaseasonfriendxpboost": 5
|
||||
},
|
||||
{
|
||||
"Currency:mtxgiveaway": 100
|
||||
},
|
||||
{
|
||||
"AthenaDance:toy_001_basketball": 1
|
||||
},
|
||||
{
|
||||
"AthenaDance:spid_024_boogie": 1
|
||||
},
|
||||
{
|
||||
"AthenaLoadingScreen:lsid_046_vikingpattern": 1
|
||||
},
|
||||
{
|
||||
"HomebaseBannerIcon:brseason05dolphin": 1
|
||||
},
|
||||
{
|
||||
"AthenaPickaxe:pickaxe_id_073_balloon": 1
|
||||
},
|
||||
{
|
||||
"AthenaDance:emoji_poolparty": 1
|
||||
},
|
||||
{
|
||||
"Token:athenaseasonxpboost": 10
|
||||
},
|
||||
{
|
||||
"Currency:mtxgiveaway": 100
|
||||
},
|
||||
{
|
||||
"AthenaLoadingScreen:lsid_034_abstrakt": 1
|
||||
},
|
||||
{
|
||||
"AthenaSkyDiveContrail:trails_id_017_lanterns": 1
|
||||
},
|
||||
{
|
||||
"HomebaseBannerIcon:brseason05kitsune": 1
|
||||
},
|
||||
{
|
||||
"AthenaDance:spid_036_strawberrypaws": 1
|
||||
},
|
||||
{
|
||||
"AthenaCharacter:cid_162_athena_commando_f_streetracer": 1
|
||||
},
|
||||
{
|
||||
"AthenaDance:emoji_prickly": 1
|
||||
},
|
||||
{
|
||||
"Token:athenaseasonfriendxpboost": 5
|
||||
},
|
||||
{
|
||||
"Currency:mtxgiveaway": 100
|
||||
},
|
||||
{
|
||||
"AthenaDance:toy_002_golfball": 1
|
||||
},
|
||||
{
|
||||
"AthenaLoadingScreen:lsid_045_vikingfemale": 1
|
||||
},
|
||||
{
|
||||
"AthenaDance:spid_030_luchador": 1
|
||||
},
|
||||
{
|
||||
"AccountResource:athenaseasonalxp": 1000
|
||||
},
|
||||
{
|
||||
"AthenaDance:eid_youreawesome": 1
|
||||
},
|
||||
{
|
||||
"HomebaseBannerIcon:brseason05flowyhat": 1
|
||||
},
|
||||
{
|
||||
"Token:athenaseasonxpboost": 10
|
||||
},
|
||||
{
|
||||
"AthenaLoadingScreen:lsid_040_lifeguard": 1
|
||||
},
|
||||
{
|
||||
"Currency:mtxgiveaway": 100
|
||||
},
|
||||
{
|
||||
"AthenaSkyDiveContrail:trails_id_018_runes": 1
|
||||
},
|
||||
{
|
||||
"AthenaDance:emoji_stop": 1
|
||||
},
|
||||
{
|
||||
"AthenaDance:spid_034_goodvibes": 1
|
||||
},
|
||||
{
|
||||
"AthenaGlider:glider_id_048_viking": 1
|
||||
},
|
||||
{
|
||||
"AthenaDance:spid_028_durrr": 1
|
||||
},
|
||||
{
|
||||
"Token:athenaseasonfriendxpboost": 5
|
||||
},
|
||||
{
|
||||
"Currency:mtxgiveaway": 100
|
||||
},
|
||||
{
|
||||
"AthenaDance:toy_003_beachball": 1
|
||||
},
|
||||
{
|
||||
"AthenaLoadingScreen:lsid_039_jailbirds": 1
|
||||
},
|
||||
{
|
||||
"AccountResource:athenaseasonalxp": 1000
|
||||
},
|
||||
{
|
||||
"AthenaDance:emoji_embarrassed": 1
|
||||
},
|
||||
{
|
||||
"AthenaCharacter:cid_166_athena_commando_f_lifeguard": 1
|
||||
},
|
||||
{
|
||||
"AthenaDance:spid_033_fakedoor": 1
|
||||
},
|
||||
{
|
||||
"Token:athenaseasonxpboost": 10
|
||||
},
|
||||
{
|
||||
"HomebaseBannerIcon:brseason05golf": 1
|
||||
},
|
||||
{
|
||||
"Currency:mtxgiveaway": 100
|
||||
},
|
||||
{
|
||||
"AthenaDance:emoji_alarm": 1
|
||||
},
|
||||
{
|
||||
"AccountResource:athenaseasonalxp": 1000
|
||||
},
|
||||
{
|
||||
"AthenaDance:spid_037_drift": 1
|
||||
},
|
||||
{
|
||||
"AthenaBackpack:bid_071_vikingfemale": 1
|
||||
},
|
||||
{
|
||||
"HomebaseBannerIcon:brseason05icecreamtruck": 1
|
||||
},
|
||||
{
|
||||
"Token:athenaseasonfriendxpboost": 5
|
||||
},
|
||||
{
|
||||
"Currency:mtxgiveaway": 100
|
||||
},
|
||||
{
|
||||
"AthenaDance:toy_005_golfballelite": 1
|
||||
},
|
||||
{
|
||||
"AthenaLoadingScreen:lsid_044_flytrap": 1
|
||||
},
|
||||
{
|
||||
"AccountResource:athenaseasonalxp": 1000
|
||||
},
|
||||
{
|
||||
"HomebaseBannerIcon:brseason05palms": 1
|
||||
},
|
||||
{
|
||||
"AthenaDance:eid_swipeit": 1
|
||||
},
|
||||
{
|
||||
"Currency:mtxgiveaway": 100
|
||||
},
|
||||
{
|
||||
"Token:athenaseasonxpboost": 10
|
||||
},
|
||||
{
|
||||
"AthenaLoadingScreen:lsid_042_omen": 1
|
||||
},
|
||||
{
|
||||
"AthenaDance:emoji_tattered": 1
|
||||
},
|
||||
{
|
||||
"AthenaSkyDiveContrail:trails_id_016_ice": 1
|
||||
},
|
||||
{
|
||||
"HomebaseBannerIcon:brseason05spiderbadass": 1
|
||||
},
|
||||
{
|
||||
"AccountResource:athenaseasonalxp": 1000
|
||||
},
|
||||
{
|
||||
"AthenaCharacter:cid_167_athena_commando_m_tacticalbadass": 1
|
||||
},
|
||||
{
|
||||
"AthenaDance:spid_035_nordicllama": 1
|
||||
},
|
||||
{
|
||||
"Token:athenaseasonfriendxpboost": 5
|
||||
},
|
||||
{
|
||||
"Currency:mtxgiveaway": 100
|
||||
},
|
||||
{
|
||||
"AthenaDance:toy_006_beachballelite": 1
|
||||
},
|
||||
{
|
||||
"HomebaseBannerIcon:brseason05racingcheckers": 1
|
||||
},
|
||||
{
|
||||
"AthenaLoadingScreen:lsid_043_redknight": 1
|
||||
},
|
||||
{
|
||||
"AthenaDance:emoji_tasty": 1
|
||||
},
|
||||
{
|
||||
"AthenaGlider:glider_id_049_lifeguard": 1
|
||||
},
|
||||
{
|
||||
"AthenaDance:spid_032_potatoaim": 1
|
||||
},
|
||||
{
|
||||
"Token:athenaseasonxpboost": 10
|
||||
},
|
||||
{
|
||||
"HomebaseBannerIcon:brseason05scubagear": 1
|
||||
},
|
||||
{
|
||||
"Currency:mtxgiveaway": 100
|
||||
},
|
||||
{
|
||||
"AthenaSkyDiveContrail:trails_id_007_tp": 1
|
||||
},
|
||||
{
|
||||
"AthenaDance:emoji_badapple": 1
|
||||
},
|
||||
{
|
||||
"AthenaLoadingScreen:lsid_035_bandolier": 1
|
||||
},
|
||||
{
|
||||
"AthenaCharacter:cid_173_athena_commando_f_starfishuniform": 1
|
||||
},
|
||||
{
|
||||
"HomebaseBannerIcon:brseason05cobra": 1
|
||||
},
|
||||
{
|
||||
"Token:athenaseasonfriendxpboost": 5
|
||||
},
|
||||
{
|
||||
"Currency:mtxgiveaway": 100
|
||||
},
|
||||
{
|
||||
"AthenaDance:toy_004_basketballelite": 1
|
||||
},
|
||||
{
|
||||
"AthenaDance:emoji_stinky": 1
|
||||
},
|
||||
{
|
||||
"AthenaLoadingScreen:lsid_037_tomatohead": 1
|
||||
},
|
||||
{
|
||||
"AthenaDance:spid_039_yummy": 1
|
||||
},
|
||||
{
|
||||
"AthenaDance:eid_hiphops5": 1
|
||||
},
|
||||
{
|
||||
"Token:athenaseasonxpboost": 10
|
||||
},
|
||||
{
|
||||
"AthenaDance:emoji_potofgold": 1
|
||||
},
|
||||
{
|
||||
"Currency:mtxgiveaway": 100
|
||||
},
|
||||
{
|
||||
"AthenaDance:spid_026_darkviking": 1
|
||||
},
|
||||
{
|
||||
"AthenaCharacter:cid_165_athena_commando_m_darkviking": 1,
|
||||
"ChallengeBundleSchedule:season5_progressiveb_schedule": 1
|
||||
}
|
||||
],
|
||||
"freeRewards": [
|
||||
{},
|
||||
{
|
||||
"AthenaDance:spid_025_crazycastle": 1
|
||||
},
|
||||
{},
|
||||
{
|
||||
"AthenaLoadingScreen:lsid_036_drift": 1
|
||||
},
|
||||
{},
|
||||
{
|
||||
"AthenaDance:eid_stagebow": 1
|
||||
},
|
||||
{},
|
||||
{
|
||||
"AthenaDance:emoji_rockon": 1
|
||||
},
|
||||
{},
|
||||
{},
|
||||
{
|
||||
"HomebaseBannerIcon:brseason05vikingship": 1
|
||||
},
|
||||
{},
|
||||
{},
|
||||
{
|
||||
"AthenaBackpack:bid_075_tacticalbadass": 1
|
||||
},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{
|
||||
"Currency:mtxgiveaway": 100
|
||||
},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{
|
||||
"AthenaGlider:glider_id_055_streetracerblack": 1
|
||||
},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{
|
||||
"AthenaDance:spid_031_pixels": 1
|
||||
},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{
|
||||
"AthenaPickaxe:pickaxe_id_071_streetracer": 1
|
||||
},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{
|
||||
"Currency:mtxgiveaway": 100
|
||||
},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{
|
||||
"AthenaBackpack:bid_074_lifeguardfemale": 1
|
||||
},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{
|
||||
"HomebaseBannerIcon:brseason05dinosaur": 1
|
||||
},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{
|
||||
"AthenaDance:eid_calculated": 1
|
||||
},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{
|
||||
"AthenaLoadingScreen:lsid_038_highexplosives": 1
|
||||
},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{
|
||||
"AthenaSkyDiveContrail:trails_id_011_glitch": 1
|
||||
},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{
|
||||
"AthenaDance:emoji_trap": 1
|
||||
},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{
|
||||
"AthenaDance:spid_029_lasershark": 1
|
||||
},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{}
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,453 @@
|
||||
{
|
||||
"battleBundleOfferId": "19D4A5ACC90B4CDF88766A0C8A6D13FB",
|
||||
"battlePassOfferId": "9C8D0323775A4F59A1D4283E3FDB356C",
|
||||
"tierOfferId": "A6FE59C497B844068E1B5D84396F19BA",
|
||||
"paidRewards": [
|
||||
{
|
||||
"Token:athenaseasonxpboost": 50,
|
||||
"Token:athenaseasonfriendxpboost": 10,
|
||||
"AthenaCharacter:cid_233_athena_commando_m_fortnitedj": 1,
|
||||
"AthenaCharacter:cid_237_athena_commando_f_cowgirl": 1,
|
||||
"ChallengeBundleSchedule:season6_paid_schedule": 1,
|
||||
"Token:athenaseasonmergedxpboosts": 1,
|
||||
"ChallengeBundleSchedule:season6_progressivea_schedule": 1
|
||||
},
|
||||
{
|
||||
"Token:athenaseasonxpboost": 10,
|
||||
"Token:athenanextseasontierboost": 5
|
||||
},
|
||||
{
|
||||
"HomebaseBannerIcon:brseason06pickaxebr": 1
|
||||
},
|
||||
{
|
||||
"Currency:mtxgiveaway": 100
|
||||
},
|
||||
{
|
||||
"AthenaDance:emoji_bang": 1
|
||||
},
|
||||
{
|
||||
"AthenaDance:spid_058_cowgirl": 1
|
||||
},
|
||||
{
|
||||
"AthenaGlider:glider_id_079_redriding": 1
|
||||
},
|
||||
{
|
||||
"HomebaseBannerIcon:brseason06campfire": 1
|
||||
},
|
||||
{
|
||||
"Token:athenaseasonfriendxpboost": 5
|
||||
},
|
||||
{
|
||||
"AthenaLoadingScreen:lsid_052_emoticoncollage": 1
|
||||
},
|
||||
{
|
||||
"Currency:mtxgiveaway": 100
|
||||
},
|
||||
{
|
||||
"AthenaBackpack:petcarrier_001_dog": 1
|
||||
},
|
||||
{
|
||||
"AthenaMusicPack:musicpack_001_floss": 1
|
||||
},
|
||||
{
|
||||
"HomebaseBannerIcon:brseason06phantom": 1
|
||||
},
|
||||
{
|
||||
"AthenaPickaxe:pickaxe_id_103_fortnitedj": 1
|
||||
},
|
||||
{
|
||||
"AthenaDance:emoji_witchsbrew": 1
|
||||
},
|
||||
{
|
||||
"Token:athenaseasonxpboost": 10
|
||||
},
|
||||
{
|
||||
"Currency:mtxgiveaway": 100
|
||||
},
|
||||
{
|
||||
"AthenaSkyDiveContrail:trails_id_024_dieselsmoke": 1
|
||||
},
|
||||
{
|
||||
"AthenaDance:spid_050_fullmoon": 1
|
||||
},
|
||||
{
|
||||
"AthenaLoadingScreen:lsid_057_bunnies": 1
|
||||
},
|
||||
{
|
||||
"HomebaseBannerIcon:brseason06zigzag": 1
|
||||
},
|
||||
{
|
||||
"AthenaCharacter:cid_234_athena_commando_m_llamarider": 1
|
||||
},
|
||||
{
|
||||
"Token:athenaseasonfriendxpboost": 5
|
||||
},
|
||||
{
|
||||
"AthenaLoadingScreen:lsid_058_djconcept": 1
|
||||
},
|
||||
{
|
||||
"AthenaDance:emoji_plunger": 1
|
||||
},
|
||||
{
|
||||
"Currency:mtxgiveaway": 100
|
||||
},
|
||||
{
|
||||
"AthenaDance:toy_007_tomato": 1
|
||||
},
|
||||
{
|
||||
"AthenaBackpack:petcarrier_002_chameleon": 1
|
||||
},
|
||||
{
|
||||
"AthenaDance:spid_056_manholecover": 1
|
||||
},
|
||||
{
|
||||
"AthenaDance:eid_runningman": 1
|
||||
},
|
||||
{
|
||||
"HomebaseBannerIcon:brseason06dice": 1
|
||||
},
|
||||
{
|
||||
"Token:athenaseasonxpboost": 10
|
||||
},
|
||||
{
|
||||
"AthenaLoadingScreen:lsid_055_valkyrie": 1
|
||||
},
|
||||
{
|
||||
"Currency:mtxgiveaway": 100
|
||||
},
|
||||
{
|
||||
"AthenaSkyDiveContrail:trails_id_023_fireflies": 1
|
||||
},
|
||||
{
|
||||
"AthenaDance:spid_060_dayofdead": 1
|
||||
},
|
||||
{
|
||||
"AthenaDance:emoji_camper": 1
|
||||
},
|
||||
{
|
||||
"AthenaGlider:glider_id_080_prairiepusher": 1
|
||||
},
|
||||
{
|
||||
"AthenaDance:spid_059_dj": 1
|
||||
},
|
||||
{
|
||||
"Token:athenaseasonfriendxpboost": 5
|
||||
},
|
||||
{
|
||||
"Currency:mtxgiveaway": 100
|
||||
},
|
||||
{
|
||||
"AthenaBackpack:petcarrier_003_dragon": 1
|
||||
},
|
||||
{
|
||||
"AthenaLoadingScreen:lsid_056_fate": 1
|
||||
},
|
||||
{
|
||||
"AccountResource:athenaseasonalxp": 1000
|
||||
},
|
||||
{
|
||||
"AthenaDance:emoji_ghost": 1
|
||||
},
|
||||
{
|
||||
"AthenaCharacter:cid_231_athena_commando_f_redriding": 1
|
||||
},
|
||||
{
|
||||
"AthenaDance:spid_055_wallcrawler": 1
|
||||
},
|
||||
{
|
||||
"Token:athenaseasonxpboost": 10
|
||||
},
|
||||
{
|
||||
"HomebaseBannerIcon:brseason06rift": 1
|
||||
},
|
||||
{
|
||||
"AthenaDance:emoji_blackcat": 1
|
||||
},
|
||||
{
|
||||
"Currency:mtxgiveaway": 100
|
||||
},
|
||||
{
|
||||
"AthenaMusicPack:musicpack_002_spooky": 1
|
||||
},
|
||||
{
|
||||
"AthenaDance:spid_049_cactusmaze": 1
|
||||
},
|
||||
{
|
||||
"AthenaBackpack:bid_119_vampirefemale": 1
|
||||
},
|
||||
{
|
||||
"HomebaseBannerIcon:brseason06bat": 1
|
||||
},
|
||||
{
|
||||
"Token:athenaseasonfriendxpboost": 5
|
||||
},
|
||||
{
|
||||
"Currency:mtxgiveaway": 100
|
||||
},
|
||||
{
|
||||
"CosmeticVariantToken:vtid_033_petcarrier_dog_styleb": 1
|
||||
},
|
||||
{
|
||||
"AthenaLoadingScreen:lsid_050_tomatotemple": 1
|
||||
},
|
||||
{
|
||||
"AccountResource:athenaseasonalxp": 1000
|
||||
},
|
||||
{
|
||||
"HomebaseBannerIcon:brseason06carbonfiber": 1
|
||||
},
|
||||
{
|
||||
"AthenaDance:eid_octopus": 1
|
||||
},
|
||||
{
|
||||
"Token:athenaseasonxpboost": 10
|
||||
},
|
||||
{
|
||||
"AthenaLoadingScreen:lsid_054_scuba": 1
|
||||
},
|
||||
{
|
||||
"AthenaDance:emoji_meet": 1
|
||||
},
|
||||
{
|
||||
"AccountResource:athenaseasonalxp": 1000
|
||||
},
|
||||
{
|
||||
"AthenaSkyDiveContrail:trails_id_026_bats": 1
|
||||
},
|
||||
{
|
||||
"HomebaseBannerIcon:brseason06polkadots": 1
|
||||
},
|
||||
{
|
||||
"Currency:mtxgiveaway": 100
|
||||
},
|
||||
{
|
||||
"AthenaCharacter:cid_227_athena_commando_f_vampire": 1
|
||||
},
|
||||
{
|
||||
"AthenaDance:spid_047_gremlins": 1
|
||||
},
|
||||
{
|
||||
"Token:athenaseasonfriendxpboost": 5
|
||||
},
|
||||
{
|
||||
"CosmeticVariantToken:vtid_035_petcarrier_dragon_styleb": 1
|
||||
},
|
||||
{
|
||||
"Currency:mtxgiveaway": 100
|
||||
},
|
||||
{
|
||||
"AthenaDance:toy_008_tomatoelite": 1
|
||||
},
|
||||
{
|
||||
"HomebaseBannerIcon:brseason06housefly": 1
|
||||
},
|
||||
{
|
||||
"AthenaLoadingScreen:lsid_059_vampire": 1
|
||||
},
|
||||
{
|
||||
"AthenaGlider:glider_id_078_vampire": 1
|
||||
},
|
||||
{
|
||||
"AthenaDance:spid_045_oni": 1
|
||||
},
|
||||
{
|
||||
"Token:athenaseasonxpboost": 10
|
||||
},
|
||||
{
|
||||
"HomebaseBannerIcon:brseason06skulltrooper": 1
|
||||
},
|
||||
{
|
||||
"AthenaSkyDiveContrail:trails_id_022_greensmoke": 1
|
||||
},
|
||||
{
|
||||
"AthenaLoadingScreen:lsid_051_ravage": 1
|
||||
},
|
||||
{
|
||||
"Currency:mtxgiveaway": 100
|
||||
},
|
||||
{
|
||||
"AthenaCharacter:cid_232_athena_commando_f_halloweentomato": 1
|
||||
},
|
||||
{
|
||||
"AthenaBackpack:bid_122_halloweentomato": 1
|
||||
},
|
||||
{
|
||||
"Token:athenaseasonfriendxpboost": 5
|
||||
},
|
||||
{
|
||||
"AthenaDance:spid_046_pixelraven": 1
|
||||
},
|
||||
{
|
||||
"CosmeticVariantToken:vtid_034_petcarrier_dog_stylec": 1
|
||||
},
|
||||
{
|
||||
"Currency:mtxgiveaway": 100
|
||||
},
|
||||
{
|
||||
"AthenaMusicPack:musicpack_003_ogremix": 1
|
||||
},
|
||||
{
|
||||
"AthenaLoadingScreen:lsid_061_werewolf": 1
|
||||
},
|
||||
{
|
||||
"AthenaDance:emoji_clown": 1
|
||||
},
|
||||
{
|
||||
"AthenaDance:eid_flamenco": 1
|
||||
},
|
||||
{
|
||||
"Token:athenaseasonxpboost": 10
|
||||
},
|
||||
{
|
||||
"Currency:mtxgiveaway": 100
|
||||
},
|
||||
{
|
||||
"CosmeticVariantToken:vtid_036_petcarrier_dragon_stylec": 1
|
||||
},
|
||||
{
|
||||
"AthenaDance:spid_062_werewolf": 1
|
||||
},
|
||||
{
|
||||
"AthenaCharacter:cid_230_athena_commando_m_werewolf": 1,
|
||||
"ChallengeBundleSchedule:season6_progressiveb_schedule": 1
|
||||
}
|
||||
],
|
||||
"freeRewards": [
|
||||
{},
|
||||
{
|
||||
"AthenaDance:spid_061_spiderweb": 1
|
||||
},
|
||||
{},
|
||||
{
|
||||
"AthenaLoadingScreen:lsid_060_cowgirl": 1
|
||||
},
|
||||
{},
|
||||
{
|
||||
"AthenaDance:eid_regalwave": 1
|
||||
},
|
||||
{},
|
||||
{
|
||||
"AthenaDance:emoji_battlebus": 1
|
||||
},
|
||||
{},
|
||||
{},
|
||||
{
|
||||
"HomebaseBannerIcon:brseason06floatingisland": 1
|
||||
},
|
||||
{},
|
||||
{},
|
||||
{
|
||||
"AthenaBackpack:bid_121_redriding": 1
|
||||
},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{
|
||||
"Currency:mtxgiveaway": 100
|
||||
},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{
|
||||
"AthenaGlider:glider_id_081_cowboygunslinger": 1
|
||||
},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{
|
||||
"AthenaDance:spid_053_ggpotion": 1
|
||||
},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{
|
||||
"AthenaPickaxe:pickaxe_id_102_redriding": 1
|
||||
},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{
|
||||
"Currency:mtxgiveaway": 100
|
||||
},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{
|
||||
"AthenaBackpack:bid_123_fortnitedj": 1
|
||||
},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{
|
||||
"HomebaseBannerIcon:brseason06handhorns": 1
|
||||
},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{
|
||||
"AthenaDance:eid_needtogo": 1
|
||||
},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{
|
||||
"AthenaLoadingScreen:lsid_053_supplyllama": 1
|
||||
},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{
|
||||
"AthenaSkyDiveContrail:trails_id_025_jackolantern": 1
|
||||
},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{
|
||||
"AthenaDance:emoji_tp": 1
|
||||
},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{
|
||||
"AthenaDance:spid_051_gameover": 1
|
||||
},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{}
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,454 @@
|
||||
{
|
||||
"battleBundleOfferId": "347A90158C64424980E8C1B3DC088F37",
|
||||
"battlePassOfferId": "3A3C99847F144AF3A030DB5690477F5A",
|
||||
"tierOfferId": "64A3020B098841A7805EE257D68C554F",
|
||||
"paidRewards": [
|
||||
{
|
||||
"Token:athenaseasonxpboost": 50,
|
||||
"Token:athenaseasonfriendxpboost": 10,
|
||||
"AthenaCharacter:cid_287_athena_commando_m_arcticsniper": 1,
|
||||
"AthenaCharacter:cid_286_athena_commando_f_neoncat": 1,
|
||||
"ChallengeBundleSchedule:season7_paid_schedule": 1,
|
||||
"Token:athenaseasonmergedxpboosts": 1,
|
||||
"ChallengeBundleSchedule:season7_progressivea_schedule": 1
|
||||
},
|
||||
{
|
||||
"Token:athenaseasonxpboost": 10,
|
||||
"Token:athenanextseasontierboost": 5
|
||||
},
|
||||
{
|
||||
"HomebaseBannerIcon:brseason07wreath": 1
|
||||
},
|
||||
{
|
||||
"Currency:mtxgiveaway": 100
|
||||
},
|
||||
{
|
||||
"AthenaItemWrap:wrap_001_arcticcamo": 1
|
||||
},
|
||||
{
|
||||
"AthenaDance:emoji_mistletoe": 1
|
||||
},
|
||||
{
|
||||
"AthenaBackpack:bid_160_tacticalsantamale": 1
|
||||
},
|
||||
{
|
||||
"AthenaDance:spid_068_eviltree": 1
|
||||
},
|
||||
{
|
||||
"Token:athenaseasonfriendxpboost": 5
|
||||
},
|
||||
{
|
||||
"Currency:mtxgiveaway": 100
|
||||
},
|
||||
{
|
||||
"AthenaItemWrap:wrap_002_holidaygreen": 1
|
||||
},
|
||||
{
|
||||
"AthenaLoadingScreen:lsid_080_gingerbread": 1
|
||||
},
|
||||
{
|
||||
"AthenaMusicPack:musicpack_004_holiday": 1
|
||||
},
|
||||
{
|
||||
"HomebaseBannerIcon:brseason07merryface": 1
|
||||
},
|
||||
{
|
||||
"AthenaGlider:glider_id_101_tacticalsanta": 1
|
||||
},
|
||||
{
|
||||
"AthenaDance:emoji_ggwreath": 1
|
||||
},
|
||||
{
|
||||
"Token:athenaseasonxpboost": 10
|
||||
},
|
||||
{
|
||||
"Currency:mtxgiveaway": 100
|
||||
},
|
||||
{
|
||||
"AthenaBackpack:petcarrier_004_hamster": 1
|
||||
},
|
||||
{
|
||||
"AthenaDance:spid_069_bagofcoal": 1
|
||||
},
|
||||
{
|
||||
"AthenaSkyDiveContrail:trails_id_032_stringlights": 1
|
||||
},
|
||||
{
|
||||
"AthenaLoadingScreen:lsid_075_tacticalsanta": 1
|
||||
},
|
||||
{
|
||||
"AthenaCharacter:cid_279_athena_commando_m_tacticalsanta": 1,
|
||||
"ChallengeBundleSchedule:season7_sgtwinter_schedule": 1
|
||||
},
|
||||
{
|
||||
"Token:athenaseasonfriendxpboost": 5
|
||||
},
|
||||
{
|
||||
"AthenaDance:emoji_gingerbreadhappy": 1
|
||||
},
|
||||
{
|
||||
"AthenaItemWrap:wrap_003_anodizedred": 1
|
||||
},
|
||||
{
|
||||
"Currency:mtxgiveaway": 100
|
||||
},
|
||||
{
|
||||
"AthenaDance:toy_010_icepuck": 1
|
||||
},
|
||||
{
|
||||
"HomebaseBannerIcon:brseason07tartan": 1
|
||||
},
|
||||
{
|
||||
"AthenaLoadingScreen:lsid_083_crackshot": 1
|
||||
},
|
||||
{
|
||||
"AthenaDance:eid_wristflick": 1
|
||||
},
|
||||
{
|
||||
"AthenaDance:emoji_gingerbreadmad": 1
|
||||
},
|
||||
{
|
||||
"Token:athenaseasonxpboost": 10
|
||||
},
|
||||
{
|
||||
"Currency:mtxgiveaway": 100
|
||||
},
|
||||
{
|
||||
"AthenaBackpack:petcarrier_005_wolf": 1
|
||||
},
|
||||
{
|
||||
"AthenaDance:spid_071_neoncat": 1
|
||||
},
|
||||
{
|
||||
"AthenaSkyDiveContrail:trails_id_037_glyphs": 1
|
||||
},
|
||||
{
|
||||
"HomebaseBannerIcon:brseason07iceninjastar": 1
|
||||
},
|
||||
{
|
||||
"AthenaGlider:glider_id_104_durrburger": 1
|
||||
},
|
||||
{
|
||||
"AthenaLoadingScreen:lsid_081_tenderdefender": 1
|
||||
},
|
||||
{
|
||||
"Token:athenaseasonfriendxpboost": 5
|
||||
},
|
||||
{
|
||||
"Currency:mtxgiveaway": 100
|
||||
},
|
||||
{
|
||||
"AthenaItemWrap:wrap_004_durrburgerpjs": 1
|
||||
},
|
||||
{
|
||||
"AthenaDance:spid_072_mothhead": 1
|
||||
},
|
||||
{
|
||||
"AccountResource:athenaseasonalxp": 1000
|
||||
},
|
||||
{
|
||||
"AthenaDance:emoji_mittens": 1
|
||||
},
|
||||
{
|
||||
"AthenaCharacter:cid_281_athena_commando_f_snowboard": 1
|
||||
},
|
||||
{
|
||||
"AthenaDance:spid_073_porthole": 1
|
||||
},
|
||||
{
|
||||
"Token:athenaseasonxpboost": 10
|
||||
},
|
||||
{
|
||||
"HomebaseBannerIcon:brseason07meat": 1
|
||||
},
|
||||
{
|
||||
"Currency:mtxgiveaway": 100
|
||||
},
|
||||
{
|
||||
"CosmeticVariantToken:vtid_054_petcarrier_hamster_styleb": 1
|
||||
},
|
||||
{
|
||||
"AthenaDance:emoji_huskwow": 1
|
||||
},
|
||||
{
|
||||
"AthenaDance:spid_074_cuddlehula": 1
|
||||
},
|
||||
{
|
||||
"AthenaBackpack:bid_162_yetimale": 1
|
||||
},
|
||||
{
|
||||
"HomebaseBannerIcon:brseason07trash": 1
|
||||
},
|
||||
{
|
||||
"Token:athenaseasonfriendxpboost": 5
|
||||
},
|
||||
{
|
||||
"AthenaSkyDiveContrail:trails_id_036_fiberoptics": 1
|
||||
},
|
||||
{
|
||||
"Currency:mtxgiveaway": 100
|
||||
},
|
||||
{
|
||||
"AthenaItemWrap:wrap_006_ice": 1
|
||||
},
|
||||
{
|
||||
"AccountResource:athenaseasonalxp": 1000
|
||||
},
|
||||
{
|
||||
"HomebaseBannerIcon:brseason07sun": 1
|
||||
},
|
||||
{
|
||||
"AthenaDance:eid_getfunky": 1
|
||||
},
|
||||
{
|
||||
"Token:athenaseasonxpboost": 10
|
||||
},
|
||||
{
|
||||
"AthenaLoadingScreen:lsid_076_medics": 1
|
||||
},
|
||||
{
|
||||
"AccountResource:athenaseasonalxp": 1000
|
||||
},
|
||||
{
|
||||
"CosmeticVariantToken:vtid_056_petcarrier_wolf_styleb": 1
|
||||
},
|
||||
{
|
||||
"AthenaDance:emoji_penguin": 1
|
||||
},
|
||||
{
|
||||
"Currency:mtxgiveaway": 100
|
||||
},
|
||||
{
|
||||
"AthenaDance:spid_081_bananas": 1
|
||||
},
|
||||
{
|
||||
"AthenaCharacter:cid_278_athena_commando_m_yeti": 1
|
||||
},
|
||||
{
|
||||
"AthenaDance:spid_076_yeti": 1
|
||||
},
|
||||
{
|
||||
"Token:athenaseasonfriendxpboost": 5
|
||||
},
|
||||
{
|
||||
"AthenaItemWrap:wrap_005_carbonfiber": 1
|
||||
},
|
||||
{
|
||||
"Currency:mtxgiveaway": 100
|
||||
},
|
||||
{
|
||||
"AthenaDance:toy_009_burgerelite": 1
|
||||
},
|
||||
{
|
||||
"HomebaseBannerIcon:brseason07shackle": 1
|
||||
},
|
||||
{
|
||||
"AthenaLoadingScreen:lsid_074_darkbomber": 1
|
||||
},
|
||||
{
|
||||
"AthenaGlider:glider_id_100_yeti": 1
|
||||
},
|
||||
{
|
||||
"AthenaDance:spid_077_baited": 1
|
||||
},
|
||||
{
|
||||
"Token:athenaseasonxpboost": 10
|
||||
},
|
||||
{
|
||||
"Currency:mtxgiveaway": 100
|
||||
},
|
||||
{
|
||||
"CosmeticVariantToken:vtid_055_petcarrier_hamster_stylec": 1
|
||||
},
|
||||
{
|
||||
"HomebaseBannerIcon:brseason07octopus": 1
|
||||
},
|
||||
{
|
||||
"AthenaSkyDiveContrail:trails_id_034_swirlysmoke": 1
|
||||
},
|
||||
{
|
||||
"AthenaDance:emoji_durrrburger": 1
|
||||
},
|
||||
{
|
||||
"AthenaCharacter:cid_245_athena_commando_f_durrburgerpjs": 1
|
||||
},
|
||||
{
|
||||
"Token:athenaseasonfriendxpboost": 5
|
||||
},
|
||||
{
|
||||
"AthenaDance:spid_078_pixelramirez": 1
|
||||
},
|
||||
{
|
||||
"AthenaLoadingScreen:lsid_078_skulltrooper": 1
|
||||
},
|
||||
{
|
||||
"Currency:mtxgiveaway": 100
|
||||
},
|
||||
{
|
||||
"AthenaMusicPack:musicpack_006_twist": 1
|
||||
},
|
||||
{
|
||||
"CosmeticVariantToken:vtid_057_petcarrier_wolf_stylec": 1
|
||||
},
|
||||
{
|
||||
"AthenaDance:emoji_fkey": 1
|
||||
},
|
||||
{
|
||||
"AthenaDance:eid_hiphops7": 1
|
||||
},
|
||||
{
|
||||
"Token:athenaseasonxpboost": 10
|
||||
},
|
||||
{
|
||||
"Currency:mtxgiveaway": 100
|
||||
},
|
||||
{
|
||||
"AthenaLoadingScreen:lsid_073_dustydepot": 1
|
||||
},
|
||||
{
|
||||
"AthenaDance:spid_079_catgirl": 1
|
||||
},
|
||||
{
|
||||
"AthenaCharacter:cid_288_athena_commando_m_iceking": 1,
|
||||
"ChallengeBundleSchedule:season7_iceking_schedule": 1
|
||||
}
|
||||
],
|
||||
"freeRewards": [
|
||||
{},
|
||||
{
|
||||
"AthenaDance:spid_067_ggsnowman": 1
|
||||
},
|
||||
{},
|
||||
{
|
||||
"AthenaLoadingScreen:lsid_079_plane": 1
|
||||
},
|
||||
{},
|
||||
{
|
||||
"AthenaSkyDiveContrail:trails_id_033_snowflakes": 1
|
||||
},
|
||||
{},
|
||||
{
|
||||
"AthenaDance:emoji_iceheart": 1
|
||||
},
|
||||
{},
|
||||
{},
|
||||
{
|
||||
"HomebaseBannerIcon:brseason07plane": 1
|
||||
},
|
||||
{},
|
||||
{},
|
||||
{
|
||||
"AthenaDance:eid_golfclap": 1
|
||||
},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{
|
||||
"Currency:mtxgiveaway": 100
|
||||
},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{
|
||||
"AthenaBackpack:bid_161_snowboardfemale": 1
|
||||
},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{
|
||||
"AthenaDance:spid_070_hohoho": 1
|
||||
},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{
|
||||
"AthenaGlider:glider_id_105_snowboard": 1
|
||||
},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{
|
||||
"Currency:mtxgiveaway": 100
|
||||
},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{
|
||||
"AthenaPickaxe:pickaxe_id_126_yeti": 1
|
||||
},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{
|
||||
"HomebaseBannerIcon:brseason07infinityblade": 1
|
||||
},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{
|
||||
"AthenaDance:eid_micdrop": 1
|
||||
},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{
|
||||
"AthenaLoadingScreen:lsid_082_neoncat": 1
|
||||
},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{
|
||||
"AthenaMusicPack:musicpack_005_disco": 1
|
||||
},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{
|
||||
"AthenaDance:emoji_hotchocolate": 1
|
||||
},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{
|
||||
"AthenaDance:spid_075_meltingsnowman": 1
|
||||
},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{}
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,453 @@
|
||||
{
|
||||
"battleBundleOfferId": "18D9DA48000A40BFAEBAC55A99C55221",
|
||||
"battlePassOfferId": "77F31B7F83FB422195DA60CDE683671D",
|
||||
"tierOfferId": "E07E41D52D4A425F8DC6592496B75301",
|
||||
"paidRewards": [
|
||||
{
|
||||
"Token:athenaseasonxpboost": 50,
|
||||
"Token:athenaseasonfriendxpboost": 60,
|
||||
"AthenaCharacter:cid_347_athena_commando_m_pirateprogressive": 1,
|
||||
"AthenaCharacter:cid_346_athena_commando_m_dragonninja": 1,
|
||||
"ChallengeBundleSchedule:season8_paid_schedule": 1,
|
||||
"ChallengeBundleSchedule:season8_cumulative_schedule": 1,
|
||||
"Token:athenaseasonmergedxpboosts": 1
|
||||
},
|
||||
{
|
||||
"Token:athenaseasonxpboost": 10,
|
||||
"Token:athenanextseasonxpboost": 30
|
||||
},
|
||||
{
|
||||
"HomebaseBannerIcon:brs8pineapple": 1
|
||||
},
|
||||
{
|
||||
"Currency:mtxgiveaway": 100
|
||||
},
|
||||
{
|
||||
"AthenaItemWrap:wrap_020_tropicalcamo": 1
|
||||
},
|
||||
{
|
||||
"AthenaDance:spid_091_dragonninja": 1
|
||||
},
|
||||
{
|
||||
"AthenaBackpack:bid_218_medusa": 1
|
||||
},
|
||||
{
|
||||
"HomebaseBannerIcon:brs8jellyfish": 1
|
||||
},
|
||||
{
|
||||
"Token:athenaseasonfriendxpboost": 10
|
||||
},
|
||||
{
|
||||
"AthenaLoadingScreen:lsid_106_treasuremap": 1
|
||||
},
|
||||
{
|
||||
"Currency:mtxgiveaway": 100
|
||||
},
|
||||
{
|
||||
"AthenaMusicPack:musicpack_007_pirate": 1
|
||||
},
|
||||
{
|
||||
"AthenaDance:emoji_palmtree": 1
|
||||
},
|
||||
{
|
||||
"AthenaDance:spid_092_bananapeel": 1
|
||||
},
|
||||
{
|
||||
"AthenaGlider:glider_id_124_medusa": 1
|
||||
},
|
||||
{
|
||||
"AthenaDance:emoji_octopirate": 1
|
||||
},
|
||||
{
|
||||
"Token:athenaseasonxpboost": 10
|
||||
},
|
||||
{
|
||||
"Currency:mtxgiveaway": 100
|
||||
},
|
||||
{
|
||||
"AthenaBackpack:petcarrier_007_woodsy": 1
|
||||
},
|
||||
{
|
||||
"AthenaDance:spid_103_mermaid": 1
|
||||
},
|
||||
{
|
||||
"AthenaSkyDiveContrail:trails_id_046_clover": 1
|
||||
},
|
||||
{
|
||||
"AthenaLoadingScreen:lsid_100_stpattyday": 1
|
||||
},
|
||||
{
|
||||
"AthenaCharacter:cid_348_athena_commando_f_medusa": 1
|
||||
},
|
||||
{
|
||||
"Token:athenaseasonfriendxpboost": 10
|
||||
},
|
||||
{
|
||||
"AthenaDance:emoji_4leafclover": 1
|
||||
},
|
||||
{
|
||||
"AthenaDance:toy_014_bouncyball": 1
|
||||
},
|
||||
{
|
||||
"Currency:mtxgiveaway": 100
|
||||
},
|
||||
{
|
||||
"AthenaItemWrap:wrap_021_pirate": 1
|
||||
},
|
||||
{
|
||||
"HomebaseBannerIcon:brs8ziggurat": 1
|
||||
},
|
||||
{
|
||||
"AthenaLoadingScreen:lsid_101_icequeen": 1
|
||||
},
|
||||
{
|
||||
"AthenaDance:eid_conga": 1
|
||||
},
|
||||
{
|
||||
"AthenaDance:emoji_spicy": 1
|
||||
},
|
||||
{
|
||||
"Token:athenaseasonxpboost": 10
|
||||
},
|
||||
{
|
||||
"Currency:mtxgiveaway": 100
|
||||
},
|
||||
{
|
||||
"CosmeticVariantToken:vtid_129_petcarrier_woodsy_styleb": 1
|
||||
},
|
||||
{
|
||||
"AthenaDance:spid_099_key": 1
|
||||
},
|
||||
{
|
||||
"AthenaSkyDiveContrail:trails_id_048_spectral": 1
|
||||
},
|
||||
{
|
||||
"HomebaseBannerIcon:brs8coconuts": 1
|
||||
},
|
||||
{
|
||||
"AthenaGlider:glider_id_123_masterkey": 1
|
||||
},
|
||||
{
|
||||
"AthenaLoadingScreen:lsid_102_triceraops": 1
|
||||
},
|
||||
{
|
||||
"Token:athenaseasonfriendxpboost": 10
|
||||
},
|
||||
{
|
||||
"Currency:mtxgiveaway": 100
|
||||
},
|
||||
{
|
||||
"AthenaItemWrap:wrap_023_aztec": 1
|
||||
},
|
||||
{
|
||||
"AthenaDance:spid_094_wootdog": 1
|
||||
},
|
||||
{
|
||||
"AccountResource:athenaseasonalxp": 1000
|
||||
},
|
||||
{
|
||||
"AthenaDance:emoji_skullbrite": 1
|
||||
},
|
||||
{
|
||||
"AthenaCharacter:cid_349_athena_commando_m_banana": 1
|
||||
},
|
||||
{
|
||||
"AthenaDance:spid_095_loveranger": 1
|
||||
},
|
||||
{
|
||||
"Token:athenaseasonxpboost": 10
|
||||
},
|
||||
{
|
||||
"HomebaseBannerIcon:brs8foxhead": 1
|
||||
},
|
||||
{
|
||||
"Currency:mtxgiveaway": 100
|
||||
},
|
||||
{
|
||||
"AthenaBackpack:petcarrier_008_fox": 1
|
||||
},
|
||||
{
|
||||
"AthenaDance:emoji_aztecmask": 1
|
||||
},
|
||||
{
|
||||
"AthenaDance:spid_096_fallenloveranger": 1
|
||||
},
|
||||
{
|
||||
"AthenaPickaxe:pickaxe_id_165_masterkey": 1
|
||||
},
|
||||
{
|
||||
"HomebaseBannerIcon:brs8roach": 1
|
||||
},
|
||||
{
|
||||
"Token:athenaseasonfriendxpboost": 10
|
||||
},
|
||||
{
|
||||
"AthenaSkyDiveContrail:trails_id_044_lava": 1
|
||||
},
|
||||
{
|
||||
"Currency:mtxgiveaway": 100
|
||||
},
|
||||
{
|
||||
"AthenaItemWrap:wrap_017_dragonninja": 1
|
||||
},
|
||||
{
|
||||
"AccountResource:athenaseasonalxp": 1000
|
||||
},
|
||||
{
|
||||
"HomebaseBannerIcon:brs8whaletail": 1
|
||||
},
|
||||
{
|
||||
"AthenaDance:eid_banana": 1
|
||||
},
|
||||
{
|
||||
"Token:athenaseasonxpboost": 10
|
||||
},
|
||||
{
|
||||
"AthenaLoadingScreen:lsid_103_spraycollage": 1
|
||||
},
|
||||
{
|
||||
"AccountResource:athenaseasonalxp": 1000
|
||||
},
|
||||
{
|
||||
"CosmeticVariantToken:vtid_131_petcarrier_fox_styleb": 1
|
||||
},
|
||||
{
|
||||
"AthenaDance:spid_101_britebomber": 1
|
||||
},
|
||||
{
|
||||
"Currency:mtxgiveaway": 100
|
||||
},
|
||||
{
|
||||
"AthenaDance:emoji_200m": 1
|
||||
},
|
||||
{
|
||||
"AthenaCharacter:cid_351_athena_commando_f_fireelf": 1
|
||||
},
|
||||
{
|
||||
"HomebaseBannerIcon:brs8tigerstripes": 1
|
||||
},
|
||||
{
|
||||
"Token:athenaseasonfriendxpboost": 10
|
||||
},
|
||||
{
|
||||
"AthenaLoadingScreen:lsid_097_powerchord": 1
|
||||
},
|
||||
{
|
||||
"AthenaDance:spid_097_fireelf": 1
|
||||
},
|
||||
{
|
||||
"Currency:mtxgiveaway": 100
|
||||
},
|
||||
{
|
||||
"AthenaItemWrap:wrap_019_tiger": 1
|
||||
},
|
||||
{
|
||||
"AthenaDance:emoji_cuddle": 1
|
||||
},
|
||||
{
|
||||
"AthenaGlider:glider_id_128_bootybuoy": 1
|
||||
},
|
||||
{
|
||||
"AthenaDance:spid_100_salty": 1
|
||||
},
|
||||
{
|
||||
"Token:athenaseasonxpboost": 10
|
||||
},
|
||||
{
|
||||
"Currency:mtxgiveaway": 100
|
||||
},
|
||||
{
|
||||
"CosmeticVariantToken:vtid_130_petcarrier_woodsy_stylec": 1
|
||||
},
|
||||
{
|
||||
"AthenaLoadingScreen:lsid_104_masterkey": 1
|
||||
},
|
||||
{
|
||||
"AthenaSkyDiveContrail:trails_id_047_ammobelt": 1
|
||||
},
|
||||
{
|
||||
"HomebaseBannerIcon:brs8crystalllama": 1
|
||||
},
|
||||
{
|
||||
"AthenaCharacter:cid_350_athena_commando_m_masterkey": 1
|
||||
},
|
||||
{
|
||||
"Token:athenaseasonfriendxpboost": 10
|
||||
},
|
||||
{
|
||||
"AthenaDance:emoji_angryvolcano": 1
|
||||
},
|
||||
{
|
||||
"AthenaDance:spid_098_shiny": 1
|
||||
},
|
||||
{
|
||||
"Currency:mtxgiveaway": 100
|
||||
},
|
||||
{
|
||||
"AthenaMusicPack:musicpack_009_starpower": 1
|
||||
},
|
||||
{
|
||||
"CosmeticVariantToken:vtid_132_petcarrier_fox_stylec": 1
|
||||
},
|
||||
{
|
||||
"AthenaLoadingScreen:lsid_105_blackwidow": 1
|
||||
},
|
||||
{
|
||||
"AthenaDance:eid_hulahoop": 1
|
||||
},
|
||||
{
|
||||
"Token:athenaseasonxpboost": 10
|
||||
},
|
||||
{
|
||||
"Currency:mtxgiveaway": 100
|
||||
},
|
||||
{
|
||||
"AthenaItemWrap:wrap_022_gemstone": 1
|
||||
},
|
||||
{
|
||||
"CosmeticVariantToken:vtid_128_masterkey_styleb": 1
|
||||
},
|
||||
{
|
||||
"AthenaCharacter:cid_352_athena_commando_f_shiny": 1,
|
||||
"ChallengeBundleSchedule:season8_shiny_schedule": 1
|
||||
}
|
||||
],
|
||||
"freeRewards": [
|
||||
{},
|
||||
{
|
||||
"AthenaDance:spid_102_ggaztec": 1
|
||||
},
|
||||
{},
|
||||
{
|
||||
"AthenaLoadingScreen:lsid_099_piratetheme": 1
|
||||
},
|
||||
{},
|
||||
{
|
||||
"AthenaSkyDiveContrail:trails_id_045_undertow": 1
|
||||
},
|
||||
{},
|
||||
{
|
||||
"AthenaDance:emoji_sun": 1
|
||||
},
|
||||
{},
|
||||
{},
|
||||
{
|
||||
"Currency:mtxgiveaway": 100
|
||||
},
|
||||
{},
|
||||
{},
|
||||
{
|
||||
"AthenaDance:eid_happywave": 1
|
||||
},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{
|
||||
"HomebaseBannerIcon:brs8jollyroger": 1
|
||||
},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{
|
||||
"AthenaBackpack:bid_215_masterkey": 1
|
||||
},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{
|
||||
"AthenaDance:spid_090_dancefloorbox": 1
|
||||
},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{
|
||||
"AthenaGlider:glider_id_129_fireelf": 1
|
||||
},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{
|
||||
"Currency:mtxgiveaway": 100
|
||||
},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{
|
||||
"AthenaPickaxe:pickaxe_id_167_medusa": 1
|
||||
},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{
|
||||
"HomebaseBannerIcon:brs8treasurechest": 1
|
||||
},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{
|
||||
"AthenaDance:eid_youboreme": 1
|
||||
},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{
|
||||
"AthenaLoadingScreen:lsid_098_dragonninja": 1
|
||||
},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{
|
||||
"AthenaMusicPack:musicpack_008_coral": 1
|
||||
},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{
|
||||
"AthenaDance:emoji_ggjellyfish": 1
|
||||
},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{
|
||||
"AthenaDance:spid_093_theend": 1
|
||||
},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{}
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,458 @@
|
||||
{
|
||||
"battleBundleOfferId": "C7190ACA4E5E228A94CA3CB9C3FC7AE9",
|
||||
"battlePassOfferId": "73E6EE6F4526EF97450D1592C3DB0EF5",
|
||||
"tierOfferId": "33E185A84ED7B64F2856E69AADFD092C",
|
||||
"paidRewards": [
|
||||
{
|
||||
"Token:athenaseasonxpboost": 50,
|
||||
"Token:athenaseasonfriendxpboost": 60,
|
||||
"AthenaCharacter:cid_408_athena_commando_f_strawberrypilot": 1,
|
||||
"AthenaCharacter:cid_403_athena_commando_m_rooster": 1,
|
||||
"ChallengeBundleSchedule:season9_paid_schedule": 1,
|
||||
"ChallengeBundleSchedule:season9_cumulative_schedule": 1,
|
||||
"ChallengeBundleSchedule:season9_fortbyte_schedule": 1,
|
||||
"Token:athenaseasonmergedxpboosts": 1
|
||||
},
|
||||
{
|
||||
"Token:athenaseasonxpboost": 10,
|
||||
"Token:athenanextseasonxpboost": 30
|
||||
},
|
||||
{
|
||||
"AthenaDance:emoji_tomatohead": 1
|
||||
},
|
||||
{
|
||||
"Currency:mtxgiveaway": 100
|
||||
},
|
||||
{
|
||||
"AthenaItemWrap:wrap_060_rooster": 1
|
||||
},
|
||||
{
|
||||
"AthenaDance:spid_109_strawberrypilot": 1
|
||||
},
|
||||
{
|
||||
"AthenaPickaxe:pickaxe_id_211_bunkerman_1h": 1
|
||||
},
|
||||
{
|
||||
"HomebaseBannerIcon:brs9chair": 1
|
||||
},
|
||||
{
|
||||
"Token:athenaseasonfriendxpboost": 10
|
||||
},
|
||||
{
|
||||
"AthenaLoadingScreen:lsid_126_floorislava": 1
|
||||
},
|
||||
{
|
||||
"Currency:mtxgiveaway": 100
|
||||
},
|
||||
{
|
||||
"AthenaMusicPack:musicpack_015_goodvibes": 1
|
||||
},
|
||||
{
|
||||
"AthenaDance:emoji_rexhead": 1
|
||||
},
|
||||
{
|
||||
"AthenaDance:spid_118_chevronleft": 1
|
||||
},
|
||||
{
|
||||
"AthenaGlider:glider_id_144_strawberrypilot": 1
|
||||
},
|
||||
{
|
||||
"AthenaDance:emoji_drifthead": 1
|
||||
},
|
||||
{
|
||||
"Token:athenaseasonxpboost": 10
|
||||
},
|
||||
{
|
||||
"Currency:mtxgiveaway": 100
|
||||
},
|
||||
{
|
||||
"AthenaItemWrap:wrap_057_banana": 1
|
||||
},
|
||||
{
|
||||
"AthenaDance:spid_115_pixeljonesy": 1
|
||||
},
|
||||
{
|
||||
"HomebaseBannerIcon:brs9bone": 1
|
||||
},
|
||||
{
|
||||
"AthenaLoadingScreen:lsid_130_strawberrypilot": 1
|
||||
},
|
||||
{
|
||||
"AthenaCharacter:cid_409_athena_commando_m_bunkerman": 1,
|
||||
"ChallengeBundleSchedule:season9_bunkerman_schedule": 1
|
||||
},
|
||||
{
|
||||
"Token:athenaseasonfriendxpboost": 10
|
||||
},
|
||||
{
|
||||
"AthenaDance:emoji_silentmaven": 1
|
||||
},
|
||||
{
|
||||
"AthenaSkyDiveContrail:trails_id_054_kpopglow": 1
|
||||
},
|
||||
{
|
||||
"Currency:mtxgiveaway": 100
|
||||
},
|
||||
{
|
||||
"AthenaBackpack:petcarrier_010_robokitty": 1
|
||||
},
|
||||
{
|
||||
"HomebaseBannerIcon:brs9x": 1
|
||||
},
|
||||
{
|
||||
"AthenaLoadingScreen:lsid_121_vikings": 1
|
||||
},
|
||||
{
|
||||
"AthenaDance:eid_chickenmoves": 1
|
||||
},
|
||||
{
|
||||
"AthenaDance:emoji_loveranger": 1
|
||||
},
|
||||
{
|
||||
"Token:athenaseasonxpboost": 10
|
||||
},
|
||||
{
|
||||
"Currency:mtxgiveaway": 100
|
||||
},
|
||||
{
|
||||
"AthenaDance:toy_017_flyingdisc": 1
|
||||
},
|
||||
{
|
||||
"AthenaDance:spid_119_chevronright": 1
|
||||
},
|
||||
{
|
||||
"AthenaLoadingScreen:lsid_127_unicornpickaxe": 1
|
||||
},
|
||||
{
|
||||
"HomebaseBannerIcon:brs9bacon": 1
|
||||
},
|
||||
{
|
||||
"AthenaGlider:glider_id_146_masako": 1
|
||||
},
|
||||
{
|
||||
"Token:athenaseasonfriendxpboost": 10
|
||||
},
|
||||
{
|
||||
"AthenaDance:spid_108_fate": 1
|
||||
},
|
||||
{
|
||||
"Currency:mtxgiveaway": 100
|
||||
},
|
||||
{
|
||||
"AthenaItemWrap:wrap_062_neotag": 1
|
||||
},
|
||||
{
|
||||
"AthenaDance:emoji_screamingwukong": 1
|
||||
},
|
||||
{
|
||||
"AccountResource:athenaseasonalxp": 1000
|
||||
},
|
||||
{
|
||||
"CosmeticVariantToken:vtid_199_petcarrier_robokitty_styleb": 1
|
||||
},
|
||||
{
|
||||
"AthenaCharacter:cid_404_athena_commando_f_bountyhunter": 1,
|
||||
"ChallengeBundleSchedule:season9_bountyhunter_schedule": 1
|
||||
},
|
||||
{
|
||||
"Token:athenaseasonxpboost": 10
|
||||
},
|
||||
{
|
||||
"AthenaSkyDiveContrail:trails_id_055_bananas": 1
|
||||
},
|
||||
{
|
||||
"HomebaseBannerIcon:brs9roar": 1
|
||||
},
|
||||
{
|
||||
"Currency:mtxgiveaway": 100
|
||||
},
|
||||
{
|
||||
"HomebaseBannerIcon:brs9violin": 1
|
||||
},
|
||||
{
|
||||
"AthenaDance:emoji_durrburgerhead": 1
|
||||
},
|
||||
{
|
||||
"AthenaDance:spid_117_nosymbol": 1
|
||||
},
|
||||
{
|
||||
"AthenaPickaxe:pickaxe_id_205_strawberrypilot": 1
|
||||
},
|
||||
{
|
||||
"Token:athenaseasonfriendxpboost": 10
|
||||
},
|
||||
{
|
||||
"AthenaDance:spid_113_nananana": 1
|
||||
},
|
||||
{
|
||||
"Currency:mtxgiveaway": 100
|
||||
},
|
||||
{
|
||||
"AthenaItemWrap:wrap_061_purplesplatter": 1
|
||||
},
|
||||
{
|
||||
"CosmeticVariantToken:vtid_201_petcarrier_robokitty_styled": 1
|
||||
},
|
||||
{
|
||||
"AccountResource:athenaseasonalxp": 1000
|
||||
},
|
||||
{
|
||||
"HomebaseBannerIcon:brs9cone": 1
|
||||
},
|
||||
{
|
||||
"AthenaDance:eid_signspinner": 1
|
||||
},
|
||||
{
|
||||
"Token:athenaseasonxpboost": 10
|
||||
},
|
||||
{
|
||||
"AthenaLoadingScreen:lsid_125_lavalegends": 1
|
||||
},
|
||||
{
|
||||
"AthenaDance:spid_111_ark": 1
|
||||
},
|
||||
{
|
||||
"Currency:mtxgiveaway": 100
|
||||
},
|
||||
{
|
||||
"AthenaDance:toy_018_fancyflyingdisc": 1
|
||||
},
|
||||
{
|
||||
"AccountResource:athenaseasonalxp": 1000
|
||||
},
|
||||
{
|
||||
"HomebaseBannerIcon:brs9target": 1
|
||||
},
|
||||
{
|
||||
"AthenaCharacter:cid_406_athena_commando_m_stormtracker": 1,
|
||||
"ChallengeBundleSchedule:season9_stormtracker_schedule": 1
|
||||
},
|
||||
{
|
||||
"AthenaDance:emoji_skepticalfishstix": 1
|
||||
},
|
||||
{
|
||||
"Token:athenaseasonfriendxpboost": 10
|
||||
},
|
||||
{
|
||||
"CosmeticVariantToken:vtid_200_petcarrier_robokitty_stylec": 1
|
||||
},
|
||||
{
|
||||
"AthenaLoadingScreen:lsid_129_stormtracker": 1
|
||||
},
|
||||
{
|
||||
"Currency:mtxgiveaway": 100
|
||||
},
|
||||
{
|
||||
"AthenaSkyDiveContrail:trails_id_056_stormtracker": 1
|
||||
},
|
||||
{
|
||||
"HomebaseBannerIcon:brs9blast": 1
|
||||
},
|
||||
{
|
||||
"AthenaGlider:glider_id_143_battlesuit": 1
|
||||
},
|
||||
{
|
||||
"AthenaLoadingScreen:lsid_123_inferno": 1
|
||||
},
|
||||
{
|
||||
"Token:athenaseasonxpboost": 10
|
||||
},
|
||||
{
|
||||
"AthenaDance:emoji_whiteflag": 1
|
||||
},
|
||||
{
|
||||
"Currency:mtxgiveaway": 100
|
||||
},
|
||||
{
|
||||
"AthenaItemWrap:wrap_058_storm": 1
|
||||
},
|
||||
{
|
||||
"AthenaDance:spid_116_robot": 1
|
||||
},
|
||||
{
|
||||
"HomebaseBannerIcon:brs9spade": 1
|
||||
},
|
||||
{
|
||||
"AthenaCharacter:cid_405_athena_commando_f_masako": 1,
|
||||
"ChallengeBundleSchedule:season9_masako_schedule": 1
|
||||
},
|
||||
{
|
||||
"Token:athenaseasonfriendxpboost": 10
|
||||
},
|
||||
{
|
||||
"AthenaSkyDiveContrail:trails_id_057_battlesuit": 1
|
||||
},
|
||||
{
|
||||
"AthenaDance:spid_110_rooster": 1
|
||||
},
|
||||
{
|
||||
"Currency:mtxgiveaway": 100
|
||||
},
|
||||
{
|
||||
"AthenaMusicPack:musicpack_014_s9cine": 1
|
||||
},
|
||||
{
|
||||
"AthenaDance:emoji_supdood": 1
|
||||
},
|
||||
{
|
||||
"AthenaLoadingScreen:lsid_128_auroraglow": 1
|
||||
},
|
||||
{
|
||||
"AthenaDance:eid_gabbyhiphop_01": 1
|
||||
},
|
||||
{
|
||||
"Token:athenaseasonxpboost": 10
|
||||
},
|
||||
{
|
||||
"AthenaItemWrap:wrap_059_battlesuit": 1
|
||||
},
|
||||
{
|
||||
"Currency:mtxgiveaway": 100
|
||||
},
|
||||
{
|
||||
"CosmeticVariantToken:vtid_202_rooster_styleb": 1
|
||||
},
|
||||
{
|
||||
"AthenaCharacter:cid_407_athena_commando_m_battlesuit": 1,
|
||||
"ChallengeBundleSchedule:season9_battlesuit_schedule": 1
|
||||
}
|
||||
],
|
||||
"freeRewards": [
|
||||
{},
|
||||
{
|
||||
"AthenaDance:spid_112_rockpeople": 1
|
||||
},
|
||||
{},
|
||||
{
|
||||
"AthenaLoadingScreen:lsid_122_aztec": 1
|
||||
},
|
||||
{},
|
||||
{
|
||||
"AthenaSkyDiveContrail:trails_id_051_neontubes": 1
|
||||
},
|
||||
{},
|
||||
{
|
||||
"AthenaDance:emoji_cuddleteamhead": 1
|
||||
},
|
||||
{},
|
||||
{},
|
||||
{
|
||||
"Currency:mtxgiveaway": 100
|
||||
},
|
||||
{},
|
||||
{},
|
||||
{
|
||||
"AthenaDance:eid_yayexcited": 1
|
||||
},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{
|
||||
"HomebaseBannerIcon:brs9plane": 1
|
||||
},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{
|
||||
"AthenaGlider:glider_id_032_tacticalwoodland": 1
|
||||
},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{
|
||||
"AthenaDance:spid_121_sunbird": 1
|
||||
},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{
|
||||
"AthenaItemWrap:wrap_046_demon": 1
|
||||
},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{
|
||||
"Currency:mtxgiveaway": 100
|
||||
},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{
|
||||
"AthenaPickaxe:pickaxe_id_210_bunkerman": 1
|
||||
},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{
|
||||
"HomebaseBannerIcon:brs9paintbrush": 1
|
||||
},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{
|
||||
"AthenaDance:eid_sadtrombone": 1
|
||||
},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{
|
||||
"AthenaLoadingScreen:lsid_124_airroyale": 1
|
||||
},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{
|
||||
"AthenaMusicPack:musicpack_013_robotrack": 1
|
||||
},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{
|
||||
"AthenaDance:emoji_skulltrooper": 1
|
||||
},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{
|
||||
"AthenaDance:spid_114_bush": 1
|
||||
},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{}
|
||||
]
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
+38757
File diff suppressed because it is too large
Load Diff
+279
@@ -0,0 +1,279 @@
|
||||
const express = require("express");
|
||||
const app = express.Router();
|
||||
const jwt = require("jsonwebtoken");
|
||||
const bcrypt = require("bcrypt");
|
||||
|
||||
const error = require("../structs/error.js");
|
||||
const functions = require("../structs/functions.js");
|
||||
|
||||
const tokenCreation = require("../tokenManager/tokenCreation.js");
|
||||
const { verifyToken, verifyClient } = require("../tokenManager/tokenVerify.js");
|
||||
const User = require("../model/user.js");
|
||||
|
||||
app.post("/account/api/oauth/token", async (req, res) => {
|
||||
let clientId;
|
||||
|
||||
try {
|
||||
clientId = functions.DecodeBase64(req.headers["authorization"].split(" ")[1]).split(":");
|
||||
|
||||
if (!clientId[1]) throw new Error("invalid client id");
|
||||
|
||||
clientId = clientId[0];
|
||||
} catch {
|
||||
return error.createError(
|
||||
"errors.com.epicgames.common.oauth.invalid_client",
|
||||
"It appears that your Authorization header may be invalid or not present, please verify that you are sending the correct headers.",
|
||||
[], 1011, "invalid_client", 400, res
|
||||
);
|
||||
}
|
||||
|
||||
switch (req.body.grant_type) {
|
||||
case "client_credentials":
|
||||
let ip = req.ip;
|
||||
|
||||
let clientToken = global.clientTokens.findIndex(i => i.ip == ip);
|
||||
if (clientToken != -1) global.clientTokens.splice(clientToken, 1);
|
||||
|
||||
const token = tokenCreation.createClient(clientId, req.body.grant_type, ip, 4); // expires in 4 hours
|
||||
|
||||
functions.UpdateTokens();
|
||||
|
||||
const decodedClient = jwt.decode(token);
|
||||
|
||||
res.json({
|
||||
access_token: `eg1~${token}`,
|
||||
expires_in: Math.round(((DateAddHours(new Date(decodedClient.creation_date), decodedClient.hours_expire).getTime()) - (new Date().getTime())) / 1000),
|
||||
expires_at: DateAddHours(new Date(decodedClient.creation_date), decodedClient.hours_expire).toISOString(),
|
||||
token_type: "bearer",
|
||||
client_id: clientId,
|
||||
internal_client: true,
|
||||
client_service: "fortnite"
|
||||
});
|
||||
return;
|
||||
|
||||
case "password":
|
||||
if (!req.body.username || !req.body.password) return error.createError(
|
||||
"errors.com.epicgames.common.oauth.invalid_request",
|
||||
"Username/password is required.",
|
||||
[], 1013, "invalid_request", 400, res
|
||||
);
|
||||
const { username: email, password: password } = req.body;
|
||||
|
||||
req.user = await User.findOne({ email: email.toLowerCase() }).lean();
|
||||
|
||||
let err = () => error.createError(
|
||||
"errors.com.epicgames.account.invalid_account_credentials",
|
||||
"Your e-mail and/or password are incorrect. Please check them and try again.",
|
||||
[], 18031, "invalid_grant", 400, res
|
||||
);
|
||||
|
||||
if (!req.user) return err();
|
||||
else {
|
||||
if (!await bcrypt.compare(password, req.user.password)) return err();
|
||||
}
|
||||
break;
|
||||
|
||||
case "refresh_token":
|
||||
if (!req.body.refresh_token) return error.createError(
|
||||
"errors.com.epicgames.common.oauth.invalid_request",
|
||||
"Refresh token is required.",
|
||||
[], 1013, "invalid_request", 400, res
|
||||
);
|
||||
|
||||
const refresh_token = req.body.refresh_token;
|
||||
|
||||
let refreshToken = global.refreshTokens.findIndex(i => i.token == refresh_token);
|
||||
let object = global.refreshTokens[refreshToken];
|
||||
|
||||
try {
|
||||
if (refreshToken == -1) throw new Error("Refresh token invalid.");
|
||||
let decodedRefreshToken = jwt.decode(refresh_token.replace("eg1~", ""));
|
||||
|
||||
if (DateAddHours(new Date(decodedRefreshToken.creation_date), decodedRefreshToken.hours_expire).getTime() <= new Date().getTime()) {
|
||||
throw new Error("Expired refresh token.");
|
||||
}
|
||||
} catch {
|
||||
if (refreshToken != -1) {
|
||||
global.refreshTokens.splice(refreshToken, 1);
|
||||
|
||||
functions.UpdateTokens();
|
||||
}
|
||||
|
||||
error.createError(
|
||||
"errors.com.epicgames.account.auth_token.invalid_refresh_token",
|
||||
`Sorry the refresh token '${refresh_token}' is invalid`,
|
||||
[refresh_token], 18036, "invalid_grant", 400, res
|
||||
);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
req.user = await User.findOne({ accountId: object.accountId }).lean();
|
||||
break;
|
||||
|
||||
case "exchange_code":
|
||||
if (!req.body.exchange_code) return error.createError(
|
||||
"errors.com.epicgames.common.oauth.invalid_request",
|
||||
"Exchange code is required.",
|
||||
[], 1013, "invalid_request", 400, res
|
||||
);
|
||||
|
||||
const { exchange_code } = req.body;
|
||||
|
||||
let index = global.exchangeCodes.findIndex(i => i.exchange_code == exchange_code);
|
||||
let exchange = global.exchangeCodes[index];
|
||||
|
||||
if (index == -1) return error.createError(
|
||||
"errors.com.epicgames.account.oauth.exchange_code_not_found",
|
||||
"Sorry the exchange code you supplied was not found. It is possible that it was no longer valid",
|
||||
[], 18057, "invalid_grant", 400, res
|
||||
);
|
||||
|
||||
global.exchangeCodes.splice(index, 1);
|
||||
|
||||
req.user = await User.findOne({ accountId: exchange.accountId }).lean();
|
||||
break;
|
||||
|
||||
default:
|
||||
error.createError(
|
||||
"errors.com.epicgames.common.oauth.unsupported_grant_type",
|
||||
`Unsupported grant type: ${req.body.grant_type}`,
|
||||
[], 1016, "unsupported_grant_type", 400, res
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
if (req.user.banned) return error.createError(
|
||||
"errors.com.epicgames.account.account_not_active",
|
||||
"You have been permanently banned from Fortnite.",
|
||||
[], -1, undefined, 400, res
|
||||
);
|
||||
|
||||
let refreshIndex = global.refreshTokens.findIndex(i => i.accountId == req.user.accountId);
|
||||
if (refreshIndex != -1) global.refreshTokens.splice(refreshIndex, 1);
|
||||
|
||||
let accessIndex = global.accessTokens.findIndex(i => i.accountId == req.user.accountId);
|
||||
if (accessIndex != -1) {
|
||||
global.accessTokens.splice(accessIndex, 1);
|
||||
|
||||
let xmppClient = global.Clients.find(i => i.accountId == req.user.accountId);
|
||||
if (xmppClient) xmppClient.client.close();
|
||||
}
|
||||
|
||||
const deviceId = functions.MakeID().replace(/-/ig, "");
|
||||
const accessToken = tokenCreation.createAccess(req.user, clientId, req.body.grant_type, deviceId, 8); // expires in 8 hours
|
||||
const refreshToken = tokenCreation.createRefresh(req.user, clientId, req.body.grant_type, deviceId, 24); // expires in 24 hours
|
||||
|
||||
functions.UpdateTokens();
|
||||
|
||||
const decodedAccess = jwt.decode(accessToken);
|
||||
const decodedRefresh = jwt.decode(refreshToken);
|
||||
|
||||
res.json({
|
||||
access_token: `eg1~${accessToken}`,
|
||||
expires_in: Math.round(((DateAddHours(new Date(decodedAccess.creation_date), decodedAccess.hours_expire).getTime()) - (new Date().getTime())) / 1000),
|
||||
expires_at: DateAddHours(new Date(decodedAccess.creation_date), decodedAccess.hours_expire).toISOString(),
|
||||
token_type: "bearer",
|
||||
refresh_token: `eg1~${refreshToken}`,
|
||||
refresh_expires: Math.round(((DateAddHours(new Date(decodedRefresh.creation_date), decodedRefresh.hours_expire).getTime()) - (new Date().getTime())) / 1000),
|
||||
refresh_expires_at: DateAddHours(new Date(decodedRefresh.creation_date), decodedRefresh.hours_expire).toISOString(),
|
||||
account_id: req.user.accountId,
|
||||
client_id: clientId,
|
||||
internal_client: true,
|
||||
client_service: "fortnite",
|
||||
displayName: req.user.username,
|
||||
app: "fortnite",
|
||||
in_app_id: req.user.accountId,
|
||||
device_id: deviceId
|
||||
});
|
||||
});
|
||||
|
||||
app.get("/account/api/oauth/verify", verifyToken, (req, res) => {
|
||||
let token = req.headers["authorization"].replace("bearer ", "");
|
||||
const decodedToken = jwt.decode(token.replace("eg1~", ""));
|
||||
|
||||
res.json({
|
||||
token: token,
|
||||
session_id: decodedToken.jti,
|
||||
token_type: "bearer",
|
||||
client_id: decodedToken.clid,
|
||||
internal_client: true,
|
||||
client_service: "fortnite",
|
||||
account_id: req.user.accountId,
|
||||
expires_in: Math.round(((DateAddHours(new Date(decodedToken.creation_date), decodedToken.hours_expire).getTime()) - (new Date().getTime())) / 1000),
|
||||
expires_at: DateAddHours(new Date(decodedToken.creation_date), decodedToken.hours_expire).toISOString(),
|
||||
auth_method: decodedToken.am,
|
||||
display_name: req.user.username,
|
||||
app: "fortnite",
|
||||
in_app_id: req.user.accountId,
|
||||
device_id: decodedToken.dvid
|
||||
});
|
||||
});
|
||||
|
||||
app.get("/account/api/oauth/exchange", verifyToken, (req, res) => {
|
||||
return res.status(400).json({
|
||||
"error": "This endpoint is deprecated, please use the discord bot to generate an exchange code."
|
||||
});
|
||||
// remove the return code above if you still want to make use of this endpoint
|
||||
|
||||
let token = req.headers["authorization"].replace("bearer ", "");
|
||||
const exchange_code = functions.MakeID().replace(/-/ig, "");
|
||||
|
||||
const decodedToken = jwt.decode(token.replace("eg1~", ""));
|
||||
|
||||
global.exchangeCodes.push({
|
||||
accountId: req.user.accountId,
|
||||
exchange_code: exchange_code,
|
||||
creatingClientId: decodedToken.clid
|
||||
});
|
||||
|
||||
setTimeout(() => {
|
||||
let exchangeCode = global.exchangeCodes.findIndex(i => i.exchange_code == exchange_code);
|
||||
|
||||
if (exchangeCode != -1) global.exchangeCodes.splice(exchangeCode, 1);
|
||||
}, 300000) // remove exchange code in 5 minutes if unused
|
||||
|
||||
res.json({
|
||||
expiresInSeconds: 300,
|
||||
code: exchange_code,
|
||||
creatingClientId: decodedToken.clid
|
||||
});
|
||||
});
|
||||
|
||||
app.delete("/account/api/oauth/sessions/kill", (req, res) => {
|
||||
res.status(204).end();
|
||||
});
|
||||
|
||||
app.delete("/account/api/oauth/sessions/kill/:token", (req, res) => {
|
||||
let token = req.params.token;
|
||||
|
||||
let accessIndex = global.accessTokens.findIndex(i => i.token == token);
|
||||
|
||||
if (accessIndex != -1) {
|
||||
let object = global.accessTokens[accessIndex];
|
||||
|
||||
global.accessTokens.splice(accessIndex, 1);
|
||||
|
||||
let xmppClient = global.Clients.find(i => i.token == object.token);
|
||||
if (xmppClient) xmppClient.client.close();
|
||||
|
||||
let refreshIndex = global.refreshTokens.findIndex(i => i.accountId == object.accountId);
|
||||
if (refreshIndex != -1) global.refreshTokens.splice(refreshIndex, 1);
|
||||
}
|
||||
|
||||
let clientIndex = global.clientTokens.findIndex(i => i.token == token);
|
||||
if (clientIndex != -1) global.clientTokens.splice(clientIndex, 1);
|
||||
|
||||
if (accessIndex != -1 || clientIndex != -1) functions.UpdateTokens();
|
||||
|
||||
res.status(204).end();
|
||||
});
|
||||
|
||||
function DateAddHours(pdate, number) {
|
||||
let date = pdate;
|
||||
date.setHours(date.getHours() + number);
|
||||
|
||||
return date;
|
||||
}
|
||||
|
||||
module.exports = app;
|
||||
@@ -0,0 +1,132 @@
|
||||
const express = require("express");
|
||||
const app = express.Router();
|
||||
const fs = require("fs");
|
||||
const crypto = require("crypto");
|
||||
const path = require("path");
|
||||
|
||||
const { verifyToken, verifyClient } = require("../tokenManager/tokenVerify.js");
|
||||
const functions = require("../structs/functions.js");
|
||||
|
||||
let seasons = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20];
|
||||
|
||||
app.get("/fortnite/api/cloudstorage/system", (req, res) => {
|
||||
const dir = path.join(__dirname, "..", "CloudStorage");
|
||||
|
||||
let CloudFiles = [];
|
||||
|
||||
fs.readdirSync(dir).forEach(name => {
|
||||
if (name.toLowerCase().endsWith(".ini")) {
|
||||
const ParsedFile = fs.readFileSync(path.join(dir, name)).toString();
|
||||
const ParsedStats = fs.statSync(path.join(dir, name));
|
||||
|
||||
CloudFiles.push({
|
||||
"uniqueFilename": name,
|
||||
"filename": name,
|
||||
"hash": crypto.createHash('sha1').update(ParsedFile).digest('hex'),
|
||||
"hash256": crypto.createHash('sha256').update(ParsedFile).digest('hex'),
|
||||
"length": ParsedFile.length,
|
||||
"contentType": "application/octet-stream",
|
||||
"uploaded": ParsedStats.mtime,
|
||||
"storageType": "S3",
|
||||
"storageIds": {},
|
||||
"doNotCache": true
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
res.json(CloudFiles);
|
||||
});
|
||||
|
||||
app.get("/fortnite/api/cloudstorage/system/:file", (req, res) => {
|
||||
if (req.params.file.includes("..")) return res.status(404).end();
|
||||
if (req.params.file.includes("~")) return res.status(404).end();
|
||||
|
||||
const file = path.join(__dirname, "..", "CloudStorage", req.params.file);
|
||||
|
||||
if (fs.existsSync(file)) return res.status(200).send(fs.readFileSync(file));
|
||||
|
||||
res.status(200).end();
|
||||
});
|
||||
|
||||
app.get("/fortnite/api/cloudstorage/user/*/:file", verifyToken, (req, res) => {
|
||||
let clientSettingsPath = path.join(__dirname, "..", "ClientSettings", req.user.accountId);
|
||||
if (!fs.existsSync(clientSettingsPath)) fs.mkdirSync(clientSettingsPath);
|
||||
|
||||
if (req.params.file.toLowerCase() != "clientsettings.sav") return res.status(200).end();
|
||||
|
||||
const memory = functions.GetVersionInfo(req);
|
||||
if (!seasons.includes(memory.season)) return res.status(200).end();
|
||||
|
||||
let file = path.join(clientSettingsPath, `ClientSettings-${memory.season}.Sav`);
|
||||
|
||||
if (fs.existsSync(file)) return res.status(200).send(fs.readFileSync(file));
|
||||
|
||||
res.status(200).end();
|
||||
});
|
||||
|
||||
app.get("/fortnite/api/cloudstorage/user/:accountId", verifyToken, (req, res) => {
|
||||
let clientSettingsPath = path.join(__dirname, "..", "ClientSettings", req.user.accountId);
|
||||
if (!fs.existsSync(clientSettingsPath)) fs.mkdirSync(clientSettingsPath);
|
||||
|
||||
const memory = functions.GetVersionInfo(req);
|
||||
if (!seasons.includes(memory.season)) return res.json([]);
|
||||
|
||||
let file = path.join(clientSettingsPath, `ClientSettings-${memory.season}.Sav`);
|
||||
|
||||
if (fs.existsSync(file)) {
|
||||
const ParsedFile = fs.readFileSync(file, 'latin1');
|
||||
const ParsedStats = fs.statSync(file);
|
||||
|
||||
return res.json([{
|
||||
"uniqueFilename": "ClientSettings.Sav",
|
||||
"filename": "ClientSettings.Sav",
|
||||
"hash": crypto.createHash('sha1').update(ParsedFile).digest('hex'),
|
||||
"hash256": crypto.createHash('sha256').update(ParsedFile).digest('hex'),
|
||||
"length": Buffer.byteLength(ParsedFile),
|
||||
"contentType": "application/octet-stream",
|
||||
"uploaded": ParsedStats.mtime,
|
||||
"storageType": "S3",
|
||||
"storageIds": {},
|
||||
"accountId": req.user.accountId,
|
||||
"doNotCache": false
|
||||
}]);
|
||||
}
|
||||
|
||||
res.json([]);
|
||||
});
|
||||
|
||||
app.put("/fortnite/api/cloudstorage/user/*/:file", verifyToken, getRawBody, (req, res) => {
|
||||
if (Buffer.byteLength(req.rawBody) >= 400000) return res.status(403).json({ "error": "File size must be less than 400kb." });
|
||||
|
||||
let clientSettingsPath = path.join(__dirname, "..", "ClientSettings", req.user.accountId);
|
||||
if (!fs.existsSync(clientSettingsPath)) fs.mkdirSync(clientSettingsPath);
|
||||
|
||||
if (req.params.file.toLowerCase() != "clientsettings.sav") return res.status(204).end();
|
||||
|
||||
const memory = functions.GetVersionInfo(req);
|
||||
if (!seasons.includes(memory.season)) return res.status(204).end();
|
||||
|
||||
let file = path.join(clientSettingsPath, `ClientSettings-${memory.season}.Sav`);
|
||||
fs.writeFileSync(file, req.rawBody, 'latin1');
|
||||
|
||||
res.status(204).end();
|
||||
});
|
||||
|
||||
function getRawBody(req, res, next) {
|
||||
if (req.headers["content-length"]) {
|
||||
if (Number(req.headers["content-length"]) >= 400000) return res.status(403).json({ "error": "File size must be less than 400kb." });
|
||||
}
|
||||
|
||||
// Get raw body in encoding latin1 for ClientSettings
|
||||
try {
|
||||
req.rawBody = "";
|
||||
req.setEncoding("latin1");
|
||||
|
||||
req.on("data", (chunk) => req.rawBody += chunk);
|
||||
req.on("end", () => next());
|
||||
} catch {
|
||||
res.status(400).json({ "error": "Something went wrong while trying to access the request body." });
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = app;
|
||||
@@ -0,0 +1,11 @@
|
||||
const express = require("express");
|
||||
const app = express.Router();
|
||||
const functions = require("../structs/functions.js");
|
||||
|
||||
app.get("/content/api/pages/*", async (req, res) => {
|
||||
const contentpages = functions.getContentPages(req);
|
||||
|
||||
res.json(contentpages);
|
||||
});
|
||||
|
||||
module.exports = app;
|
||||
@@ -0,0 +1,229 @@
|
||||
const express = require("express");
|
||||
const app = express.Router();
|
||||
|
||||
const functions = require("../structs/functions.js");
|
||||
|
||||
const Friends = require("../model/friends.js");
|
||||
const friendManager = require("../structs/friend.js");
|
||||
|
||||
const { verifyToken, verifyClient } = require("../tokenManager/tokenVerify.js");
|
||||
|
||||
app.get("/friends/api/v1/*/settings", (req, res) => {
|
||||
res.json({});
|
||||
});
|
||||
|
||||
app.get("/friends/api/v1/*/blocklist", (req, res) => {
|
||||
res.json([]);
|
||||
});
|
||||
|
||||
app.get("/friends/api/public/list/fortnite/*/recentPlayers", (req, res) => {
|
||||
res.json([]);
|
||||
});
|
||||
|
||||
app.all("/friends/api/v1/*/friends/:friendId/alias", verifyToken, getRawBody, async (req, res) => {
|
||||
let friends = await Friends.findOne({ accountId: req.user.accountId });
|
||||
|
||||
let validationFail = () => error.createError(
|
||||
"errors.com.epicgames.validation.validation_failed",
|
||||
"Validation Failed. Invalid fields were [alias]",
|
||||
["[alias]"], 1040, undefined, 404, res
|
||||
);
|
||||
|
||||
const allowedCharacters = (" !\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~").split("");
|
||||
|
||||
for (let character of req.rawBody) {
|
||||
if (!allowedCharacters.includes(character)) return validationFail();
|
||||
}
|
||||
|
||||
if (!friends.list.accepted.find(i => i.accountId == req.params.friendId)) return error.createError(
|
||||
"errors.com.epicgames.friends.friendship_not_found",
|
||||
`Friendship between ${req.user.accountId} and ${req.params.friendId} does not exist`,
|
||||
[req.user.accountId,req.params.friendId], 14004, undefined, 404, res
|
||||
);
|
||||
|
||||
const friendIndex = friends.list.accepted.findIndex(i => i.accountId == req.params.friendId);
|
||||
|
||||
switch (req.method) {
|
||||
case "PUT":
|
||||
if ((req.rawBody < 3) || (req.rawBody > 16)) return validationFail();
|
||||
|
||||
friends.list.accepted[friendIndex].alias = req.rawBody;
|
||||
|
||||
await friends.updateOne({ $set: { list: friends.list } });
|
||||
break;
|
||||
|
||||
case "DELETE":
|
||||
friends.list.accepted[friendIndex].alias = "";
|
||||
|
||||
await friends.updateOne({ $set: { list: friends.list } });
|
||||
break;
|
||||
}
|
||||
|
||||
res.status(204).end();
|
||||
});
|
||||
|
||||
app.get("/friends/api/public/friends/:accountId", verifyToken, async (req, res) => {
|
||||
let response = [];
|
||||
|
||||
const friends = await Friends.findOne({ accountId: req.user.accountId }).lean();
|
||||
|
||||
friends.list.accepted.forEach(acceptedFriend => {
|
||||
response.push({
|
||||
"accountId": acceptedFriend.accountId,
|
||||
"status": "ACCEPTED",
|
||||
"direction": "OUTBOUND",
|
||||
"created": acceptedFriend.created,
|
||||
"favorite": false
|
||||
});
|
||||
});
|
||||
|
||||
friends.list.incoming.forEach(incomingFriend => {
|
||||
response.push({
|
||||
"accountId": incomingFriend.accountId,
|
||||
"status": "PENDING",
|
||||
"direction": "INBOUND",
|
||||
"created": incomingFriend.created,
|
||||
"favorite": false
|
||||
});
|
||||
});
|
||||
|
||||
friends.list.outgoing.forEach(outgoingFriend => {
|
||||
response.push({
|
||||
"accountId": outgoingFriend.accountId,
|
||||
"status": "PENDING",
|
||||
"direction": "OUTBOUND",
|
||||
"created": outgoingFriend.created,
|
||||
"favorite": false
|
||||
});
|
||||
});
|
||||
|
||||
res.json(response);
|
||||
});
|
||||
|
||||
app.post("/friends/api/*/friends*/:receiverId", verifyToken, async (req, res) => {
|
||||
let sender = await Friends.findOne({ accountId: req.user.accountId });
|
||||
let receiver = await Friends.findOne({ accountId: req.params.receiverId });
|
||||
if (!sender || !receiver) return res.status(403).end();
|
||||
|
||||
if (sender.list.incoming.find(i => i.accountId == receiver.accountId)) {
|
||||
if (!await friendManager.acceptFriendReq(sender.accountId, receiver.accountId)) return res.status(403).end();
|
||||
|
||||
functions.getPresenceFromUser(sender.accountId, receiver.accountId, false);
|
||||
functions.getPresenceFromUser(receiver.accountId, sender.accountId, false);
|
||||
} else if (!sender.list.outgoing.find(i => i.accountId == receiver.accountId)) {
|
||||
if (!await friendManager.sendFriendReq(sender.accountId, receiver.accountId)) return res.status(403).end();
|
||||
}
|
||||
|
||||
res.status(204).end();
|
||||
});
|
||||
|
||||
app.delete("/friends/api/*/friends*/:receiverId", verifyToken, async (req, res) => {
|
||||
let sender = await Friends.findOne({ accountId: req.user.accountId });
|
||||
let receiver = await Friends.findOne({ accountId: req.params.receiverId });
|
||||
if (!sender || !receiver) return res.status(403).end();
|
||||
|
||||
if (!await friendManager.deleteFriend(sender.accountId, receiver.accountId)) return res.status(403).end();
|
||||
|
||||
functions.getPresenceFromUser(sender.accountId, receiver.accountId, true);
|
||||
functions.getPresenceFromUser(receiver.accountId, sender.accountId, true);
|
||||
|
||||
res.status(204).end();
|
||||
});
|
||||
|
||||
app.post("/friends/api/*/blocklist*/:receiverId", verifyToken, async (req, res) => {
|
||||
let sender = await Friends.findOne({ accountId: req.user.accountId });
|
||||
let receiver = await Friends.findOne({ accountId: req.params.receiverId });
|
||||
if (!sender || !receiver) return res.status(403).end();
|
||||
|
||||
if (!await friendManager.blockFriend(sender.accountId, receiver.accountId)) return res.status(403).end();
|
||||
|
||||
functions.getPresenceFromUser(sender.accountId, receiver.accountId, true);
|
||||
functions.getPresenceFromUser(receiver.accountId, sender.accountId, true);
|
||||
|
||||
res.status(204).end();
|
||||
});
|
||||
|
||||
app.delete("/friends/api/*/blocklist*/:receiverId", verifyToken, async (req, res) => {
|
||||
let sender = await Friends.findOne({ accountId: req.user.accountId });
|
||||
let receiver = await Friends.findOne({ accountId: req.params.receiverId });
|
||||
if (!sender || !receiver) return res.status(403).end();
|
||||
|
||||
if (!await friendManager.deleteFriend(sender.accountId, receiver.accountId)) return res.status(403).end();
|
||||
|
||||
res.status(204).end();
|
||||
});
|
||||
|
||||
app.get("/friends/api/v1/:accountId/summary", verifyToken, async (req, res) => {
|
||||
let response = {
|
||||
"friends": [],
|
||||
"incoming": [],
|
||||
"outgoing": [],
|
||||
"suggested": [],
|
||||
"blocklist": [],
|
||||
"settings": {
|
||||
"acceptInvites": "public"
|
||||
}
|
||||
}
|
||||
|
||||
const friends = await Friends.findOne({ accountId: req.user.accountId }).lean();
|
||||
|
||||
friends.list.accepted.forEach(acceptedFriend => {
|
||||
response.friends.push({
|
||||
"accountId": acceptedFriend.accountId,
|
||||
"groups": [],
|
||||
"mutual": 0,
|
||||
"alias": acceptedFriend.alias ? acceptedFriend.alias : "",
|
||||
"note": "",
|
||||
"favorite": false,
|
||||
"created": acceptedFriend.created
|
||||
});
|
||||
});
|
||||
|
||||
friends.list.incoming.forEach(incomingFriend => {
|
||||
response.incoming.push({
|
||||
"accountId": incomingFriend.accountId,
|
||||
"mutual": 0,
|
||||
"favorite": false,
|
||||
"created": incomingFriend.created
|
||||
});
|
||||
});
|
||||
|
||||
friends.list.outgoing.forEach(outgoingFriend => {
|
||||
response.outgoing.push({
|
||||
"accountId": outgoingFriend.accountId,
|
||||
"favorite": false
|
||||
});
|
||||
});
|
||||
|
||||
friends.list.blocked.forEach(blockedFriend => {
|
||||
response.blocklist.push({
|
||||
"accountId": blockedFriend.accountId
|
||||
});
|
||||
});
|
||||
|
||||
res.json(response);
|
||||
});
|
||||
|
||||
app.get("/friends/api/public/blocklist/*", verifyToken, async (req, res) => {
|
||||
let friends = await Friends.findOne({ accountId: req.user.accountId }).lean();
|
||||
|
||||
res.json({
|
||||
"blockedUsers": friends.list.blocked.map(i => i.accountId)
|
||||
});
|
||||
});
|
||||
|
||||
function getRawBody(req, res, next) {
|
||||
if (req.headers["content-length"]) {
|
||||
if (Number(req.headers["content-length"]) > 16) return res.status(403).json({ "error": "File size must be 16 bytes or less." });
|
||||
}
|
||||
|
||||
try {
|
||||
req.rawBody = "";
|
||||
req.on("data", (chunk) => req.rawBody += chunk);
|
||||
req.on("end", () => next());
|
||||
} catch {
|
||||
res.status(400).json({ "error": "Something went wrong while trying to access the request body." });
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = app;
|
||||
@@ -0,0 +1,47 @@
|
||||
const express = require("express");
|
||||
const app = express.Router();
|
||||
|
||||
const { verifyToken, verifyClient } = require("../tokenManager/tokenVerify.js");
|
||||
|
||||
app.get("/lightswitch/api/service/Fortnite/status", async (req, res) => {
|
||||
res.json({
|
||||
"serviceInstanceId": "fortnite",
|
||||
"status": "UP",
|
||||
"message": "Fortnite is online",
|
||||
"maintenanceUri": null,
|
||||
"overrideCatalogIds": [
|
||||
"a7f138b2e51945ffbfdacc1af0541053"
|
||||
],
|
||||
"allowedActions": [],
|
||||
"banned": false,
|
||||
"launcherInfoDTO": {
|
||||
"appName": "Fortnite",
|
||||
"catalogItemId": "4fe75bbc5a674f4f9b356b5c90567da5",
|
||||
"namespace": "fn"
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
app.get("/lightswitch/api/service/bulk/status", async (req, res) => {
|
||||
res.json([{
|
||||
"serviceInstanceId": "fortnite",
|
||||
"status": "UP",
|
||||
"message": "fortnite is up.",
|
||||
"maintenanceUri": null,
|
||||
"overrideCatalogIds": [
|
||||
"a7f138b2e51945ffbfdacc1af0541053"
|
||||
],
|
||||
"allowedActions": [
|
||||
"PLAY",
|
||||
"DOWNLOAD"
|
||||
],
|
||||
"banned": false,
|
||||
"launcherInfoDTO": {
|
||||
"appName": "Fortnite",
|
||||
"catalogItemId": "4fe75bbc5a674f4f9b356b5c90567da5",
|
||||
"namespace": "fn"
|
||||
}
|
||||
}]);
|
||||
});
|
||||
|
||||
module.exports = app;
|
||||
+127
@@ -0,0 +1,127 @@
|
||||
const express = require("express");
|
||||
const fs = require("fs");
|
||||
const app = express.Router();
|
||||
|
||||
const { verifyToken, verifyClient } = require("../tokenManager/tokenVerify.js");
|
||||
|
||||
const config = JSON.parse(fs.readFileSync("./Config/config.json").toString());
|
||||
|
||||
app.post("/fortnite/api/game/v2/chat/*/*/*/pc", (req, res) => {
|
||||
let resp = config.chat.EnableGlobalChat ? { "GlobalChatRooms": [{ "roomName": "reloadbackendglobal" }] } : {};
|
||||
|
||||
res.json(resp);
|
||||
});
|
||||
|
||||
app.post("/fortnite/api/game/v2/tryPlayOnPlatform/account/*", (req, res) => {
|
||||
res.setHeader("Content-Type", "text/plain");
|
||||
res.send(true);
|
||||
});
|
||||
|
||||
app.get("/launcher/api/public/distributionpoints/", (req, res) => {
|
||||
res.json({
|
||||
"distributions": [
|
||||
"https://download.epicgames.com/",
|
||||
"https://download2.epicgames.com/",
|
||||
"https://download3.epicgames.com/",
|
||||
"https://download4.epicgames.com/",
|
||||
"https://epicgames-download1.akamaized.net/"
|
||||
]
|
||||
});
|
||||
});
|
||||
|
||||
app.get("/waitingroom/api/waitingroom", (req, res) => {
|
||||
res.status(204);
|
||||
res.end();
|
||||
});
|
||||
|
||||
app.get("/socialban/api/public/v1/*", (req, res) => {
|
||||
res.json({
|
||||
"bans": [],
|
||||
"warnings": []
|
||||
});
|
||||
});
|
||||
|
||||
app.get("/fortnite/api/game/v2/events/tournamentandhistory/*/EU/WindowsClient", (req, res) => {
|
||||
res.json({});
|
||||
});
|
||||
|
||||
app.get("/fortnite/api/statsv2/account/:accountId", (req, res) => {
|
||||
res.json({
|
||||
"startTime": 0,
|
||||
"endTime": 0,
|
||||
"stats": {},
|
||||
"accountId": req.params.accountId
|
||||
});
|
||||
});
|
||||
|
||||
app.get("/statsproxy/api/statsv2/account/:accountId", (req, res) => {
|
||||
res.json({
|
||||
"startTime": 0,
|
||||
"endTime": 0,
|
||||
"stats": {},
|
||||
"accountId": req.params.accountId
|
||||
});
|
||||
});
|
||||
|
||||
app.get("/fortnite/api/stats/accountId/:accountId/bulk/window/alltime", (req, res) => {
|
||||
res.json({
|
||||
"startTime": 0,
|
||||
"endTime": 0,
|
||||
"stats": {},
|
||||
"accountId": req.params.accountId
|
||||
});
|
||||
});
|
||||
|
||||
app.post("/fortnite/api/feedback/*", (req, res) => {
|
||||
res.status(200);
|
||||
res.end();
|
||||
});
|
||||
|
||||
app.post("/fortnite/api/statsv2/query", (req, res) => {
|
||||
res.json([]);
|
||||
});
|
||||
|
||||
app.post("/statsproxy/api/statsv2/query", (req, res) => {
|
||||
res.json([]);
|
||||
});
|
||||
|
||||
app.post("/fortnite/api/game/v2/events/v2/setSubgroup/*", (req, res) => {
|
||||
res.status(204);
|
||||
res.end();
|
||||
});
|
||||
|
||||
app.get("/fortnite/api/game/v2/enabled_features", (req, res) => {
|
||||
res.json([]);
|
||||
});
|
||||
|
||||
app.get("/api/v1/events/Fortnite/download/*", (req, res) => {
|
||||
res.json({});
|
||||
});
|
||||
|
||||
app.get("/fortnite/api/game/v2/twitch/*", (req, res) => {
|
||||
res.status(200);
|
||||
res.end();
|
||||
});
|
||||
|
||||
app.get("/fortnite/api/game/v2/world/info", (req, res) => {
|
||||
res.json({});
|
||||
});
|
||||
|
||||
app.post("/fortnite/api/game/v2/chat/*/recommendGeneralChatRooms/pc", (req, res) => {
|
||||
res.json({});
|
||||
});
|
||||
|
||||
app.get("/fortnite/api/receipts/v1/account/*/receipts", (req, res) => {
|
||||
res.json([]);
|
||||
});
|
||||
|
||||
app.get("/fortnite/api/game/v2/leaderboards/cohort/*", (req, res) => {
|
||||
res.json([]);
|
||||
});
|
||||
|
||||
app.post("/datarouter/api/v1/public/data", (req, res) => {
|
||||
res.status(204);
|
||||
res.end();
|
||||
});
|
||||
|
||||
module.exports = app;
|
||||
@@ -0,0 +1,108 @@
|
||||
const express = require("express");
|
||||
const app = express.Router();
|
||||
const fs = require("fs");
|
||||
const functions = require("../structs/functions.js");
|
||||
|
||||
const { verifyToken, verifyClient } = require("../tokenManager/tokenVerify.js");
|
||||
|
||||
let buildUniqueId = {};
|
||||
|
||||
app.get("/fortnite/api/matchmaking/session/findPlayer/*", (req, res) => {
|
||||
res.status(200).end();
|
||||
});
|
||||
|
||||
app.get("/fortnite/api/game/v2/matchmakingservice/ticket/player/*", verifyToken, (req, res) => {
|
||||
if (typeof req.query.bucketId != "string") return res.status(400).end();
|
||||
if (req.query.bucketId.split(":").length != 4) return res.status(400).end();
|
||||
|
||||
buildUniqueId[req.user.accountId] = req.query.bucketId.split(":")[0];
|
||||
|
||||
const config = JSON.parse(fs.readFileSync("./Config/config.json").toString());
|
||||
|
||||
res.json({
|
||||
"serviceUrl": `ws://${config.matchmakerIP}`,
|
||||
"ticketType": "mms-player",
|
||||
"payload": "69=",
|
||||
"signature": "420="
|
||||
});
|
||||
res.end();
|
||||
});
|
||||
|
||||
app.get("/fortnite/api/game/v2/matchmaking/account/:accountId/session/:sessionId", (req, res) => {
|
||||
res.json({
|
||||
"accountId": req.params.accountId,
|
||||
"sessionId": req.params.sessionId,
|
||||
"key": "none"
|
||||
});
|
||||
});
|
||||
|
||||
app.get("/fortnite/api/matchmaking/session/:sessionId", verifyToken, (req, res) => {
|
||||
const config = JSON.parse(fs.readFileSync("./Config/config.json").toString());
|
||||
|
||||
let gameServerInfo = {
|
||||
serverAddress: "127.0.0.1",
|
||||
serverPort: 7777
|
||||
}
|
||||
|
||||
try {
|
||||
let calculateIp = config.gameServerIP.split(":")[0];
|
||||
let calculatePort = Number(config.gameServerIP.split(":")[1]);
|
||||
|
||||
if (calculateIp) gameServerInfo.serverAddress = calculateIp;
|
||||
if (Number.isNaN(calculatePort) || !calculatePort) throw new Error("Invalid port.");
|
||||
|
||||
gameServerInfo.serverPort = calculatePort;
|
||||
} catch {}
|
||||
|
||||
res.json({
|
||||
"id": req.params.sessionId,
|
||||
"ownerId": functions.MakeID().replace(/-/ig, "").toUpperCase(),
|
||||
"ownerName": "[DS]fortnite-liveeugcec1c2e30ubrcore0a-z8hj-1968",
|
||||
"serverName": "[DS]fortnite-liveeugcec1c2e30ubrcore0a-z8hj-1968",
|
||||
"serverAddress": gameServerInfo.serverAddress,
|
||||
"serverPort": gameServerInfo.serverPort,
|
||||
"maxPublicPlayers": 220,
|
||||
"openPublicPlayers": 175,
|
||||
"maxPrivatePlayers": 0,
|
||||
"openPrivatePlayers": 0,
|
||||
"attributes": {
|
||||
"REGION_s": "EU",
|
||||
"GAMEMODE_s": "FORTATHENA",
|
||||
"ALLOWBROADCASTING_b": true,
|
||||
"SUBREGION_s": "GB",
|
||||
"DCID_s": "FORTNITE-LIVEEUGCEC1C2E30UBRCORE0A-14840880",
|
||||
"tenant_s": "Fortnite",
|
||||
"MATCHMAKINGPOOL_s": "Any",
|
||||
"STORMSHIELDDEFENSETYPE_i": 0,
|
||||
"HOTFIXVERSION_i": 0,
|
||||
"PLAYLISTNAME_s": "Playlist_DefaultSolo",
|
||||
"SESSIONKEY_s": functions.MakeID().replace(/-/ig, "").toUpperCase(),
|
||||
"TENANT_s": "Fortnite",
|
||||
"BEACONPORT_i": 15009
|
||||
},
|
||||
"publicPlayers": [],
|
||||
"privatePlayers": [],
|
||||
"totalPlayers": 45,
|
||||
"allowJoinInProgress": false,
|
||||
"shouldAdvertise": false,
|
||||
"isDedicated": false,
|
||||
"usesStats": false,
|
||||
"allowInvites": false,
|
||||
"usesPresence": false,
|
||||
"allowJoinViaPresence": true,
|
||||
"allowJoinViaPresenceFriendsOnly": false,
|
||||
"buildUniqueId": buildUniqueId[req.user.accountId] || "0",
|
||||
"lastUpdated": new Date().toISOString(),
|
||||
"started": false
|
||||
});
|
||||
});
|
||||
|
||||
app.post("/fortnite/api/matchmaking/session/*/join", (req, res) => {
|
||||
res.status(204).end();
|
||||
});
|
||||
|
||||
app.post("/fortnite/api/matchmaking/session/matchMakingRequest", (req, res) => {
|
||||
res.json([]);
|
||||
});
|
||||
|
||||
module.exports = app;
|
||||
+2555
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,60 @@
|
||||
const express = require("express");
|
||||
const app = express.Router();
|
||||
const Profile = require("../model/profiles.js");
|
||||
const Friends = require("../model/friends.js");
|
||||
const functions = require("../structs/functions.js");
|
||||
|
||||
const { verifyToken, verifyClient } = require("../tokenManager/tokenVerify.js");
|
||||
const keychain = require("../responses/keychain.json");
|
||||
|
||||
app.get("/fortnite/api/storefront/v2/catalog", (req, res) => {
|
||||
if (req.headers["user-agent"].includes("2870186")) return res.status(404).end();
|
||||
|
||||
res.json(functions.getItemShop());
|
||||
});
|
||||
|
||||
app.get("/fortnite/api/storefront/v2/gift/check_eligibility/recipient/:recipientId/offer/:offerId", verifyToken, async (req, res) => {
|
||||
const findOfferId = functions.getOfferID(req.params.offerId);
|
||||
if (!findOfferId) return error.createError(
|
||||
"errors.com.epicgames.fortnite.id_invalid",
|
||||
`Offer ID (id: "${req.params.offerId}") not found`,
|
||||
[req.params.offerId], 16027, undefined, 400, res
|
||||
);
|
||||
|
||||
let sender = await Friends.findOne({ accountId: req.user.accountId }).lean();
|
||||
|
||||
if (!sender.list.accepted.find(i => i.accountId == req.params.recipientId) && req.params.recipientId != req.user.accountId) return error.createError(
|
||||
"errors.com.epicgames.friends.no_relationship",
|
||||
`User ${req.user.accountId} is not friends with ${req.params.recipientId}`,
|
||||
[req.user.accountId,req.params.recipientId], 28004, undefined, 403, res
|
||||
);
|
||||
|
||||
const profiles = await Profile.findOne({ accountId: req.params.recipientId });
|
||||
|
||||
let athena = profiles.profiles["athena"];
|
||||
|
||||
for (let itemGrant of findOfferId.offerId.itemGrants) {
|
||||
for (let itemId in athena.items) {
|
||||
if (itemGrant.templateId.toLowerCase() == athena.items[itemId].templateId.toLowerCase()) return error.createError(
|
||||
"errors.com.epicgames.modules.gamesubcatalog.purchase_not_allowed",
|
||||
`Could not purchase catalog offer ${findOfferId.offerId.devName}, item ${itemGrant.templateId}`,
|
||||
[findOfferId.offerId.devName,itemGrant.templateId], 28004, undefined, 403, res
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
res.json({
|
||||
price: findOfferId.offerId.prices[0],
|
||||
items: findOfferId.offerId.itemGrants
|
||||
});
|
||||
});
|
||||
|
||||
app.get("/fortnite/api/storefront/v2/keychain", (req, res) => {
|
||||
res.json(keychain);
|
||||
});
|
||||
|
||||
app.get("/catalog/api/shared/bulk/offers", (req, res) => {
|
||||
res.json({});
|
||||
});
|
||||
|
||||
module.exports = app;
|
||||
@@ -0,0 +1,57 @@
|
||||
const express = require("express");
|
||||
const app = express.Router();
|
||||
|
||||
const { verifyToken, verifyClient } = require("../tokenManager/tokenVerify.js");
|
||||
const functions = require("../structs/functions.js");
|
||||
|
||||
app.get("/fortnite/api/calendar/v1/timeline", (req, res) => {
|
||||
const memory = functions.GetVersionInfo(req);
|
||||
|
||||
let activeEvents = [
|
||||
{
|
||||
"eventType": `EventFlag.Season${memory.season}`,
|
||||
"activeUntil": "9999-01-01T00:00:00.000Z",
|
||||
"activeSince": "2020-01-01T00:00:00.000Z"
|
||||
},
|
||||
{
|
||||
"eventType": `EventFlag.${memory.lobby}`,
|
||||
"activeUntil": "9999-01-01T00:00:00.000Z",
|
||||
"activeSince": "2020-01-01T00:00:00.000Z"
|
||||
}
|
||||
];
|
||||
|
||||
res.json({
|
||||
channels: {
|
||||
"client-matchmaking": {
|
||||
states: [],
|
||||
cacheExpire: "9999-01-01T00:00:00.000Z"
|
||||
},
|
||||
"client-events": {
|
||||
states: [{
|
||||
validFrom: "0001-01-01T00:00:00.000Z",
|
||||
activeEvents: activeEvents,
|
||||
state: {
|
||||
activeStorefronts: [],
|
||||
eventNamedWeights: {},
|
||||
seasonNumber: memory.season,
|
||||
seasonTemplateId: `AthenaSeason:athenaseason${memory.season}`,
|
||||
matchXpBonusPoints: 0,
|
||||
seasonBegin: "2020-01-01T00:00:00Z",
|
||||
seasonEnd: "9999-01-01T00:00:00Z",
|
||||
seasonDisplayedEnd: "9999-01-01T00:00:00Z",
|
||||
weeklyStoreEnd: "9999-01-01T00:00:00Z",
|
||||
stwEventStoreEnd: "9999-01-01T00:00:00.000Z",
|
||||
stwWeeklyStoreEnd: "9999-01-01T00:00:00.000Z",
|
||||
dailyStoreEnd: "9999-01-01T00:00:00Z"
|
||||
}
|
||||
}],
|
||||
cacheExpire: "9999-01-01T00:00:00.000Z"
|
||||
}
|
||||
},
|
||||
eventsTimeOffsetHrs: 0,
|
||||
cacheIntervalMins: 10,
|
||||
currentTime: new Date().toISOString()
|
||||
});
|
||||
});
|
||||
|
||||
module.exports = app;
|
||||
+137
@@ -0,0 +1,137 @@
|
||||
const express = require("express");
|
||||
const app = express.Router();
|
||||
|
||||
const error = require("../structs/error.js");
|
||||
|
||||
const { verifyToken, verifyClient } = require("../tokenManager/tokenVerify.js");
|
||||
const User = require("../model/user.js");
|
||||
|
||||
app.get("/account/api/public/account", async (req, res) => {
|
||||
let response = [];
|
||||
|
||||
if (typeof req.query.accountId == "string") {
|
||||
let user = await User.findOne({ accountId: req.query.accountId, banned: false }).lean();
|
||||
|
||||
if (user) {
|
||||
response.push({
|
||||
id: user.accountId,
|
||||
displayName: user.username,
|
||||
externalAuths: {}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
if (Array.isArray(req.query.accountId)) {
|
||||
let users = await User.find({ accountId: { $in: req.query.accountId }, banned: false }).lean();
|
||||
|
||||
if (users) {
|
||||
for (let user of users) {
|
||||
if (response.length >= 100) break;
|
||||
|
||||
response.push({
|
||||
id: user.accountId,
|
||||
displayName: user.username,
|
||||
externalAuths: {}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
res.json(response);
|
||||
});
|
||||
|
||||
app.get("/account/api/public/account/displayName/:displayName", async (req, res) => {
|
||||
let user = await User.findOne({ username_lower: req.params.displayName.toLowerCase(), banned: false }).lean();
|
||||
if (!user) return error.createError(
|
||||
"errors.com.epicgames.account.account_not_found",
|
||||
`Sorry, we couldn't find an account for ${req.params.displayName}`,
|
||||
[req.params.displayName], 18007, undefined, 404, res
|
||||
);
|
||||
|
||||
res.json({
|
||||
id: user.accountId,
|
||||
displayName: user.username,
|
||||
externalAuths: {}
|
||||
});
|
||||
});
|
||||
|
||||
app.get("/persona/api/public/account/lookup", async (req, res) => {
|
||||
if (typeof req.query.q != "string" || !req.query.q) return error.createError(
|
||||
"errors.com.epicgames.bad_request",
|
||||
"Required String parameter 'q' is invalid or not present",
|
||||
undefined, 1001, undefined, 400, res
|
||||
);
|
||||
|
||||
let user = await User.findOne({ username_lower: req.query.q.toLowerCase(), banned: false }).lean();
|
||||
if (!user) return error.createError(
|
||||
"errors.com.epicgames.account.account_not_found",
|
||||
`Sorry, we couldn't find an account for ${req.query.q}`,
|
||||
[req.query.q], 18007, undefined, 404, res
|
||||
);
|
||||
|
||||
res.json({
|
||||
id: user.accountId,
|
||||
displayName: user.username,
|
||||
externalAuths: {}
|
||||
});
|
||||
});
|
||||
|
||||
app.get("/api/v1/search/:accountId", async (req, res) => {
|
||||
let response = [];
|
||||
|
||||
if (typeof req.query.prefix != "string" || !req.query.prefix) return error.createError(
|
||||
"errors.com.epicgames.bad_request",
|
||||
"Required String parameter 'prefix' is invalid or not present",
|
||||
undefined, 1001, undefined, 400, res
|
||||
);
|
||||
|
||||
let users = await User.find({ username_lower: new RegExp(`^${req.query.prefix.toLowerCase()}`), banned: false }).lean();
|
||||
|
||||
for (let user of users) {
|
||||
if (response.length >= 100) break;
|
||||
|
||||
response.push({
|
||||
accountId: user.accountId,
|
||||
matches: [
|
||||
{
|
||||
"value": user.username,
|
||||
"platform": "epic"
|
||||
}
|
||||
],
|
||||
matchType: req.query.prefix.toLowerCase() == user.username_lower ? "exact" : "prefix",
|
||||
epicMutuals: 0,
|
||||
sortPosition: response.length
|
||||
});
|
||||
}
|
||||
|
||||
res.json(response);
|
||||
});
|
||||
|
||||
app.get("/account/api/public/account/:accountId", verifyToken, (req, res) => {
|
||||
res.json({
|
||||
id: req.user.accountId,
|
||||
displayName: req.user.username,
|
||||
name: "Lawin",
|
||||
email: `[hidden]@${req.user.email.split("@")[1]}`,
|
||||
failedLoginAttempts: 0,
|
||||
lastLogin: new Date().toISOString(),
|
||||
numberOfDisplayNameChanges: 0,
|
||||
ageGroup: "UNKNOWN",
|
||||
headless: false,
|
||||
country: "US",
|
||||
lastName: "Server",
|
||||
preferredLanguage: "en",
|
||||
canUpdateDisplayName: false,
|
||||
tfaEnabled: false,
|
||||
emailVerified: true,
|
||||
minorVerified: false,
|
||||
minorExpected: false,
|
||||
minorStatus: "UNKNOWN"
|
||||
});
|
||||
});
|
||||
|
||||
app.get("/account/api/public/account/*/externalAuths", (req, res) => {
|
||||
res.json([]);
|
||||
});
|
||||
|
||||
module.exports = app;
|
||||
@@ -0,0 +1,49 @@
|
||||
const express = require("express");
|
||||
const app = express.Router();
|
||||
|
||||
const { verifyToken, verifyClient } = require("../tokenManager/tokenVerify.js");
|
||||
|
||||
app.get("/fortnite/api/version", (req, res) => {
|
||||
res.json({
|
||||
"app": "fortnite",
|
||||
"serverDate": new Date().toISOString(),
|
||||
"overridePropertiesVersion": "unknown",
|
||||
"cln": "17951730",
|
||||
"build": "444",
|
||||
"moduleName": "Fortnite-Core",
|
||||
"buildDate": "2021-10-27T21:00:51.697Z",
|
||||
"version": "18.30",
|
||||
"branch": "Release-18.30",
|
||||
"modules": {
|
||||
"Epic-LightSwitch-AccessControlCore": {
|
||||
"cln": "17237679",
|
||||
"build": "b2130",
|
||||
"buildDate": "2021-08-19T18:56:08.144Z",
|
||||
"version": "1.0.0",
|
||||
"branch": "trunk"
|
||||
},
|
||||
"epic-xmpp-api-v1-base": {
|
||||
"cln": "5131a23c1470acbd9c94fae695ef7d899c1a41d6",
|
||||
"build": "b3595",
|
||||
"buildDate": "2019-07-30T09:11:06.587Z",
|
||||
"version": "0.0.1",
|
||||
"branch": "master"
|
||||
},
|
||||
"epic-common-core": {
|
||||
"cln": "17909521",
|
||||
"build": "3217",
|
||||
"buildDate": "2021-10-25T18:41:12.486Z",
|
||||
"version": "3.0",
|
||||
"branch": "TRUNK"
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
app.get("/fortnite/api*/versioncheck*", (req, res) => {
|
||||
res.json({
|
||||
"type": "NO_UPDATE"
|
||||
});
|
||||
});
|
||||
|
||||
module.exports = app;
|
||||
@@ -0,0 +1,6 @@
|
||||
@echo off
|
||||
title Reload Backend
|
||||
|
||||
:start
|
||||
node index.js
|
||||
goto start
|
||||
@@ -0,0 +1,21 @@
|
||||
function createError(errorCode, errorMessage, messageVars, numericErrorCode, error, statusCode, res) {
|
||||
res.set({
|
||||
'X-Epic-Error-Name': errorCode,
|
||||
'X-Epic-Error-Code': numericErrorCode
|
||||
});
|
||||
|
||||
res.status(statusCode).json({
|
||||
errorCode: errorCode,
|
||||
errorMessage: errorMessage,
|
||||
messageVars: messageVars,
|
||||
numericErrorCode: numericErrorCode,
|
||||
originatingService: "any",
|
||||
intent: "prod",
|
||||
error_description: errorMessage,
|
||||
error: error
|
||||
});
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
createError
|
||||
}
|
||||
@@ -0,0 +1,202 @@
|
||||
const Friends = require("../model/friends.js");
|
||||
const functions = require("../structs/functions.js");
|
||||
|
||||
async function validateFriendAdd(accountId, friendId) {
|
||||
let sender = await Friends.findOne({ accountId: accountId }).lean();
|
||||
let receiver = await Friends.findOne({ accountId: friendId }).lean();
|
||||
if (!sender || !receiver) return false;
|
||||
|
||||
if (sender.list.accepted.find(i => i.accountId == receiver.accountId) || receiver.list.accepted.find(i => i.accountId == sender.accountId)) return false;
|
||||
if (sender.list.blocked.find(i => i.accountId == receiver.accountId) || receiver.list.blocked.find(i => i.accountId == sender.accountId)) return false;
|
||||
if (sender.accountId == receiver.accountId) return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
async function validateFriendDelete(accountId, friendId) {
|
||||
let sender = await Friends.findOne({ accountId: accountId }).lean();
|
||||
let receiver = await Friends.findOne({ accountId: friendId }).lean();
|
||||
if (!sender || !receiver) return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
async function validateFriendBlock(accountId, friendId) {
|
||||
let sender = await Friends.findOne({ accountId: accountId }).lean();
|
||||
let receiver = await Friends.findOne({ accountId: friendId }).lean();
|
||||
if (!sender || !receiver) return false;
|
||||
|
||||
if (sender.list.blocked.find(i => i.accountId == receiver.accountId)) return false;
|
||||
if (sender.accountId == receiver.accountId) return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
async function sendFriendReq(fromId, toId) {
|
||||
if (!await validateFriendAdd(fromId, toId)) return false;
|
||||
|
||||
let from = await Friends.findOne({ accountId: fromId });
|
||||
let fromFriends = from.list;
|
||||
|
||||
let to = await Friends.findOne({ accountId: toId });
|
||||
let toFriends = to.list;
|
||||
|
||||
fromFriends.outgoing.push({ accountId: to.accountId, created: new Date().toISOString() });
|
||||
|
||||
functions.sendXmppMessageToId({
|
||||
"payload": {
|
||||
"accountId": to.accountId,
|
||||
"status": "PENDING",
|
||||
"direction": "OUTBOUND",
|
||||
"created": new Date().toISOString(),
|
||||
"favorite": false
|
||||
},
|
||||
"type": "com.epicgames.friends.core.apiobjects.Friend",
|
||||
"timestamp": new Date().toISOString()
|
||||
}, from.accountId);
|
||||
|
||||
toFriends.incoming.push({ accountId: from.accountId, created: new Date().toISOString() });
|
||||
|
||||
functions.sendXmppMessageToId({
|
||||
"payload": {
|
||||
"accountId": from.accountId,
|
||||
"status": "PENDING",
|
||||
"direction": "INBOUND",
|
||||
"created": new Date().toISOString(),
|
||||
"favorite": false
|
||||
},
|
||||
"type": "com.epicgames.friends.core.apiobjects.Friend",
|
||||
"timestamp": new Date().toISOString()
|
||||
}, to.accountId);
|
||||
|
||||
await from.updateOne({ $set: { list: fromFriends } });
|
||||
await to.updateOne({ $set: { list: toFriends } });
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
async function acceptFriendReq(fromId, toId) {
|
||||
if (!await validateFriendAdd(fromId, toId)) return false;
|
||||
|
||||
let from = await Friends.findOne({ accountId: fromId });
|
||||
let fromFriends = from.list;
|
||||
|
||||
let to = await Friends.findOne({ accountId: toId });
|
||||
let toFriends = to.list;
|
||||
|
||||
let incomingIndex = fromFriends.incoming.findIndex(i => i.accountId == to.accountId);
|
||||
|
||||
if (incomingIndex != -1) {
|
||||
fromFriends.incoming.splice(incomingIndex, 1);
|
||||
fromFriends.accepted.push({ accountId: to.accountId, created: new Date().toISOString() });
|
||||
|
||||
functions.sendXmppMessageToId({
|
||||
"payload": {
|
||||
"accountId": to.accountId,
|
||||
"status": "ACCEPTED",
|
||||
"direction": "OUTBOUND",
|
||||
"created": new Date().toISOString(),
|
||||
"favorite": false
|
||||
},
|
||||
"type": "com.epicgames.friends.core.apiobjects.Friend",
|
||||
"timestamp": new Date().toISOString()
|
||||
}, from.accountId);
|
||||
|
||||
toFriends.outgoing.splice(toFriends.outgoing.findIndex(i => i.accountId == from.accountId), 1);
|
||||
toFriends.accepted.push({ accountId: from.accountId, created: new Date().toISOString() });
|
||||
|
||||
functions.sendXmppMessageToId({
|
||||
"payload": {
|
||||
"accountId": from.accountId,
|
||||
"status": "ACCEPTED",
|
||||
"direction": "OUTBOUND",
|
||||
"created": new Date().toISOString(),
|
||||
"favorite": false
|
||||
},
|
||||
"type": "com.epicgames.friends.core.apiobjects.Friend",
|
||||
"timestamp": new Date().toISOString()
|
||||
}, to.accountId);
|
||||
|
||||
await from.updateOne({ $set: { list: fromFriends } });
|
||||
await to.updateOne({ $set: { list: toFriends } });
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
async function deleteFriend(fromId, toId) {
|
||||
if (!await validateFriendDelete(fromId, toId)) return false;
|
||||
|
||||
let from = await Friends.findOne({ accountId: fromId });
|
||||
let fromFriends = from.list;
|
||||
|
||||
let to = await Friends.findOne({ accountId: toId });
|
||||
let toFriends = to.list;
|
||||
|
||||
let removed = false;
|
||||
|
||||
for (let listType in fromFriends) {
|
||||
let findFriend = fromFriends[listType].findIndex(i => i.accountId == to.accountId);
|
||||
let findToFriend = toFriends[listType].findIndex(i => i.accountId == from.accountId);
|
||||
|
||||
if (findFriend != -1) {
|
||||
fromFriends[listType].splice(findFriend, 1);
|
||||
removed = true;
|
||||
}
|
||||
|
||||
if (listType == "blocked") continue;
|
||||
|
||||
if (findToFriend != -1) toFriends[listType].splice(findToFriend, 1);
|
||||
}
|
||||
|
||||
if (removed == true) {
|
||||
functions.sendXmppMessageToId({
|
||||
"payload": {
|
||||
"accountId": to.accountId,
|
||||
"reason": "DELETED"
|
||||
},
|
||||
"type": "com.epicgames.friends.core.apiobjects.FriendRemoval",
|
||||
"timestamp": new Date().toISOString()
|
||||
}, from.accountId);
|
||||
|
||||
functions.sendXmppMessageToId({
|
||||
"payload": {
|
||||
"accountId": from.accountId,
|
||||
"reason": "DELETED"
|
||||
},
|
||||
"type": "com.epicgames.friends.core.apiobjects.FriendRemoval",
|
||||
"timestamp": new Date().toISOString()
|
||||
}, to.accountId);
|
||||
|
||||
await from.updateOne({ $set: { list: fromFriends } });
|
||||
await to.updateOne({ $set: { list: toFriends } });
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
async function blockFriend(fromId, toId) {
|
||||
if (!await validateFriendDelete(fromId, toId)) return false;
|
||||
if (!await validateFriendBlock(fromId, toId)) return false;
|
||||
await deleteFriend(fromId, toId);
|
||||
|
||||
let from = await Friends.findOne({ accountId: fromId });
|
||||
let fromFriends = from.list;
|
||||
|
||||
let to = await Friends.findOne({ accountId: toId });
|
||||
|
||||
fromFriends.blocked.push({ accountId: to.accountId, created: new Date().toISOString() });
|
||||
|
||||
await from.updateOne({ $set: { list: fromFriends } });
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
validateFriendAdd,
|
||||
validateFriendDelete,
|
||||
sendFriendReq,
|
||||
acceptFriendReq,
|
||||
blockFriend,
|
||||
deleteFriend
|
||||
}
|
||||
@@ -0,0 +1,330 @@
|
||||
const XMLBuilder = require("xmlbuilder");
|
||||
const uuid = require("uuid");
|
||||
const bcrypt = require("bcrypt");
|
||||
const fs = require("fs");
|
||||
const crypto = require("crypto");
|
||||
const path = require("path");
|
||||
|
||||
const User = require("../model/user.js");
|
||||
const Profile = require("../model/profiles.js");
|
||||
const profileManager = require("../structs/profile.js");
|
||||
const Friends = require("../model/friends.js");
|
||||
|
||||
async function sleep(ms) {
|
||||
await new Promise((resolve, reject) => {
|
||||
setTimeout(resolve, ms);
|
||||
})
|
||||
}
|
||||
|
||||
function GetVersionInfo(req) {
|
||||
let memory = {
|
||||
season: 0,
|
||||
build: 0.0,
|
||||
CL: "0",
|
||||
lobby: ""
|
||||
}
|
||||
|
||||
if (req.headers["user-agent"]) {
|
||||
let CL = "";
|
||||
|
||||
try {
|
||||
let BuildID = req.headers["user-agent"].split("-")[3].split(",")[0];
|
||||
|
||||
if (!Number.isNaN(Number(BuildID))) CL = BuildID;
|
||||
else {
|
||||
BuildID = req.headers["user-agent"].split("-")[3].split(" ")[0];
|
||||
|
||||
if (!Number.isNaN(Number(BuildID))) CL = BuildID;
|
||||
}
|
||||
} catch {
|
||||
try {
|
||||
let BuildID = req.headers["user-agent"].split("-")[1].split("+")[0];
|
||||
|
||||
if (!Number.isNaN(Number(BuildID))) CL = BuildID;
|
||||
} catch {}
|
||||
}
|
||||
|
||||
try {
|
||||
let Build = req.headers["user-agent"].split("Release-")[1].split("-")[0];
|
||||
|
||||
if (Build.split(".").length == 3) {
|
||||
let Value = Build.split(".");
|
||||
Build = Value[0] + "." + Value[1] + Value[2];
|
||||
}
|
||||
|
||||
memory.season = Number(Build.split(".")[0]);
|
||||
memory.build = Number(Build);
|
||||
memory.CL = CL;
|
||||
memory.lobby = `LobbySeason${memory.season}`;
|
||||
|
||||
if (Number.isNaN(memory.season)) throw new Error();
|
||||
} catch {
|
||||
if (Number(memory.CL) < 3724489) {
|
||||
memory.season = 0;
|
||||
memory.build = 0.0;
|
||||
memory.CL = CL;
|
||||
memory.lobby = "LobbySeason0";
|
||||
} else if (Number(memory.CL) <= 3790078) {
|
||||
memory.season = 1;
|
||||
memory.build = 1.0;
|
||||
memory.CL = CL;
|
||||
memory.lobby = "LobbySeason1";
|
||||
} else {
|
||||
memory.season = 2;
|
||||
memory.build = 2.0;
|
||||
memory.CL = CL;
|
||||
memory.lobby = "LobbyWinterDecor";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return memory;
|
||||
}
|
||||
|
||||
function getContentPages(req) {
|
||||
const memory = GetVersionInfo(req);
|
||||
|
||||
const contentpages = JSON.parse(fs.readFileSync(path.join(__dirname, "..", "responses", "contentpages.json")).toString());
|
||||
|
||||
let Language = "en";
|
||||
|
||||
try {
|
||||
if (req.headers["accept-language"]) {
|
||||
if (req.headers["accept-language"].includes("-") && req.headers["accept-language"] != "es-419") {
|
||||
Language = req.headers["accept-language"].split("-")[0];
|
||||
} else {
|
||||
Language = req.headers["accept-language"];
|
||||
}
|
||||
}
|
||||
} catch {}
|
||||
|
||||
const modes = ["saveTheWorldUnowned", "battleRoyale", "creative", "saveTheWorld"];
|
||||
const news = ["savetheworldnews", "battleroyalenews"];
|
||||
|
||||
try {
|
||||
modes.forEach(mode => {
|
||||
contentpages.subgameselectdata[mode].message.title = contentpages.subgameselectdata[mode].message.title[Language]
|
||||
contentpages.subgameselectdata[mode].message.body = contentpages.subgameselectdata[mode].message.body[Language]
|
||||
})
|
||||
} catch {}
|
||||
|
||||
try {
|
||||
if (memory.build < 5.30) {
|
||||
news.forEach(mode => {
|
||||
contentpages[mode].news.messages[0].image = "https://cdn.discordapp.com/attachments/927739901540188200/930879507496308736/discord.png";
|
||||
contentpages[mode].news.messages[1].image = "https://cdn.discordapp.com/attachments/927739901540188200/930879519882088508/lawin.png";
|
||||
});
|
||||
}
|
||||
} catch {}
|
||||
|
||||
try {
|
||||
contentpages.dynamicbackgrounds.backgrounds.backgrounds[0].stage = `season${memory.season}`;
|
||||
contentpages.dynamicbackgrounds.backgrounds.backgrounds[1].stage = `season${memory.season}`;
|
||||
|
||||
if (memory.season == 10) {
|
||||
contentpages.dynamicbackgrounds.backgrounds.backgrounds[0].stage = "seasonx";
|
||||
contentpages.dynamicbackgrounds.backgrounds.backgrounds[1].stage = "seasonx";
|
||||
}
|
||||
|
||||
if (memory.build == 11.31 || memory.build == 11.40) {
|
||||
contentpages.dynamicbackgrounds.backgrounds.backgrounds[0].stage = "Winter19";
|
||||
contentpages.dynamicbackgrounds.backgrounds.backgrounds[1].stage = "Winter19";
|
||||
}
|
||||
|
||||
if (memory.build == 19.01) {
|
||||
contentpages.dynamicbackgrounds.backgrounds.backgrounds[0].stage = "winter2021";
|
||||
contentpages.dynamicbackgrounds.backgrounds.backgrounds[0].backgroundimage = "https://cdn.discordapp.com/attachments/927739901540188200/930880158167085116/t-bp19-lobby-xmas-2048x1024-f85d2684b4af.png";
|
||||
contentpages.subgameinfo.battleroyale.image = "https://cdn.discordapp.com/attachments/927739901540188200/930880421514846268/19br-wf-subgame-select-512x1024-16d8bb0f218f.jpg";
|
||||
contentpages.specialoffervideo.bSpecialOfferEnabled = "true";
|
||||
}
|
||||
|
||||
if (memory.season == 20) {
|
||||
if (memory.build == 20.40) {
|
||||
contentpages.dynamicbackgrounds.backgrounds.backgrounds[0].backgroundimage = "https://cdn2.unrealengine.com/t-bp20-40-armadillo-glowup-lobby-2048x2048-2048x2048-3b83b887cc7f.jpg"
|
||||
} else {
|
||||
contentpages.dynamicbackgrounds.backgrounds.backgrounds[0].backgroundimage = "https://cdn2.unrealengine.com/t-bp20-lobby-2048x1024-d89eb522746c.png";
|
||||
}
|
||||
}
|
||||
|
||||
if (memory.season == 21) {
|
||||
contentpages.dynamicbackgrounds.backgrounds.backgrounds[0].backgroundimage = "https://cdn2.unrealengine.com/s21-lobby-background-2048x1024-2e7112b25dc3.jpg"
|
||||
}
|
||||
} catch {}
|
||||
|
||||
return contentpages;
|
||||
}
|
||||
|
||||
function getItemShop() {
|
||||
const catalog = JSON.parse(fs.readFileSync(path.join(__dirname, "..", "responses", "catalog.json")).toString());
|
||||
const CatalogConfig = JSON.parse(fs.readFileSync(path.join(__dirname, "..", "Config", "catalog_config.json").toString()));
|
||||
|
||||
try {
|
||||
for (let value in CatalogConfig) {
|
||||
if (!Array.isArray(CatalogConfig[value].itemGrants)) continue;
|
||||
if (CatalogConfig[value].itemGrants.length == 0) continue;
|
||||
|
||||
const CatalogEntry = {"devName":"","offerId":"","fulfillmentIds":[],"dailyLimit":-1,"weeklyLimit":-1,"monthlyLimit":-1,"categories":[],"prices":[{"currencyType":"MtxCurrency","currencySubType":"","regularPrice":0,"finalPrice":0,"saleExpiration":"9999-12-02T01:12:00Z","basePrice":0}],"matchFilter":"","filterWeight":0,"appStoreId":[],"requirements":[],"offerType":"StaticPrice","giftInfo":{"bIsEnabled":true,"forcedGiftBoxTemplateId":"","purchaseRequirements":[],"giftRecordIds":[]},"refundable":false,"metaInfo":[],"displayAssetPath":"","itemGrants":[],"sortPriority":0,"catalogGroupPriority":0};
|
||||
|
||||
let i = catalog.storefronts.findIndex(p => p.name == (value.toLowerCase().startsWith("daily") ? "BRDailyStorefront" : "BRWeeklyStorefront"));
|
||||
if (i == -1) continue;
|
||||
|
||||
for (let itemGrant of CatalogConfig[value].itemGrants) {
|
||||
if (typeof itemGrant != "string") continue;
|
||||
if (itemGrant.length == 0) continue;
|
||||
|
||||
CatalogEntry.requirements.push({ "requirementType": "DenyOnItemOwnership", "requiredId": itemGrant, "minQuantity": 1 });
|
||||
CatalogEntry.itemGrants.push({ "templateId": itemGrant, "quantity": 1 });
|
||||
}
|
||||
|
||||
CatalogEntry.prices = [{
|
||||
"currencyType": "MtxCurrency",
|
||||
"currencySubType": "",
|
||||
"regularPrice": CatalogConfig[value].price,
|
||||
"finalPrice": CatalogConfig[value].price,
|
||||
"saleExpiration": "9999-12-02T01:12:00Z",
|
||||
"basePrice": CatalogConfig[value].price
|
||||
}];
|
||||
|
||||
if (CatalogEntry.itemGrants.length > 0) {
|
||||
let uniqueIdentifier = crypto.createHash("sha1").update(`${JSON.stringify(CatalogConfig[value].itemGrants)}_${CatalogConfig[value].price}`).digest("hex");
|
||||
|
||||
CatalogEntry.devName = uniqueIdentifier;
|
||||
CatalogEntry.offerId = uniqueIdentifier;
|
||||
|
||||
catalog.storefronts[i].catalogEntries.push(CatalogEntry);
|
||||
}
|
||||
}
|
||||
} catch {}
|
||||
|
||||
return catalog;
|
||||
}
|
||||
|
||||
function getOfferID(offerId) {
|
||||
const catalog = getItemShop();
|
||||
|
||||
for (let storefront of catalog.storefronts) {
|
||||
let findOfferId = storefront.catalogEntries.find(i => i.offerId == offerId);
|
||||
|
||||
if (findOfferId) return {
|
||||
name: storefront.name,
|
||||
offerId: findOfferId
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
function MakeID() {
|
||||
return uuid.v4();
|
||||
}
|
||||
|
||||
function sendXmppMessageToAll(body) {
|
||||
if (!global.Clients) return;
|
||||
if (typeof body == "object") body = JSON.stringify(body);
|
||||
|
||||
global.Clients.forEach(ClientData => {
|
||||
ClientData.client.send(XMLBuilder.create("message")
|
||||
.attribute("from", "[email protected]")
|
||||
.attribute("xmlns", "jabber:client")
|
||||
.attribute("to", ClientData.jid)
|
||||
.element("body", `${body}`).up().toString());
|
||||
});
|
||||
}
|
||||
|
||||
function sendXmppMessageToId(body, toAccountId) {
|
||||
if (!global.Clients) return;
|
||||
if (typeof body == "object") body = JSON.stringify(body);
|
||||
|
||||
let receiver = global.Clients.find(i => i.accountId == toAccountId);
|
||||
if (!receiver) return;
|
||||
|
||||
receiver.client.send(XMLBuilder.create("message")
|
||||
.attribute("from", "[email protected]")
|
||||
.attribute("to", receiver.jid)
|
||||
.attribute("xmlns", "jabber:client")
|
||||
.element("body", `${body}`).up().toString());
|
||||
}
|
||||
|
||||
function getPresenceFromUser(fromId, toId, offline) {
|
||||
if (!global.Clients) return;
|
||||
|
||||
let SenderData = global.Clients.find(i => i.accountId == fromId);
|
||||
let ClientData = global.Clients.find(i => i.accountId == toId);
|
||||
|
||||
if (!SenderData || !ClientData) return;
|
||||
|
||||
let xml = XMLBuilder.create("presence")
|
||||
.attribute("to", ClientData.jid)
|
||||
.attribute("xmlns", "jabber:client")
|
||||
.attribute("from", SenderData.jid)
|
||||
.attribute("type", offline ? "unavailable" : "available")
|
||||
|
||||
if (SenderData.lastPresenceUpdate.away) xml = xml.element("show", "away").up().element("status", SenderData.lastPresenceUpdate.status).up();
|
||||
else xml = xml.element("status", SenderData.lastPresenceUpdate.status).up();
|
||||
|
||||
ClientData.client.send(xml.toString());
|
||||
}
|
||||
|
||||
async function registerUser(discordId, username, email, plainPassword) {
|
||||
email = email.toLowerCase();
|
||||
|
||||
if (!discordId || !username || !email || !plainPassword) return { message: "Username/email/password is required.", status: 400 };
|
||||
|
||||
if (await User.findOne({ discordId })) return { message: "You already created an account!", status: 400 };
|
||||
|
||||
const accountId = MakeID().replace(/-/ig, "");
|
||||
|
||||
// filters
|
||||
const emailFilter = /^([a-zA-Z0-9_\.\-])+\@(([a-zA-Z0-9\-])+\.)+([a-zA-Z0-9]{2,4})+$/;
|
||||
if (!emailFilter.test(email)) return { message: "You did not provide a valid email address!", status: 400 };
|
||||
if (username.length >= 25) return { message: "Your username must be less than 25 characters long.", status: 400 };
|
||||
if (username.length < 3) return { message: "Your username must be atleast 3 characters long.", status: 400 };
|
||||
if (plainPassword.length >= 128) return { message: "Your password must be less than 128 characters long.", status: 400 };
|
||||
if (plainPassword.length < 8) return { message: "Your password must be atleast 8 characters long.", status: 400 };
|
||||
|
||||
const allowedCharacters = (" !\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~").split("");
|
||||
|
||||
for (let character of username) {
|
||||
if (!allowedCharacters.includes(character)) return { message: "Your username has special characters, please remove them and try again.", status: 400 };
|
||||
}
|
||||
|
||||
const hashedPassword = await bcrypt.hash(plainPassword, 10);
|
||||
|
||||
try {
|
||||
await User.create({ created: new Date().toISOString(), discordId, accountId, username, username_lower: username.toLowerCase(), email, password: hashedPassword }).then(async (i) => {
|
||||
await Profile.create({ created: i.created, accountId: i.accountId, profiles: profileManager.createProfiles(i.accountId) });
|
||||
await Friends.create({ created: i.created, accountId: i.accountId });
|
||||
});
|
||||
} catch (err) {
|
||||
if (err.code == 11000) return { message: `Username or email is already in use.`, status: 400 };
|
||||
|
||||
return { message: "An unknown error has occured, please try again later.", status: 400 };
|
||||
};
|
||||
|
||||
return { message: `Successfully created an account with the username ${username}`, status: 200 };
|
||||
}
|
||||
|
||||
function DecodeBase64(str) {
|
||||
return Buffer.from(str, 'base64').toString();
|
||||
}
|
||||
|
||||
function UpdateTokens() {
|
||||
fs.writeFileSync("./tokenManager/tokens.json", JSON.stringify({
|
||||
accessTokens: global.accessTokens,
|
||||
refreshTokens: global.refreshTokens,
|
||||
clientTokens: global.clientTokens
|
||||
}, null, 2));
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
sleep,
|
||||
GetVersionInfo,
|
||||
getContentPages,
|
||||
getItemShop,
|
||||
getOfferID,
|
||||
MakeID,
|
||||
sendXmppMessageToAll,
|
||||
sendXmppMessageToId,
|
||||
getPresenceFromUser,
|
||||
registerUser,
|
||||
DecodeBase64,
|
||||
UpdateTokens
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
function backend() {
|
||||
let msg = "";
|
||||
|
||||
for (let i in backend.arguments) {
|
||||
msg += `${i == "0" ? "" : " "}${backend.arguments[i]}`;
|
||||
}
|
||||
|
||||
console.log(`\x1b[32mBackend Log\x1b[0m: ${msg}`);
|
||||
}
|
||||
|
||||
function bot() {
|
||||
let msg = "";
|
||||
|
||||
for (let i in bot.arguments) {
|
||||
msg += `${i == "0" ? "" : " "}${bot.arguments[i]}`;
|
||||
}
|
||||
|
||||
console.log(`\x1b[33mBot Log\x1b[0m: ${msg}`);
|
||||
}
|
||||
|
||||
function xmpp() {
|
||||
let msg = "";
|
||||
|
||||
for (let i in xmpp.arguments) {
|
||||
msg += `${i == "0" ? "" : " "}${xmpp.arguments[i]}`;
|
||||
}
|
||||
|
||||
console.log(`\x1b[34mXmpp Log\x1b[0m: ${msg}`);
|
||||
}
|
||||
|
||||
function error() {
|
||||
let msg = "";
|
||||
|
||||
for (let i in error.arguments) {
|
||||
msg += `${i == "0" ? "" : " "}${error.arguments[i]}`;
|
||||
}
|
||||
|
||||
console.log(`\x1b[31mError\x1b[0m: ${msg}`);
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
backend,
|
||||
bot,
|
||||
xmpp,
|
||||
error
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
const fs = require("fs");
|
||||
|
||||
function createProfiles(accountId) {
|
||||
let profiles = {};
|
||||
|
||||
fs.readdirSync("./Config/DefaultProfiles").forEach(fileName => {
|
||||
const profile = require(`../Config/DefaultProfiles/${fileName}`);
|
||||
|
||||
profile.accountId = accountId;
|
||||
profile.created = new Date().toISOString();
|
||||
profile.updated = new Date().toISOString();
|
||||
|
||||
profiles[profile.profileId] = profile;
|
||||
});
|
||||
|
||||
return profiles;
|
||||
}
|
||||
|
||||
async function validateProfile(profileId, profiles) {
|
||||
try {
|
||||
let profile = profiles.profiles[profileId];
|
||||
|
||||
if (!profile || !profileId) throw new Error("Invalid profile/profileId");
|
||||
} catch {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
createProfiles,
|
||||
validateProfile
|
||||
}
|
||||
@@ -0,0 +1,69 @@
|
||||
const functions = require("../structs/functions.js");
|
||||
const jwt = require("jsonwebtoken");
|
||||
|
||||
function createClient(clientId, grant_type, ip, expiresIn) {
|
||||
let clientToken = jwt.sign({
|
||||
"p": Buffer.from(functions.MakeID()).toString("base64"),
|
||||
"clsvc": "fortnite",
|
||||
"t": "s",
|
||||
"mver": false,
|
||||
"clid": clientId,
|
||||
"ic": true,
|
||||
"am": grant_type,
|
||||
"jti": functions.MakeID().replace(/-/ig, ""),
|
||||
"creation_date": new Date(),
|
||||
"hours_expire": expiresIn
|
||||
}, global.JWT_SECRET, { expiresIn: `${expiresIn}h` });
|
||||
|
||||
global.clientTokens.push({ ip: ip, token: `eg1~${clientToken}` });
|
||||
|
||||
return clientToken;
|
||||
}
|
||||
|
||||
function createAccess(user, clientId, grant_type, deviceId, expiresIn) {
|
||||
let accessToken = jwt.sign({
|
||||
"app": "fortnite",
|
||||
"sub": user.accountId,
|
||||
"dvid": deviceId,
|
||||
"mver": false,
|
||||
"clid": clientId,
|
||||
"dn": user.username,
|
||||
"am": grant_type,
|
||||
"p": Buffer.from(functions.MakeID()).toString("base64"),
|
||||
"iai": user.accountId,
|
||||
"sec": 1,
|
||||
"clsvc": "fortnite",
|
||||
"t": "s",
|
||||
"ic": true,
|
||||
"jti": functions.MakeID().replace(/-/ig, ""),
|
||||
"creation_date": new Date(),
|
||||
"hours_expire": expiresIn
|
||||
}, global.JWT_SECRET, { expiresIn: `${expiresIn}h` });
|
||||
|
||||
global.accessTokens.push({ accountId: user.accountId, token: `eg1~${accessToken}` });
|
||||
|
||||
return accessToken;
|
||||
}
|
||||
|
||||
function createRefresh(user, clientId, grant_type, deviceId, expiresIn) {
|
||||
let refreshToken = jwt.sign({
|
||||
"sub": user.accountId,
|
||||
"dvid": deviceId,
|
||||
"t": "r",
|
||||
"clid": clientId,
|
||||
"am": grant_type,
|
||||
"jti": functions.MakeID().replace(/-/ig, ""),
|
||||
"creation_date": new Date(),
|
||||
"hours_expire": expiresIn
|
||||
}, global.JWT_SECRET, { expiresIn: `${expiresIn}h` });
|
||||
|
||||
global.refreshTokens.push({ accountId: user.accountId, token: `eg1~${refreshToken}` });
|
||||
|
||||
return refreshToken;
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
createClient,
|
||||
createAccess,
|
||||
createRefresh
|
||||
}
|
||||
@@ -0,0 +1,104 @@
|
||||
const jwt = require("jsonwebtoken");
|
||||
|
||||
const User = require("../model/user.js");
|
||||
const functions = require("../structs/functions.js");
|
||||
const error = require("../structs/error.js");
|
||||
|
||||
async function verifyToken(req, res, next) {
|
||||
let authErr = () => error.createError(
|
||||
"errors.com.epicgames.common.authorization.authorization_failed",
|
||||
`Authorization failed for ${req.originalUrl}`,
|
||||
[req.originalUrl], 1032, undefined, 401, res
|
||||
);
|
||||
|
||||
if (!req.headers["authorization"] || !req.headers["authorization"].startsWith("bearer eg1~")) return authErr();
|
||||
|
||||
const token = req.headers["authorization"].replace("bearer eg1~", "");
|
||||
|
||||
try {
|
||||
const decodedToken = jwt.decode(token);
|
||||
|
||||
if (!global.accessTokens.find(i => i.token == `eg1~${token}`)) throw new Error("Invalid token.");
|
||||
|
||||
if (DateAddHours(new Date(decodedToken.creation_date), decodedToken.hours_expire).getTime() <= new Date().getTime()) {
|
||||
throw new Error("Expired access token.");
|
||||
}
|
||||
|
||||
req.user = await User.findOne({ accountId: decodedToken.sub }).lean();
|
||||
|
||||
if (req.user.banned) return error.createError(
|
||||
"errors.com.epicgames.account.account_not_active",
|
||||
"You have been permanently banned from Fortnite.",
|
||||
[], -1, undefined, 400, res
|
||||
);
|
||||
|
||||
next();
|
||||
} catch {
|
||||
let accessIndex = global.accessTokens.findIndex(i => i.token == `eg1~${token}`);
|
||||
if (accessIndex != -1) {
|
||||
global.accessTokens.splice(accessIndex, 1);
|
||||
|
||||
functions.UpdateTokens();
|
||||
}
|
||||
|
||||
return authErr();
|
||||
}
|
||||
}
|
||||
|
||||
async function verifyClient(req, res, next) {
|
||||
let authErr = () => error.createError(
|
||||
"errors.com.epicgames.common.authorization.authorization_failed",
|
||||
`Authorization failed for ${req.originalUrl}`,
|
||||
[req.originalUrl], 1032, undefined, 401, res
|
||||
);
|
||||
|
||||
if (!req.headers["authorization"] || !req.headers["authorization"].startsWith("bearer eg1~")) return authErr();
|
||||
|
||||
const token = req.headers["authorization"].replace("bearer eg1~", "");
|
||||
|
||||
try {
|
||||
const decodedToken = jwt.decode(token);
|
||||
|
||||
let findAccess = global.accessTokens.find(i => i.token == `eg1~${token}`);
|
||||
|
||||
if (!findAccess && !global.clientTokens.find(i => i.token == `eg1~${token}`)) throw new Error("Invalid token.");
|
||||
|
||||
if (DateAddHours(new Date(decodedToken.creation_date), decodedToken.hours_expire).getTime() <= new Date().getTime()) {
|
||||
throw new Error("Expired access/client token.");
|
||||
}
|
||||
|
||||
if (findAccess) {
|
||||
req.user = await User.findOne({ accountId: decodedToken.sub }).lean();
|
||||
|
||||
if (req.user.banned) return error.createError(
|
||||
"errors.com.epicgames.account.account_not_active",
|
||||
"You have been permanently banned from Fortnite.",
|
||||
[], -1, undefined, 400, res
|
||||
);
|
||||
}
|
||||
|
||||
next();
|
||||
} catch (err) {
|
||||
let accessIndex = global.accessTokens.findIndex(i => i.token == `eg1~${token}`);
|
||||
if (accessIndex != -1) global.accessTokens.splice(accessIndex, 1);
|
||||
|
||||
let clientIndex = global.clientTokens.findIndex(i => i.token == `eg1~${token}`);
|
||||
if (clientIndex != -1) global.clientTokens.splice(clientIndex, 1);
|
||||
|
||||
if (accessIndex != -1 || clientIndex != -1) functions.UpdateTokens();
|
||||
|
||||
return authErr();
|
||||
}
|
||||
}
|
||||
|
||||
function DateAddHours(pdate, number) {
|
||||
let date = pdate;
|
||||
date.setHours(date.getHours() + number);
|
||||
|
||||
return date;
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
verifyToken,
|
||||
verifyClient
|
||||
}
|
||||
@@ -0,0 +1,132 @@
|
||||
{
|
||||
"accessTokens": [
|
||||
{
|
||||
"accountId": "17b3e746b51e4d55b9fb4c7944c8fc22",
|
||||
"token": "eg1~eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJhcHAiOiJmb3J0bml0ZSIsInN1YiI6IjE3YjNlNzQ2YjUxZTRkNTViOWZiNGM3OTQ0YzhmYzIyIiwiZHZpZCI6Ijk0M2Q2MjkyZDcxZjRmZjViNDU1MDE2MjEyOGFkNzRkIiwibXZlciI6ZmFsc2UsImNsaWQiOiJlYzY4NGI4YzY4N2Y0NzlmYWRlYTNjYjJhZDgzZjVjNiIsImRuIjoiRmlza2VuIiwiYW0iOiJwYXNzd29yZCIsInAiOiJaRFprT0RNelkyTXRNREExTnkwMFltWXdMVGc1WlRjdFltRmtaR00wTmprd05UbG0iLCJpYWkiOiIxN2IzZTc0NmI1MWU0ZDU1YjlmYjRjNzk0NGM4ZmMyMiIsInNlYyI6MSwiY2xzdmMiOiJmb3J0bml0ZSIsInQiOiJzIiwiaWMiOnRydWUsImp0aSI6ImUxNWU0MzU2N2ZkZjRlNjlhNjcwYWI4ZDU3MTA2Yzg2IiwiY3JlYXRpb25fZGF0ZSI6IjIwMjQtMDctMDRUMjE6MDc6MjguNTA0WiIsImhvdXJzX2V4cGlyZSI6OCwiaWF0IjoxNzIwMTI3MjQ4LCJleHAiOjE3MjAxNTYwNDh9.9ncABkt3qrvo2CLt7TB2w6XGJmNAfi4eSr-UERAKnr4"
|
||||
},
|
||||
{
|
||||
"accountId": "991a475866dd4910878d4aba87ff2879",
|
||||
"token": "eg1~eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJhcHAiOiJmb3J0bml0ZSIsInN1YiI6Ijk5MWE0NzU4NjZkZDQ5MTA4NzhkNGFiYTg3ZmYyODc5IiwiZHZpZCI6IjkyODkzMmQzMmZkNzQ4MzY5YjBjOWFhYzE3MGQ0NzMxIiwibXZlciI6ZmFsc2UsImNsaWQiOiJlYzY4NGI4YzY4N2Y0NzlmYWRlYTNjYjJhZDgzZjVjNiIsImRuIjoiY2FjYSIsImFtIjoicGFzc3dvcmQiLCJwIjoiWVRaaE1UQTROamt0TTJZNFpTMDBaV000TFdFeE1XVXRNMlE1WVRaaE1tRTNaREF3IiwiaWFpIjoiOTkxYTQ3NTg2NmRkNDkxMDg3OGQ0YWJhODdmZjI4NzkiLCJzZWMiOjEsImNsc3ZjIjoiZm9ydG5pdGUiLCJ0IjoicyIsImljIjp0cnVlLCJqdGkiOiIyMDBjNDgxYTU4ODI0MjE0YWEwOTViOTRkZWVjYjRkZSIsImNyZWF0aW9uX2RhdGUiOiIyMDI0LTA3LTA0VDIyOjA0OjM2Ljg1M1oiLCJob3Vyc19leHBpcmUiOjgsImlhdCI6MTcyMDEzMDY3NiwiZXhwIjoxNzIwMTU5NDc2fQ.uwBn4oGx2GCcjeISe0rSBSi5unGl1P5nESPWR-NTu9w"
|
||||
},
|
||||
{
|
||||
"accountId": "4074b82eece54257954323dcb2e7b2df",
|
||||
"token": "eg1~eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJhcHAiOiJmb3J0bml0ZSIsInN1YiI6IjQwNzRiODJlZWNlNTQyNTc5NTQzMjNkY2IyZTdiMmRmIiwiZHZpZCI6IjA3NjlkN2QxOGZlZDQxNzlhYTBkZjM1NTFhM2I4Nzg4IiwibXZlciI6ZmFsc2UsImNsaWQiOiJlYzY4NGI4YzY4N2Y0NzlmYWRlYTNjYjJhZDgzZjVjNiIsImRuIjoiTUJQQWJlbCIsImFtIjoicGFzc3dvcmQiLCJwIjoiTUROaU5HVmlZemN0WkRVM01DMDBNRGM1TFRrM05ERXRObVkyTlRZM1lUWmhPRFppIiwiaWFpIjoiNDA3NGI4MmVlY2U1NDI1Nzk1NDMyM2RjYjJlN2IyZGYiLCJzZWMiOjEsImNsc3ZjIjoiZm9ydG5pdGUiLCJ0IjoicyIsImljIjp0cnVlLCJqdGkiOiI2NjZlZWFlY2FhYWE0ODFhYWEzNzI5MWM4ZDk3NWYzZSIsImNyZWF0aW9uX2RhdGUiOiIyMDI0LTA3LTA1VDAwOjUyOjAwLjUxN1oiLCJob3Vyc19leHBpcmUiOjgsImlhdCI6MTcyMDE0MDcyMCwiZXhwIjoxNzIwMTY5NTIwfQ.B9HZXgjBws0VijXhjQT27edVGL7O1TfdaHaUr6IvogI"
|
||||
},
|
||||
{
|
||||
"accountId": "40211d5be4954f00acc5650829de8f43",
|
||||
"token": "eg1~eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJhcHAiOiJmb3J0bml0ZSIsInN1YiI6IjQwMjExZDViZTQ5NTRmMDBhY2M1NjUwODI5ZGU4ZjQzIiwiZHZpZCI6ImYzNGQwYjU2MWI3NTQ4MWNhMTc1YmRkNzJjNmQ2OTZiIiwibXZlciI6ZmFsc2UsImNsaWQiOiJlYzY4NGI4YzY4N2Y0NzlmYWRlYTNjYjJhZDgzZjVjNiIsImRuIjoiZGdkZ2RnIiwiYW0iOiJwYXNzd29yZCIsInAiOiJOV1E0Tm1Vek1HWXRaR1k1WWkwME9ERmpMVGszWmpjdE1UWTBNRE15TW1FeU1UQTAiLCJpYWkiOiI0MDIxMWQ1YmU0OTU0ZjAwYWNjNTY1MDgyOWRlOGY0MyIsInNlYyI6MSwiY2xzdmMiOiJmb3J0bml0ZSIsInQiOiJzIiwiaWMiOnRydWUsImp0aSI6ImU2YTMwYzFiYTViNDQ0ZTc4YmNiM2Q4ZGQ3YTI5NTc5IiwiY3JlYXRpb25fZGF0ZSI6IjIwMjQtMDctMDVUMDE6NDY6NTguMzU2WiIsImhvdXJzX2V4cGlyZSI6OCwiaWF0IjoxNzIwMTQ0MDE4LCJleHAiOjE3MjAxNzI4MTh9.VQRSl8lel1f0ef5eIy-oDLP0gZ21m0_FHoV73CVsUbk"
|
||||
},
|
||||
{
|
||||
"accountId": "d082eeaec6a84b58b7eede8de8ba3ef1",
|
||||
"token": "eg1~eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJhcHAiOiJmb3J0bml0ZSIsInN1YiI6ImQwODJlZWFlYzZhODRiNThiN2VlZGU4ZGU4YmEzZWYxIiwiZHZpZCI6IjIwMjJkNzBhMjc4OTQ2M2Y5YTE1ZTg5MTM3MzFmZTMyIiwibXZlciI6ZmFsc2UsImNsaWQiOiJlYzY4NGI4YzY4N2Y0NzlmYWRlYTNjYjJhZDgzZjVjNiIsImRuIjoiW093bmVyXSBFcGljSG9zdGluZ1NlcnZlciIsImFtIjoicmVmcmVzaF90b2tlbiIsInAiOiJNREkwTVRGbU5ERXRNamMwTmkwME5HVXlMVGxoTldVdFlqY3dNMlF6TXpjeE1EVm0iLCJpYWkiOiJkMDgyZWVhZWM2YTg0YjU4YjdlZWRlOGRlOGJhM2VmMSIsInNlYyI6MSwiY2xzdmMiOiJmb3J0bml0ZSIsInQiOiJzIiwiaWMiOnRydWUsImp0aSI6ImQyMWFiNDJlOGEwZjRkZDViMTUwYTJkZmExNzJhN2Q1IiwiY3JlYXRpb25fZGF0ZSI6IjIwMjQtMDctMDVUMDM6Mzc6NDUuOTUwWiIsImhvdXJzX2V4cGlyZSI6OCwiaWF0IjoxNzIwMTUwNjY1LCJleHAiOjE3MjAxNzk0NjV9.eGLGNoBNCfNarRf6EmqNBIjOjCgv9xIilr0LHDk3ZIQ"
|
||||
},
|
||||
{
|
||||
"accountId": "a88d41054f794ff8986c60d115c7c645",
|
||||
"token": "eg1~eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJhcHAiOiJmb3J0bml0ZSIsInN1YiI6ImE4OGQ0MTA1NGY3OTRmZjg5ODZjNjBkMTE1YzdjNjQ1IiwiZHZpZCI6IjRkZmJlNGM3NjY1MTQxMjE5Mzc2YTZkMWU5NjQ1M2IzIiwibXZlciI6ZmFsc2UsImNsaWQiOiJlYzY4NGI4YzY4N2Y0NzlmYWRlYTNjYjJhZDgzZjVjNiIsImRuIjoiW093bmVyXSBCdXJsb25lIiwiYW0iOiJwYXNzd29yZCIsInAiOiJZMlF6WkRSbE9ERXRaV1JoTWkwMFpqTXdMV0poWlRNdE56aGpNalJpWXpCak5ERm0iLCJpYWkiOiJhODhkNDEwNTRmNzk0ZmY4OTg2YzYwZDExNWM3YzY0NSIsInNlYyI6MSwiY2xzdmMiOiJmb3J0bml0ZSIsInQiOiJzIiwiaWMiOnRydWUsImp0aSI6IjMwZjU2MDViNjIyYzRkYjRiMDEzYjNlNGViMWUxOGRkIiwiY3JlYXRpb25fZGF0ZSI6IjIwMjQtMDctMDVUMDQ6MDc6MzUuNTI2WiIsImhvdXJzX2V4cGlyZSI6OCwiaWF0IjoxNzIwMTUyNDU1LCJleHAiOjE3MjAxODEyNTV9.knwWqbKBubCSLT6c1zxRgAEQUufNpcJ5nxXpUXEb-R4"
|
||||
}
|
||||
],
|
||||
"refreshTokens": [
|
||||
{
|
||||
"accountId": "4764b894a9524c869a0ab5e34767f7c5",
|
||||
"token": "eg1~eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiI0NzY0Yjg5NGE5NTI0Yzg2OWEwYWI1ZTM0NzY3ZjdjNSIsImR2aWQiOiI3NGM0NzU5YTk2M2Q0M2YzOTRiZmIwYjExMTcyNWY2NSIsInQiOiJyIiwiY2xpZCI6ImVjNjg0YjhjNjg3ZjQ3OWZhZGVhM2NiMmFkODNmNWM2IiwiYW0iOiJwYXNzd29yZCIsImp0aSI6IjM1MDE3ZmI3OGU5NjQzOWM4MDM4MDNmMTk4ZDE3Yzk1IiwiY3JlYXRpb25fZGF0ZSI6IjIwMjQtMDctMDRUMDY6MTI6MDIuMzQwWiIsImhvdXJzX2V4cGlyZSI6MjQsImlhdCI6MTcyMDA3MzUyMiwiZXhwIjoxNzIwMTU5OTIyfQ.QLU6qHajYIKrWvQF-LAMvMeWS_uOWY4MqGWDXYxMJCY"
|
||||
},
|
||||
{
|
||||
"accountId": "e8a831f6ea8c4d1d88861c69ff8c3007",
|
||||
"token": "eg1~eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJlOGE4MzFmNmVhOGM0ZDFkODg4NjFjNjlmZjhjMzAwNyIsImR2aWQiOiI0NTE5OTJkZDY2MzA0MmU5YWI3MjVlYjBjYzczM2MzMCIsInQiOiJyIiwiY2xpZCI6ImVjNjg0YjhjNjg3ZjQ3OWZhZGVhM2NiMmFkODNmNWM2IiwiYW0iOiJwYXNzd29yZCIsImp0aSI6ImQ1OGRhYzMyNDQ0NjQ3MWVhMzBhMDIyODI1YmI1ZjZkIiwiY3JlYXRpb25fZGF0ZSI6IjIwMjQtMDctMDRUMDY6MzI6MzcuNzYxWiIsImhvdXJzX2V4cGlyZSI6MjQsImlhdCI6MTcyMDA3NDc1NywiZXhwIjoxNzIwMTYxMTU3fQ.xrCpxPzwS5Geozn-GRuh7lxnFo4mzi4QaaxJ4guBeRs"
|
||||
},
|
||||
{
|
||||
"accountId": "35be9b871d584724bc768496d456bfa5",
|
||||
"token": "eg1~eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIzNWJlOWI4NzFkNTg0NzI0YmM3Njg0OTZkNDU2YmZhNSIsImR2aWQiOiI5NzZiZWZjMzkxMDQ0MGQ0OTMwMDkwMzU1YzY0MDc3YSIsInQiOiJyIiwiY2xpZCI6ImVjNjg0YjhjNjg3ZjQ3OWZhZGVhM2NiMmFkODNmNWM2IiwiYW0iOiJwYXNzd29yZCIsImp0aSI6IjEzNWJiYTZlZjY5ZDQyNmI4ZjUxYjM0NmIwNTRlODY4IiwiY3JlYXRpb25fZGF0ZSI6IjIwMjQtMDctMDRUMTI6NDU6MjguMzQ5WiIsImhvdXJzX2V4cGlyZSI6MjQsImlhdCI6MTcyMDA5NzEyOCwiZXhwIjoxNzIwMTgzNTI4fQ.l8le1KlPGVP5cm8VfZPezE2IuOE4uO003zlobe19srw"
|
||||
},
|
||||
{
|
||||
"accountId": "b0f7c36ed92e4556b9bdee019cb14146",
|
||||
"token": "eg1~eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJiMGY3YzM2ZWQ5MmU0NTU2YjliZGVlMDE5Y2IxNDE0NiIsImR2aWQiOiIyNzc2MGY2ODYxN2I0NDFhYjllMWE2NGIzYmQyMDg1OCIsInQiOiJyIiwiY2xpZCI6ImVjNjg0YjhjNjg3ZjQ3OWZhZGVhM2NiMmFkODNmNWM2IiwiYW0iOiJwYXNzd29yZCIsImp0aSI6ImE4Y2M3MWJlMDI3MzQ3MGJhZjc0NGUxZWJiZDU1MmZkIiwiY3JlYXRpb25fZGF0ZSI6IjIwMjQtMDctMDRUMTY6MTg6MTEuMTQ1WiIsImhvdXJzX2V4cGlyZSI6MjQsImlhdCI6MTcyMDEwOTg5MSwiZXhwIjoxNzIwMTk2MjkxfQ.NUghmA1T27g06Lo7qEYzmOEU4yqjXFpV43a6JeSqYFw"
|
||||
},
|
||||
{
|
||||
"accountId": "b509bda5f67e4775ae998b69530592ef",
|
||||
"token": "eg1~eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJiNTA5YmRhNWY2N2U0Nzc1YWU5OThiNjk1MzA1OTJlZiIsImR2aWQiOiJmMWMxNDQ0ZjAyMDk0YTVlYjdhZDkyYWFiZGIxMjg5MyIsInQiOiJyIiwiY2xpZCI6ImVjNjg0YjhjNjg3ZjQ3OWZhZGVhM2NiMmFkODNmNWM2IiwiYW0iOiJwYXNzd29yZCIsImp0aSI6IjQ5OWE5YmY2ZGM4NzQyMmI5Y2YwZjVjNmZhNWFjYTJkIiwiY3JlYXRpb25fZGF0ZSI6IjIwMjQtMDctMDRUMTY6MzM6NTcuMzU4WiIsImhvdXJzX2V4cGlyZSI6MjQsImlhdCI6MTcyMDExMDgzNywiZXhwIjoxNzIwMTk3MjM3fQ.Mqulgld3wooCUzP1eFJ97wQD4xOEYfxA3zSSjHX1w04"
|
||||
},
|
||||
{
|
||||
"accountId": "4ff26be89d7f4dfe82960dd5b5a8ed4e",
|
||||
"token": "eg1~eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiI0ZmYyNmJlODlkN2Y0ZGZlODI5NjBkZDViNWE4ZWQ0ZSIsImR2aWQiOiJjMTAyMmEzNzExYTk0YjNjOGIyNDc2YjNmNGI4ODJiYiIsInQiOiJyIiwiY2xpZCI6ImVjNjg0YjhjNjg3ZjQ3OWZhZGVhM2NiMmFkODNmNWM2IiwiYW0iOiJwYXNzd29yZCIsImp0aSI6Ijg0MTZiYzU2YmNkZTRjZTM4OTBlNWIzMDhiYmU1ZWM5IiwiY3JlYXRpb25fZGF0ZSI6IjIwMjQtMDctMDRUMTY6NTY6MzYuNTIyWiIsImhvdXJzX2V4cGlyZSI6MjQsImlhdCI6MTcyMDExMjE5NiwiZXhwIjoxNzIwMTk4NTk2fQ.Wc97h5_uqHLcp_F88AUbW8SWUk_qR26pt3G6AIPlSD4"
|
||||
},
|
||||
{
|
||||
"accountId": "4d57ab62ffcf420bb0a2ad110d4bc3dd",
|
||||
"token": "eg1~eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiI0ZDU3YWI2MmZmY2Y0MjBiYjBhMmFkMTEwZDRiYzNkZCIsImR2aWQiOiIzNmI5OGMyZTIyYjU0NThkOWRjNjdmZjI1YmQ0MDU5OSIsInQiOiJyIiwiY2xpZCI6ImVjNjg0YjhjNjg3ZjQ3OWZhZGVhM2NiMmFkODNmNWM2IiwiYW0iOiJwYXNzd29yZCIsImp0aSI6ImRlYzQ0OTlmYjk3MjRhMTM5YjcyZmUzYWIyODgyZjZmIiwiY3JlYXRpb25fZGF0ZSI6IjIwMjQtMDctMDRUMTc6MTk6NTIuMzI3WiIsImhvdXJzX2V4cGlyZSI6MjQsImlhdCI6MTcyMDExMzU5MiwiZXhwIjoxNzIwMTk5OTkyfQ.HLspzhIIVJXIpq73dQj1aHWwyR2SHpckANhC2FqrJqc"
|
||||
},
|
||||
{
|
||||
"accountId": "71d16952c758456ba57496fb1cf06661",
|
||||
"token": "eg1~eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiI3MWQxNjk1MmM3NTg0NTZiYTU3NDk2ZmIxY2YwNjY2MSIsImR2aWQiOiIyOWJiMWNhOTEyZTM0ZmEyOWYzZDRiNjVhYmZhMDA2YSIsInQiOiJyIiwiY2xpZCI6ImVjNjg0YjhjNjg3ZjQ3OWZhZGVhM2NiMmFkODNmNWM2IiwiYW0iOiJwYXNzd29yZCIsImp0aSI6IjVmZTYwNTIwYWI5NzQ3OGZhYzdhMzRjNzI1ZjMzNmJkIiwiY3JlYXRpb25fZGF0ZSI6IjIwMjQtMDctMDRUMTc6NTg6MTQuMzU1WiIsImhvdXJzX2V4cGlyZSI6MjQsImlhdCI6MTcyMDExNTg5NCwiZXhwIjoxNzIwMjAyMjk0fQ.sAXRDNpYAncq3AT1p15kPOK507EpeAPJEsSGF9KEL90"
|
||||
},
|
||||
{
|
||||
"accountId": "0a320655717a4156823c3187cebb9278",
|
||||
"token": "eg1~eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIwYTMyMDY1NTcxN2E0MTU2ODIzYzMxODdjZWJiOTI3OCIsImR2aWQiOiI4MTU1MGMxNTVkYzc0ZGVjYjkyNTMyZmFiMjM2NmQzMCIsInQiOiJyIiwiY2xpZCI6ImVjNjg0YjhjNjg3ZjQ3OWZhZGVhM2NiMmFkODNmNWM2IiwiYW0iOiJwYXNzd29yZCIsImp0aSI6IjUwYTI4MDBlMjI4NTQ4ODQ5MzA2MmRjZGIwZjc0ZGY1IiwiY3JlYXRpb25fZGF0ZSI6IjIwMjQtMDctMDRUMTg6NDg6MjkuNTU1WiIsImhvdXJzX2V4cGlyZSI6MjQsImlhdCI6MTcyMDExODkwOSwiZXhwIjoxNzIwMjA1MzA5fQ.614Qdy9kxW4sO_b4KYDhAJ_17vOloX4oyY8ajRDhfcA"
|
||||
},
|
||||
{
|
||||
"accountId": "c437d248ef3f4fbfb63045e138fad408",
|
||||
"token": "eg1~eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJjNDM3ZDI0OGVmM2Y0ZmJmYjYzMDQ1ZTEzOGZhZDQwOCIsImR2aWQiOiJmNGExMDg1M2JjMTk0MjEzODRhODYzMzBjYjM0MDViZSIsInQiOiJyIiwiY2xpZCI6ImVjNjg0YjhjNjg3ZjQ3OWZhZGVhM2NiMmFkODNmNWM2IiwiYW0iOiJwYXNzd29yZCIsImp0aSI6IjkwZTNhMjYxNWRlNTRhNjlhZThlMTMyNDMxZDk5ZmNmIiwiY3JlYXRpb25fZGF0ZSI6IjIwMjQtMDctMDRUMTg6NTg6NDQuNTg3WiIsImhvdXJzX2V4cGlyZSI6MjQsImlhdCI6MTcyMDExOTUyNCwiZXhwIjoxNzIwMjA1OTI0fQ.H3oKET_Ef_h8AKgjAiWlA8TJWDTI2hd8pfH98WDr_5Y"
|
||||
},
|
||||
{
|
||||
"accountId": "a53a50be82084941a8b6d972ed8d7d36",
|
||||
"token": "eg1~eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJhNTNhNTBiZTgyMDg0OTQxYThiNmQ5NzJlZDhkN2QzNiIsImR2aWQiOiIwM2M1Y2JhZWU3Yjk0ZmUzOTMwMWNmZjFkZDg2NTVhZCIsInQiOiJyIiwiY2xpZCI6ImVjNjg0YjhjNjg3ZjQ3OWZhZGVhM2NiMmFkODNmNWM2IiwiYW0iOiJwYXNzd29yZCIsImp0aSI6Ijc5Zjg1NjJlYmJiMjQ2N2FhM2IxNDQ0Y2E4MDc0NWM4IiwiY3JlYXRpb25fZGF0ZSI6IjIwMjQtMDctMDRUMTk6MTk6MDkuNTUzWiIsImhvdXJzX2V4cGlyZSI6MjQsImlhdCI6MTcyMDEyMDc0OSwiZXhwIjoxNzIwMjA3MTQ5fQ.GNk_eZU6feEmX37Z5cWOq_H1X1C7cXZDIgE4MrmFDPQ"
|
||||
},
|
||||
{
|
||||
"accountId": "2fdb987ca3c946b0908c80515515f691",
|
||||
"token": "eg1~eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIyZmRiOTg3Y2EzYzk0NmIwOTA4YzgwNTE1NTE1ZjY5MSIsImR2aWQiOiJjYzBjZTNhYzFhMDk0N2JkOGQ1MmZjZTdkNjQ5NTYxNiIsInQiOiJyIiwiY2xpZCI6ImVjNjg0YjhjNjg3ZjQ3OWZhZGVhM2NiMmFkODNmNWM2IiwiYW0iOiJwYXNzd29yZCIsImp0aSI6Ijg2ZjVkZjUxMjE3ZDRmNWM5MDQ4ZjhiM2RlZmZlNzUzIiwiY3JlYXRpb25fZGF0ZSI6IjIwMjQtMDctMDRUMTk6NDQ6MTEuNTMwWiIsImhvdXJzX2V4cGlyZSI6MjQsImlhdCI6MTcyMDEyMjI1MSwiZXhwIjoxNzIwMjA4NjUxfQ.v1HrFU5BB5EW6XeaLzdRc3v6HiM8f1rvwLZEIMCJcik"
|
||||
},
|
||||
{
|
||||
"accountId": "9fd79e95fc484eb08727ec0bdead82a3",
|
||||
"token": "eg1~eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiI5ZmQ3OWU5NWZjNDg0ZWIwODcyN2VjMGJkZWFkODJhMyIsImR2aWQiOiI4YzM5YzJjMDk3NDU0MTIyYWQ3Mjc0ZWM0OTEwMmIyMSIsInQiOiJyIiwiY2xpZCI6ImVjNjg0YjhjNjg3ZjQ3OWZhZGVhM2NiMmFkODNmNWM2IiwiYW0iOiJwYXNzd29yZCIsImp0aSI6ImM0ZTBjYzFkN2UyYjRkMjU4NTJlMDgwNjM1YzkyNDM1IiwiY3JlYXRpb25fZGF0ZSI6IjIwMjQtMDctMDRUMTk6NDc6MDQuOTU2WiIsImhvdXJzX2V4cGlyZSI6MjQsImlhdCI6MTcyMDEyMjQyNCwiZXhwIjoxNzIwMjA4ODI0fQ.XiN7CY3doJk4LJEO3ndfft9pd47qeIrrkBtFBqWUO3A"
|
||||
},
|
||||
{
|
||||
"accountId": "060104ea1fe64d9f92d56cfeec028035",
|
||||
"token": "eg1~eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIwNjAxMDRlYTFmZTY0ZDlmOTJkNTZjZmVlYzAyODAzNSIsImR2aWQiOiI1MGQ5ZDM2YjA4ZGM0ZjRiOTBjMjYxYzhkNDg2MzQ2OCIsInQiOiJyIiwiY2xpZCI6ImVjNjg0YjhjNjg3ZjQ3OWZhZGVhM2NiMmFkODNmNWM2IiwiYW0iOiJwYXNzd29yZCIsImp0aSI6IjNmMWYwMTMzNmUwODRkYjFhMzExZGU4ZjYyYTBhMDdhIiwiY3JlYXRpb25fZGF0ZSI6IjIwMjQtMDctMDRUMjA6MDk6MzQuMjMzWiIsImhvdXJzX2V4cGlyZSI6MjQsImlhdCI6MTcyMDEyMzc3NCwiZXhwIjoxNzIwMjEwMTc0fQ.P1m7nPdiXXPa-f4ewmoi9rnh8xCnohdo2bas4ui4Lp4"
|
||||
},
|
||||
{
|
||||
"accountId": "17e89257115a47a09d5d5f529d9a77a6",
|
||||
"token": "eg1~eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxN2U4OTI1NzExNWE0N2EwOWQ1ZDVmNTI5ZDlhNzdhNiIsImR2aWQiOiJlNTFmODFjNGQ4NWM0Mzc0YTc4NjlhNjY5ZTMyMGE3NCIsInQiOiJyIiwiY2xpZCI6ImVjNjg0YjhjNjg3ZjQ3OWZhZGVhM2NiMmFkODNmNWM2IiwiYW0iOiJwYXNzd29yZCIsImp0aSI6ImY1MGY4NGQ3ZDZlMjQzYjVhODIwZmUyY2M0NjY5MzY3IiwiY3JlYXRpb25fZGF0ZSI6IjIwMjQtMDctMDRUMjA6MTc6MTUuNTAxWiIsImhvdXJzX2V4cGlyZSI6MjQsImlhdCI6MTcyMDEyNDIzNSwiZXhwIjoxNzIwMjEwNjM1fQ.67gPQmWBJtoeHl6ZQwWd11u6NPpTOUCBo8LZkbmW2Tc"
|
||||
},
|
||||
{
|
||||
"accountId": "17b3e746b51e4d55b9fb4c7944c8fc22",
|
||||
"token": "eg1~eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxN2IzZTc0NmI1MWU0ZDU1YjlmYjRjNzk0NGM4ZmMyMiIsImR2aWQiOiI5NDNkNjI5MmQ3MWY0ZmY1YjQ1NTAxNjIxMjhhZDc0ZCIsInQiOiJyIiwiY2xpZCI6ImVjNjg0YjhjNjg3ZjQ3OWZhZGVhM2NiMmFkODNmNWM2IiwiYW0iOiJwYXNzd29yZCIsImp0aSI6Ijk3OGU2MWFlMzZiZjQ4NjNiMzY4ZTQxYzU4MTFlNzZiIiwiY3JlYXRpb25fZGF0ZSI6IjIwMjQtMDctMDRUMjE6MDc6MjguNTA1WiIsImhvdXJzX2V4cGlyZSI6MjQsImlhdCI6MTcyMDEyNzI0OCwiZXhwIjoxNzIwMjEzNjQ4fQ.nUd7lbuAqzCJK1YPyqiIVcOSDdT_DvHVoB7C40mmn40"
|
||||
},
|
||||
{
|
||||
"accountId": "991a475866dd4910878d4aba87ff2879",
|
||||
"token": "eg1~eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiI5OTFhNDc1ODY2ZGQ0OTEwODc4ZDRhYmE4N2ZmMjg3OSIsImR2aWQiOiI5Mjg5MzJkMzJmZDc0ODM2OWIwYzlhYWMxNzBkNDczMSIsInQiOiJyIiwiY2xpZCI6ImVjNjg0YjhjNjg3ZjQ3OWZhZGVhM2NiMmFkODNmNWM2IiwiYW0iOiJwYXNzd29yZCIsImp0aSI6ImZkMGZmNDViYjk0OTRhZDc5MTI0MDM1NDgyOTg2OWYzIiwiY3JlYXRpb25fZGF0ZSI6IjIwMjQtMDctMDRUMjI6MDQ6MzYuODU0WiIsImhvdXJzX2V4cGlyZSI6MjQsImlhdCI6MTcyMDEzMDY3NiwiZXhwIjoxNzIwMjE3MDc2fQ.4ZXvEXTiwSIthsmib0iyrSQFHmI4sXPI5AwkFm9eEpQ"
|
||||
},
|
||||
{
|
||||
"accountId": "4074b82eece54257954323dcb2e7b2df",
|
||||
"token": "eg1~eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiI0MDc0YjgyZWVjZTU0MjU3OTU0MzIzZGNiMmU3YjJkZiIsImR2aWQiOiIwNzY5ZDdkMThmZWQ0MTc5YWEwZGYzNTUxYTNiODc4OCIsInQiOiJyIiwiY2xpZCI6ImVjNjg0YjhjNjg3ZjQ3OWZhZGVhM2NiMmFkODNmNWM2IiwiYW0iOiJwYXNzd29yZCIsImp0aSI6IjBiYjI4M2QyYTY2NzQzNDRiZDRiMmU2NzI2ZGQ2ZTcxIiwiY3JlYXRpb25fZGF0ZSI6IjIwMjQtMDctMDVUMDA6NTI6MDAuNTE5WiIsImhvdXJzX2V4cGlyZSI6MjQsImlhdCI6MTcyMDE0MDcyMCwiZXhwIjoxNzIwMjI3MTIwfQ.se8vvubSiqgzG4evoYoukqYzpu41fJbG8Od6xroSPbU"
|
||||
},
|
||||
{
|
||||
"accountId": "40211d5be4954f00acc5650829de8f43",
|
||||
"token": "eg1~eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiI0MDIxMWQ1YmU0OTU0ZjAwYWNjNTY1MDgyOWRlOGY0MyIsImR2aWQiOiJmMzRkMGI1NjFiNzU0ODFjYTE3NWJkZDcyYzZkNjk2YiIsInQiOiJyIiwiY2xpZCI6ImVjNjg0YjhjNjg3ZjQ3OWZhZGVhM2NiMmFkODNmNWM2IiwiYW0iOiJwYXNzd29yZCIsImp0aSI6IjA2NTg2MDgwNTg0YjQ1ZDM5MTE2NGM4YzRkYTg5M2U3IiwiY3JlYXRpb25fZGF0ZSI6IjIwMjQtMDctMDVUMDE6NDY6NTguMzU4WiIsImhvdXJzX2V4cGlyZSI6MjQsImlhdCI6MTcyMDE0NDAxOCwiZXhwIjoxNzIwMjMwNDE4fQ.9sT_ZteavPIQZRPuJSKULuD-zk6jdbyo15-a9924o2Y"
|
||||
},
|
||||
{
|
||||
"accountId": "d082eeaec6a84b58b7eede8de8ba3ef1",
|
||||
"token": "eg1~eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJkMDgyZWVhZWM2YTg0YjU4YjdlZWRlOGRlOGJhM2VmMSIsImR2aWQiOiIyMDIyZDcwYTI3ODk0NjNmOWExNWU4OTEzNzMxZmUzMiIsInQiOiJyIiwiY2xpZCI6ImVjNjg0YjhjNjg3ZjQ3OWZhZGVhM2NiMmFkODNmNWM2IiwiYW0iOiJyZWZyZXNoX3Rva2VuIiwianRpIjoiM2ExYmMyYzIwYjE3NGM1MjlkNzNiMDllZGQ1NTE4ZDciLCJjcmVhdGlvbl9kYXRlIjoiMjAyNC0wNy0wNVQwMzozNzo0NS45NTZaIiwiaG91cnNfZXhwaXJlIjoyNCwiaWF0IjoxNzIwMTUwNjY1LCJleHAiOjE3MjAyMzcwNjV9.ElUBPGxWigQFON95_8w3TwEImvVw_IJ9l_S8ujXmorU"
|
||||
},
|
||||
{
|
||||
"accountId": "a88d41054f794ff8986c60d115c7c645",
|
||||
"token": "eg1~eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJhODhkNDEwNTRmNzk0ZmY4OTg2YzYwZDExNWM3YzY0NSIsImR2aWQiOiI0ZGZiZTRjNzY2NTE0MTIxOTM3NmE2ZDFlOTY0NTNiMyIsInQiOiJyIiwiY2xpZCI6ImVjNjg0YjhjNjg3ZjQ3OWZhZGVhM2NiMmFkODNmNWM2IiwiYW0iOiJwYXNzd29yZCIsImp0aSI6IjgxYWEyNzBkZTE2YzQ0MTY4ZDNkYzBkYzkxMzY5NjE2IiwiY3JlYXRpb25fZGF0ZSI6IjIwMjQtMDctMDVUMDQ6MDc6MzUuNTI4WiIsImhvdXJzX2V4cGlyZSI6MjQsImlhdCI6MTcyMDE1MjQ1NSwiZXhwIjoxNzIwMjM4ODU1fQ.ko4L7Hm6pU51aNefgRqHy674uHiokWiXcIylRvPkGQg"
|
||||
}
|
||||
],
|
||||
"clientTokens": [
|
||||
{
|
||||
"ip": "::ffff:176.45.138.104",
|
||||
"token": "eg1~eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJwIjoiWmpRNVltWmpNekl0TlRRMk15MDBaak5oTFdJMU5ERXRaR013T1dFMFpEVTJaV0ZrIiwiY2xzdmMiOiJmb3J0bml0ZSIsInQiOiJzIiwibXZlciI6ZmFsc2UsImNsaWQiOiJlYzY4NGI4YzY4N2Y0NzlmYWRlYTNjYjJhZDgzZjVjNiIsImljIjp0cnVlLCJhbSI6ImNsaWVudF9jcmVkZW50aWFscyIsImp0aSI6IjczODY0NDJlMDlhMDQzODdhN2Q3NWZhY2JkZDFhYjI1IiwiY3JlYXRpb25fZGF0ZSI6IjIwMjQtMDctMDRUMjI6MjM6MDUuOTgwWiIsImhvdXJzX2V4cGlyZSI6NCwiaWF0IjoxNzIwMTMxNzg1LCJleHAiOjE3MjAxNDYxODV9._PnPaBS4p9E_Rva9LoXOiOxOkief9bq1Dl7L1OJLW3s"
|
||||
},
|
||||
{
|
||||
"ip": "::ffff:79.46.51.2",
|
||||
"token": "eg1~eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJwIjoiTlRJeU1UWmtPRGN0TmpjNE1DMDBaamRqTFdJeU4yTXROVGRrWkROaU5qRmtNemRpIiwiY2xzdmMiOiJmb3J0bml0ZSIsInQiOiJzIiwibXZlciI6ZmFsc2UsImNsaWQiOiJlYzY4NGI4YzY4N2Y0NzlmYWRlYTNjYjJhZDgzZjVjNiIsImljIjp0cnVlLCJhbSI6ImNsaWVudF9jcmVkZW50aWFscyIsImp0aSI6ImM3NWQ3NmE4OGEyNzRmMGViYzE1NjMzYWNlMzQ1ZWRjIiwiY3JlYXRpb25fZGF0ZSI6IjIwMjQtMDctMDVUMDE6NDY6MjguMjgzWiIsImhvdXJzX2V4cGlyZSI6NCwiaWF0IjoxNzIwMTQzOTg4LCJleHAiOjE3MjAxNTgzODh9.DR80kN5jNZ8OOPn3Gl9RRLXVJj2Lknct6ifhGMj1QBs"
|
||||
},
|
||||
{
|
||||
"ip": "::ffff:5.180.34.99",
|
||||
"token": "eg1~eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJwIjoiTkdZME9EQm1ZV1l0WXpBeU15MDBOMkZoTFRneU1tUXROak00TW1JME5USTNPRE5sIiwiY2xzdmMiOiJmb3J0bml0ZSIsInQiOiJzIiwibXZlciI6ZmFsc2UsImNsaWQiOiJlYzY4NGI4YzY4N2Y0NzlmYWRlYTNjYjJhZDgzZjVjNiIsImljIjp0cnVlLCJhbSI6ImNsaWVudF9jcmVkZW50aWFscyIsImp0aSI6ImMwMGMzOWNiM2Y3ZDQzNjc4ZjA0OWIwYzgwZWJhOGM3IiwiY3JlYXRpb25fZGF0ZSI6IjIwMjQtMDctMDVUMDI6MTM6MzMuNjA2WiIsImhvdXJzX2V4cGlyZSI6NCwiaWF0IjoxNzIwMTQ1NjEzLCJleHAiOjE3MjAxNjAwMTN9.TND3TEQ4QTz6ILk4ofADoUAkIutzUYNV8-PKLrrnuUo"
|
||||
},
|
||||
{
|
||||
"ip": "::ffff:79.32.133.67",
|
||||
"token": "eg1~eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJwIjoiTmpZek1ERTBPR010TVdRd1l5MDBNRE5rTFdJMU1EQXRZalZrWW1aaE9UWmxObVprIiwiY2xzdmMiOiJmb3J0bml0ZSIsInQiOiJzIiwibXZlciI6ZmFsc2UsImNsaWQiOiJlYzY4NGI4YzY4N2Y0NzlmYWRlYTNjYjJhZDgzZjVjNiIsImljIjp0cnVlLCJhbSI6ImNsaWVudF9jcmVkZW50aWFscyIsImp0aSI6IjFhMzJmZjJlOTE0ZTRiZDk5YmUyN2JlYjA2ZGIyNjA2IiwiY3JlYXRpb25fZGF0ZSI6IjIwMjQtMDctMDVUMDQ6MDc6MzQuMzkyWiIsImhvdXJzX2V4cGlyZSI6NCwiaWF0IjoxNzIwMTUyNDU0LCJleHAiOjE3MjAxNjY4NTR9.650TUvW53qAFDeWcwccpge6yRKSDh9_pVTcIrWF6QQw"
|
||||
}
|
||||
]
|
||||
}
|
||||
+530
@@ -0,0 +1,530 @@
|
||||
const WebSocket = require("ws").Server;
|
||||
const XMLBuilder = require("xmlbuilder");
|
||||
const XMLParser = require("xml-parser");
|
||||
const express = require("express");
|
||||
const app = express();
|
||||
|
||||
const log = require("../structs/log.js");
|
||||
const functions = require("../structs/functions.js");
|
||||
|
||||
const User = require("../model/user.js");
|
||||
const Friends = require("../model/friends.js");
|
||||
|
||||
const port = 80;
|
||||
const wss = new WebSocket({ server: app.listen(port) });
|
||||
const matchmaker = require("../matchmaker/matchmaker.js");
|
||||
|
||||
let domain = "prod.ol.epicgames.com";
|
||||
|
||||
global.Clients = [];
|
||||
|
||||
// multi user chat rooms (global chat/party chat)
|
||||
global.MUCs = {};
|
||||
|
||||
app.get("/", (req, res) => {
|
||||
res.type("application/json");
|
||||
res.header("Access-Control-Allow-Origin", "*");
|
||||
|
||||
let data = JSON.stringify({
|
||||
"Clients": {
|
||||
"amount": global.Clients.length,
|
||||
"clients": global.Clients.map(i => i.displayName)
|
||||
}
|
||||
}, null, 2);
|
||||
|
||||
res.send(data);
|
||||
});
|
||||
|
||||
app.get("/clients", (req, res) => {
|
||||
res.type("application/json");
|
||||
|
||||
let data = JSON.stringify({
|
||||
"amount": global.Clients.length,
|
||||
"clients": global.Clients.map(i => i.displayName)
|
||||
}, null, 2);
|
||||
|
||||
res.send(data);
|
||||
});
|
||||
|
||||
wss.on('listening', () => {
|
||||
log.xmpp(`XMPP and Matchmaker started listening on port ${port}`);
|
||||
});
|
||||
|
||||
wss.on('connection', async (ws) => {
|
||||
ws.on('error', () => {});
|
||||
|
||||
// Start matchmaker if it's not connecting for xmpp.
|
||||
if (ws.protocol.toLowerCase() != "xmpp") return matchmaker(ws);
|
||||
|
||||
let joinedMUCs = [];
|
||||
let accountId = "";
|
||||
let displayName = "";
|
||||
let token = "";
|
||||
let jid = "";
|
||||
let resource = "";
|
||||
let ID = functions.MakeID();
|
||||
let Authenticated = false;
|
||||
let clientExists = false;
|
||||
let connectionClosed = false;
|
||||
|
||||
ws.on('message', async (message) => {
|
||||
if (Buffer.isBuffer(message)) message = message.toString();
|
||||
|
||||
const msg = XMLParser(message);
|
||||
if (!msg || !msg.root || !msg.root.name) return Error(ws);
|
||||
|
||||
switch (msg.root.name) {
|
||||
case "open":
|
||||
ws.send(XMLBuilder.create("open")
|
||||
.attribute("xmlns", "urn:ietf:params:xml:ns:xmpp-framing")
|
||||
.attribute("from", domain)
|
||||
.attribute("id", ID)
|
||||
.attribute("version", "1.0")
|
||||
.attribute("xml:lang", "en").toString());
|
||||
|
||||
if (Authenticated) {
|
||||
ws.send(XMLBuilder.create("stream:features").attribute("xmlns:stream", "http://etherx.jabber.org/streams")
|
||||
.element("ver").attribute("xmlns", "urn:xmpp:features:rosterver").up()
|
||||
.element("starttls").attribute("xmlns", "urn:ietf:params:xml:ns:xmpp-tls").up()
|
||||
.element("bind").attribute("xmlns", "urn:ietf:params:xml:ns:xmpp-bind").up()
|
||||
.element("compression").attribute("xmlns", "http://jabber.org/features/compress")
|
||||
.element("method", "zlib").up().up()
|
||||
.element("session").attribute("xmlns", "urn:ietf:params:xml:ns:xmpp-session").up().toString());
|
||||
} else {
|
||||
ws.send(XMLBuilder.create("stream:features").attribute("xmlns:stream", "http://etherx.jabber.org/streams")
|
||||
.element("mechanisms").attribute("xmlns", "urn:ietf:params:xml:ns:xmpp-sasl")
|
||||
.element("mechanism", "PLAIN").up().up()
|
||||
.element("ver").attribute("xmlns", "urn:xmpp:features:rosterver").up()
|
||||
.element("starttls").attribute("xmlns", "urn:ietf:params:xml:ns:xmpp-tls").up()
|
||||
.element("compression").attribute("xmlns", "http://jabber.org/features/compress")
|
||||
.element("method", "zlib").up().up()
|
||||
.element("auth").attribute("xmlns", "http://jabber.org/features/iq-auth").up().toString());
|
||||
}
|
||||
break;
|
||||
|
||||
case "auth":
|
||||
if (accountId) return;
|
||||
if (!msg.root.content) return Error(ws);
|
||||
if (!functions.DecodeBase64(msg.root.content).includes("\u0000")) return Error(ws);
|
||||
|
||||
let decodedBase64 = functions.DecodeBase64(msg.root.content).split("\u0000");
|
||||
|
||||
let object = global.accessTokens.find(i => i.token == decodedBase64[2]);
|
||||
if (!object) return Error(ws);
|
||||
|
||||
if (global.Clients.find(i => i.accountId == object.accountId)) return Error(ws);
|
||||
|
||||
let user = await User.findOne({ accountId: object.accountId, banned: false }).lean();
|
||||
if (!user) return Error(ws);
|
||||
|
||||
accountId = user.accountId;
|
||||
displayName = user.username;
|
||||
token = object.token;
|
||||
|
||||
if (decodedBase64 && accountId && displayName && token && decodedBase64.length == 3) {
|
||||
Authenticated = true;
|
||||
log.xmpp(`An xmpp client with the displayName ${displayName} has logged in.`);
|
||||
|
||||
ws.send(XMLBuilder.create("success").attribute("xmlns", "urn:ietf:params:xml:ns:xmpp-sasl").toString());
|
||||
} else return Error(ws);
|
||||
break;
|
||||
|
||||
case "iq":
|
||||
switch (msg.root.attributes.id) {
|
||||
case "_xmpp_bind1":
|
||||
if (resource || !accountId) return;
|
||||
if (!msg.root.children.find(i => i.name == "bind")) return;
|
||||
|
||||
if (global.Clients.find(i => i.accountId == accountId)) return Error(ws);
|
||||
|
||||
let findResource = msg.root.children.find(i => i.name == "bind").children.find(i => i.name == "resource");
|
||||
|
||||
if (!findResource) return;
|
||||
if (!findResource.content) return;
|
||||
|
||||
resource = findResource.content;
|
||||
jid = `${accountId}@${domain}/${resource}`;
|
||||
|
||||
ws.send(XMLBuilder.create("iq")
|
||||
.attribute("to", jid)
|
||||
.attribute("id", "_xmpp_bind1")
|
||||
.attribute("xmlns", "jabber:client")
|
||||
.attribute("type", "result")
|
||||
.element("bind")
|
||||
.attribute("xmlns", "urn:ietf:params:xml:ns:xmpp-bind")
|
||||
.element("jid", jid).up().up().toString());
|
||||
break;
|
||||
|
||||
case "_xmpp_session1":
|
||||
if (!clientExists) return Error(ws);
|
||||
|
||||
ws.send(XMLBuilder.create("iq")
|
||||
.attribute("to", jid)
|
||||
.attribute("from", domain)
|
||||
.attribute("id", "_xmpp_session1")
|
||||
.attribute("xmlns", "jabber:client")
|
||||
.attribute("type", "result").toString());
|
||||
|
||||
await getPresenceFromFriends(ws, accountId, jid);
|
||||
break;
|
||||
|
||||
default:
|
||||
if (!clientExists) return Error(ws);
|
||||
|
||||
ws.send(XMLBuilder.create("iq")
|
||||
.attribute("to", jid)
|
||||
.attribute("from", domain)
|
||||
.attribute("id", msg.root.attributes.id)
|
||||
.attribute("xmlns", "jabber:client")
|
||||
.attribute("type", "result").toString());
|
||||
}
|
||||
break;
|
||||
|
||||
case "message":
|
||||
if (!clientExists) return Error(ws);
|
||||
|
||||
let findBody = msg.root.children.find(i => i.name == "body");
|
||||
|
||||
if (!findBody || !findBody.content) return;
|
||||
|
||||
let body = findBody.content;
|
||||
|
||||
switch (msg.root.attributes.type) {
|
||||
case "chat":
|
||||
if (!msg.root.attributes.to) return;
|
||||
if (body.length >= 300) return;
|
||||
|
||||
let receiver = global.Clients.find(i => i.jid.split("/")[0] == msg.root.attributes.to);
|
||||
|
||||
if (!receiver) return;
|
||||
if (receiver.accountId == accountId) return;
|
||||
|
||||
receiver.client.send(XMLBuilder.create("message")
|
||||
.attribute("to", receiver.jid)
|
||||
.attribute("from", jid)
|
||||
.attribute("xmlns", "jabber:client")
|
||||
.attribute("type", "chat")
|
||||
.element("body", body).up().toString());
|
||||
return;
|
||||
|
||||
case "groupchat":
|
||||
if (!msg.root.attributes.to) return;
|
||||
if (body.length >= 300) return;
|
||||
|
||||
let roomName = msg.root.attributes.to.split("@")[0];
|
||||
|
||||
let MUC = global.MUCs[roomName];
|
||||
if (!MUC) return;
|
||||
|
||||
if (!MUC.members.find(i => i.accountId == accountId)) return;
|
||||
|
||||
MUC.members.forEach(member => {
|
||||
let ClientData = global.Clients.find(i => i.accountId == member.accountId);
|
||||
if (!ClientData) return;
|
||||
|
||||
ClientData.client.send(XMLBuilder.create("message")
|
||||
.attribute("to", ClientData.jid)
|
||||
.attribute("from", getMUCmember(roomName, displayName, accountId, resource))
|
||||
.attribute("xmlns", "jabber:client")
|
||||
.attribute("type", "groupchat")
|
||||
.element("body", body).up().toString());
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
if (isJSON(body)) {
|
||||
let bodyJSON = JSON.parse(body);
|
||||
|
||||
if (Array.isArray(bodyJSON)) return;
|
||||
if (typeof bodyJSON.type != "string") return;
|
||||
if (!msg.root.attributes.to) return;
|
||||
if (!msg.root.attributes.id) return;
|
||||
|
||||
sendXmppMessageToClient(jid, msg, body);
|
||||
}
|
||||
break;
|
||||
|
||||
case "presence":
|
||||
if (!clientExists) return Error(ws);
|
||||
|
||||
switch (msg.root.attributes.type) {
|
||||
case "unavailable":
|
||||
if (!msg.root.attributes.to) return;
|
||||
|
||||
if (msg.root.attributes.to.endsWith(`@muc.${domain}`) || msg.root.attributes.to.split("/")[0].endsWith(`@muc.${domain}`)) {
|
||||
if (!msg.root.attributes.to.toLowerCase().startsWith("party-")) return;
|
||||
|
||||
let roomName = msg.root.attributes.to.split("@")[0];
|
||||
|
||||
if (!global.MUCs[roomName]) return;
|
||||
|
||||
let memberIndex = global.MUCs[roomName].members.findIndex(i => i.accountId == accountId);
|
||||
if (memberIndex != -1) {
|
||||
global.MUCs[roomName].members.splice(memberIndex, 1);
|
||||
joinedMUCs.splice(joinedMUCs.indexOf(roomName), 1);
|
||||
}
|
||||
|
||||
ws.send(XMLBuilder.create("presence")
|
||||
.attribute("to", jid)
|
||||
.attribute("from", getMUCmember(roomName, displayName, accountId, resource))
|
||||
.attribute("xmlns", "jabber:client")
|
||||
.attribute("type", "unavailable")
|
||||
.element("x").attribute("xmlns", "http://jabber.org/protocol/muc#user")
|
||||
.element("item")
|
||||
.attribute("nick", getMUCmember(roomName, displayName, accountId, resource).replace(`${roomName}@muc.${domain}/`, ""))
|
||||
.attribute("jid", jid)
|
||||
.attribute("role", "none").up()
|
||||
.element("status").attribute("code", "110").up()
|
||||
.element("status").attribute("code", "100").up()
|
||||
.element("status").attribute("code", "170").up().up().toString());
|
||||
return;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
if (msg.root.children.find(i => i.name == "muc:x") || msg.root.children.find(i => i.name == "x")) {
|
||||
if (!msg.root.attributes.to) return;
|
||||
|
||||
let roomName = msg.root.attributes.to.split("@")[0];
|
||||
|
||||
if (!global.MUCs[roomName]) global.MUCs[roomName] = { members: [] };
|
||||
|
||||
if (global.MUCs[roomName].members.find(i => i.accountId == accountId)) return;
|
||||
|
||||
global.MUCs[roomName].members.push({ accountId: accountId });
|
||||
|
||||
joinedMUCs.push(roomName);
|
||||
|
||||
ws.send(XMLBuilder.create("presence")
|
||||
.attribute("to", jid)
|
||||
.attribute("from", getMUCmember(roomName, displayName, accountId, resource))
|
||||
.attribute("xmlns", "jabber:client")
|
||||
.element("x").attribute("xmlns", "http://jabber.org/protocol/muc#user")
|
||||
.element("item")
|
||||
.attribute("nick", getMUCmember(roomName, displayName, accountId, resource).replace(`${roomName}@muc.${domain}/`, ""))
|
||||
.attribute("jid", jid)
|
||||
.attribute("role", "participant")
|
||||
.attribute("affiliation", "none").up()
|
||||
.element("status").attribute("code", "110").up()
|
||||
.element("status").attribute("code", "100").up()
|
||||
.element("status").attribute("code", "170").up()
|
||||
.element("status").attribute("code", "201").up().up().toString());
|
||||
|
||||
global.MUCs[roomName].members.forEach(member => {
|
||||
let ClientData = global.Clients.find(i => i.accountId == member.accountId);
|
||||
if (!ClientData) return;
|
||||
|
||||
ws.send(XMLBuilder.create("presence")
|
||||
.attribute("from", getMUCmember(roomName, ClientData.displayName, ClientData.accountId, ClientData.resource))
|
||||
.attribute("to", jid)
|
||||
.attribute("xmlns", "jabber:client")
|
||||
.element("x")
|
||||
.attribute("xmlns", "http://jabber.org/protocol/muc#user")
|
||||
.element("item")
|
||||
.attribute("nick", getMUCmember(roomName, ClientData.displayName, ClientData.accountId, ClientData.resource).replace(`${roomName}@muc.${domain}/`, ""))
|
||||
.attribute("jid", ClientData.jid)
|
||||
.attribute("role", "participant")
|
||||
.attribute("affiliation", "none").up().up().toString());
|
||||
|
||||
if (accountId == ClientData.accountId) return;
|
||||
|
||||
ClientData.client.send(XMLBuilder.create("presence")
|
||||
.attribute("from", getMUCmember(roomName, displayName, accountId, resource))
|
||||
.attribute("to", ClientData.jid)
|
||||
.attribute("xmlns", "jabber:client")
|
||||
.element("x")
|
||||
.attribute("xmlns", "http://jabber.org/protocol/muc#user")
|
||||
.element("item")
|
||||
.attribute("nick", getMUCmember(roomName, displayName, accountId, resource).replace(`${roomName}@muc.${domain}/`, ""))
|
||||
.attribute("jid", jid)
|
||||
.attribute("role", "participant")
|
||||
.attribute("affiliation", "none").up().up().toString());
|
||||
});
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
let findStatus = msg.root.children.find(i => i.name == "status");
|
||||
|
||||
if (!findStatus || !findStatus.content) return;
|
||||
if (!isJSON(findStatus.content)) return;
|
||||
if (Array.isArray(JSON.parse(findStatus.content))) return;
|
||||
|
||||
let status = findStatus.content;
|
||||
let away = msg.root.children.find(i => i.name == "show") ? true : false;
|
||||
|
||||
await updatePresenceForFriends(ws, status, away, false);
|
||||
functions.getPresenceFromUser(accountId, accountId, false);
|
||||
break;
|
||||
}
|
||||
|
||||
if (!clientExists && !connectionClosed) {
|
||||
if (accountId && displayName && token && jid && ID && resource && Authenticated) {
|
||||
global.Clients.push({
|
||||
client: ws,
|
||||
accountId: accountId,
|
||||
displayName: displayName,
|
||||
token: token,
|
||||
jid: jid,
|
||||
resource: resource,
|
||||
lastPresenceUpdate: {
|
||||
away: false,
|
||||
status: "{}"
|
||||
}
|
||||
});
|
||||
|
||||
clientExists = true;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
ws.on('close', () => { connectionClosed = true; clientExists = false; RemoveClient(ws, joinedMUCs); });
|
||||
});
|
||||
|
||||
function Error(ws) {
|
||||
ws.send(XMLBuilder.create("close").attribute("xmlns", "urn:ietf:params:xml:ns:xmpp-framing").toString());
|
||||
ws.close();
|
||||
}
|
||||
|
||||
function RemoveClient(ws, joinedMUCs) {
|
||||
let clientIndex = global.Clients.findIndex(i => i.client == ws);
|
||||
let client = global.Clients[clientIndex];
|
||||
|
||||
if (clientIndex == -1) return;
|
||||
|
||||
let ClientStatus = JSON.parse(client.lastPresenceUpdate.status);
|
||||
|
||||
updatePresenceForFriends(ws, "{}", false, true);
|
||||
|
||||
global.Clients.splice(clientIndex, 1);
|
||||
|
||||
for (let roomName of joinedMUCs) {
|
||||
if (global.MUCs[roomName]) {
|
||||
let memberIndex = global.MUCs[roomName].members.findIndex(i => i.accountId == client.accountId);
|
||||
|
||||
if (memberIndex != -1) global.MUCs[roomName].members.splice(memberIndex, 1);
|
||||
}
|
||||
}
|
||||
|
||||
let partyId = "";
|
||||
|
||||
try {
|
||||
switch (true) {
|
||||
case (!ClientStatus.Properties): break;
|
||||
case (isObject(ClientStatus.Properties)): {
|
||||
for (let key in ClientStatus.Properties) {
|
||||
if (key.toLowerCase().startsWith("party.joininfo")) {
|
||||
if (isObject(ClientStatus.Properties[key])) partyId = ClientStatus.Properties[key].partyId;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch {}
|
||||
|
||||
if (partyId && typeof partyId == "string") {
|
||||
global.Clients.forEach(ClientData => {
|
||||
if (client.accountId == ClientData.accountId) return;
|
||||
|
||||
ClientData.client.send(XMLBuilder.create("message")
|
||||
.attribute("id", functions.MakeID().replace(/-/ig, "").toUpperCase())
|
||||
.attribute("from", client.jid)
|
||||
.attribute("xmlns", "jabber:client")
|
||||
.attribute("to", ClientData.jid)
|
||||
.element("body", JSON.stringify({
|
||||
"type": "com.epicgames.party.memberexited",
|
||||
"payload": {
|
||||
"partyId": partyId,
|
||||
"memberId": client.accountId,
|
||||
"wasKicked": false
|
||||
},
|
||||
"timestamp": new Date().toISOString()
|
||||
})).up().toString());
|
||||
});
|
||||
}
|
||||
|
||||
log.xmpp(`An xmpp client with the displayName ${client.displayName} has logged out.`);
|
||||
}
|
||||
|
||||
async function getPresenceFromFriends(ws, accountId, jid) {
|
||||
let friends = await Friends.findOne({ accountId: accountId }).lean();
|
||||
if (!friends) return;
|
||||
|
||||
let accepted = friends.list.accepted;
|
||||
|
||||
accepted.forEach(friend => {
|
||||
let ClientData = global.Clients.find(i => i.accountId == friend.accountId);
|
||||
if (!ClientData) return;
|
||||
|
||||
let xml = XMLBuilder.create("presence")
|
||||
.attribute("to", jid)
|
||||
.attribute("xmlns", "jabber:client")
|
||||
.attribute("from", ClientData.jid)
|
||||
.attribute("type", "available")
|
||||
|
||||
if (ClientData.lastPresenceUpdate.away) xml = xml.element("show", "away").up().element("status", ClientData.lastPresenceUpdate.status).up();
|
||||
else xml = xml.element("status", ClientData.lastPresenceUpdate.status).up();
|
||||
|
||||
ws.send(xml.toString());
|
||||
});
|
||||
}
|
||||
|
||||
async function updatePresenceForFriends(ws, body, away, offline) {
|
||||
let SenderIndex = global.Clients.findIndex(i => i.client == ws);
|
||||
let SenderData = global.Clients[SenderIndex];
|
||||
|
||||
if (SenderIndex == -1) return;
|
||||
|
||||
global.Clients[SenderIndex].lastPresenceUpdate.away = away;
|
||||
global.Clients[SenderIndex].lastPresenceUpdate.status = body;
|
||||
|
||||
let friends = await Friends.findOne({ accountId: SenderData.accountId });
|
||||
let accepted = friends.list.accepted;
|
||||
|
||||
accepted.forEach(friend => {
|
||||
let ClientData = global.Clients.find(i => i.accountId == friend.accountId);
|
||||
if (!ClientData) return;
|
||||
|
||||
let xml = XMLBuilder.create("presence")
|
||||
.attribute("to", ClientData.jid)
|
||||
.attribute("xmlns", "jabber:client")
|
||||
.attribute("from", SenderData.jid)
|
||||
.attribute("type", offline ? "unavailable" : "available");
|
||||
|
||||
if (away) xml = xml.element("show", "away").up().element("status", body).up();
|
||||
else xml = xml.element("status", body).up();
|
||||
|
||||
ClientData.client.send(xml.toString());
|
||||
});
|
||||
}
|
||||
|
||||
function sendXmppMessageToClient(senderJid, msg, body) {
|
||||
if (typeof body == "object") body = JSON.stringify(body);
|
||||
|
||||
let receiver = global.Clients.find(i => i.jid.split("/")[0] == msg.root.attributes.to || i.jid == msg.root.attributes.to);
|
||||
if (!receiver) return;
|
||||
|
||||
receiver.client.send(XMLBuilder.create("message")
|
||||
.attribute("from", senderJid)
|
||||
.attribute("id", msg.root.attributes.id)
|
||||
.attribute("to", receiver.jid)
|
||||
.attribute("xmlns", "jabber:client")
|
||||
.element("body", `${body}`).up().toString());
|
||||
}
|
||||
|
||||
function getMUCmember(roomName, displayName, accountId, resource) {
|
||||
return `${roomName}@muc.${domain}/${encodeURI(displayName)}:${accountId}:${resource}`;
|
||||
}
|
||||
|
||||
function isObject(value) {
|
||||
if (typeof value == "object" && !Array.isArray(value)) return true;
|
||||
else return false;
|
||||
}
|
||||
|
||||
function isJSON(str) {
|
||||
try {
|
||||
JSON.parse(str)
|
||||
} catch (err) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
Reference in New Issue
Block a user