├── .gitignore ├── LICENSE ├── README.md ├── build.gradle ├── gradle └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── gradlew.bat ├── jitpack.yml ├── settings.gradle └── src └── main └── java └── athena ├── Athena.java ├── AthenaImpl.java ├── account ├── Accounts.java ├── resource │ ├── Account.java │ ├── EpicGamesProfile.java │ ├── action │ │ └── FriendAcceptor.java │ ├── address │ │ └── AccountAddress.java │ ├── device │ │ ├── Device.java │ │ └── DeviceAuth.java │ ├── external │ │ ├── ExternalAuth.java │ │ └── ExternalAuthId.java │ └── password │ │ └── AccountPassword.java └── service │ └── AccountPublicService.java ├── authentication ├── FortniteAuthenticationManager.java ├── exchange │ └── Exchange.java ├── redirect │ └── Redirect.java ├── reputation │ └── Reputation.java ├── service │ └── AuthenticationService.java ├── session │ └── Session.java └── type │ ├── AuthClient.java │ └── GrantType.java ├── channels ├── Channels.java ├── resource │ ├── channel │ │ ├── Channel.java │ │ ├── badge │ │ │ └── Badge.java │ │ ├── member │ │ │ └── ChannelMember.java │ │ ├── message │ │ │ ├── ChannelMessage.java │ │ │ ├── MessageAttachedEntity.java │ │ │ └── entity │ │ │ │ └── EntityMediaType.java │ │ ├── metadata │ │ │ └── Metadata.java │ │ └── reaction │ │ │ └── MessageReaction.java │ ├── requests │ │ ├── channel │ │ │ ├── CreateChannel.java │ │ │ └── EditChannel.java │ │ ├── member │ │ │ └── AddMembers.java │ │ └── message │ │ │ └── SendMessage.java │ └── responses │ │ ├── channel │ │ ├── UserChannel.java │ │ ├── UserChannels.java │ │ └── message │ │ │ └── MostRecentMessage.java │ │ ├── dm │ │ └── DirectMessage.java │ │ └── message │ │ ├── GetMessage.java │ │ ├── Messages.java │ │ └── SentMessage.java └── service │ └── ChannelsPublicService.java ├── chat ├── FriendChat.java └── resource │ ├── BasicMessage.java │ └── listener │ └── IncomingMessageListener.java ├── eula ├── resource │ └── Eula.java └── service │ └── EulatrackingPublicService.java ├── events ├── Events.java ├── resource │ ├── download │ │ ├── event │ │ │ ├── FortniteEvent.java │ │ │ └── FortniteEventDownload.java │ │ ├── player │ │ │ ├── EventPlayer.java │ │ │ └── payouts │ │ │ │ └── PendingPayouts.java │ │ ├── template │ │ │ ├── EventTemplate.java │ │ │ ├── payout │ │ │ │ ├── EventPayout.java │ │ │ │ ├── EventPayoutTable.java │ │ │ │ └── rank │ │ │ │ │ └── EventPayoutRank.java │ │ │ ├── scoring │ │ │ │ ├── EventRewardTier.java │ │ │ │ └── EventScoringRule.java │ │ │ └── tiebreaker │ │ │ │ ├── EventTiebreakerFormula.java │ │ │ │ └── EventTiebreakerFormulaComponent.java │ │ └── window │ │ │ ├── FortniteEventWindow.java │ │ │ └── FortniteEventWindowMetadata.java │ ├── leaderboard │ │ ├── EventLeaderboard.java │ │ ├── entry │ │ │ └── EventLeaderboardEntry.java │ │ ├── session │ │ │ └── EventSession.java │ │ └── statistic │ │ │ └── LeaderboardStatistic.java │ └── player │ │ ├── PlayerTokenResponse.java │ │ └── TokenPlayer.java └── service │ └── EventsPublicService.java ├── exception ├── EpicGamesErrorException.java └── UnsupportedBuildException.java ├── fortnite ├── Fortnite.java ├── calendar │ ├── CalendarTimeline.java │ └── channel │ │ ├── CalendarChannel.java │ │ └── states │ │ └── ChannelState.java ├── creative │ ├── CreativeHistoryResponse.java │ ├── CreativeHistoryResult.java │ ├── data │ │ ├── CreativeLinkData.java │ │ └── CreativeMetadata.java │ └── matchmaking │ │ └── CreativeMatchmaking.java ├── receipt │ └── Receipt.java ├── service │ └── FortnitePublicService.java └── shop │ ├── Storefront.java │ ├── StorefrontCatalog.java │ ├── catalog │ └── CatalogEntry.java │ ├── gift │ └── CatalogGiftInfo.java │ ├── grant │ └── CatalogEntryItemGrant.java │ ├── price │ └── CatalogPrice.java │ └── requirement │ └── CatalogEntryRequirement.java ├── friend ├── Friends.java ├── resource │ ├── Friend.java │ ├── blocked │ │ └── Blocked.java │ ├── settings │ │ └── FriendSettings.java │ ├── summary │ │ ├── Profile.java │ │ ├── Summary.java │ │ └── types │ │ │ └── BasicFriend.java │ └── types │ │ ├── FriendDirection.java │ │ └── FriendStatus.java ├── service │ └── FriendsPublicService.java └── xmpp │ ├── annotation │ └── FriendEvent.java │ ├── event │ ├── AbstractFriendEvent.java │ └── events │ │ ├── FriendAbortedEvent.java │ │ ├── FriendAcceptedEvent.java │ │ ├── FriendDeletedEvent.java │ │ ├── FriendRejectedEvent.java │ │ └── FriendRequestEvent.java │ ├── listener │ └── FriendEventListener.java │ ├── type │ └── FriendType.java │ └── types │ ├── blocklist │ ├── BlockListEntry.java │ └── BlockListUpdate.java │ └── friend │ ├── FriendApiObject.java │ └── Friendship.java ├── groups ├── application │ ├── GroupApplication.java │ └── response │ │ └── GroupApplicationsResponse.java ├── group │ └── Group.java ├── invitation │ ├── GroupInvitation.java │ └── response │ │ └── GroupInvitationsResponse.java ├── membership │ ├── GroupMember.java │ ├── MembershipOf.java │ └── response │ │ └── GroupsMembershipResponse.java ├── paging │ └── Pageable.java ├── privacy │ └── GroupPrivacy.java ├── requests │ ├── creating │ │ └── CreateGroupRequest.java │ ├── invitation │ │ └── GroupInvitationRequest.java │ └── updating │ │ └── UpdateGroupRequest.java ├── response │ └── BaseGroupsResponse.java └── service │ └── GroupsService.java ├── interceptor └── InterceptorAction.java ├── party ├── Parties.java ├── resource │ ├── ClientParty.java │ ├── Party.java │ ├── assignment │ │ └── SquadAssignment.java │ ├── chat │ │ └── PartyChat.java │ ├── configuration │ │ ├── PartyConfiguration.java │ │ ├── privacy │ │ │ └── PartyPrivacy.java │ │ └── types │ │ │ └── Joinability.java │ ├── connection │ │ └── Connection.java │ ├── invite │ │ └── PartyInvitation.java │ ├── member │ │ ├── PartyMember.java │ │ ├── client │ │ │ └── ClientPartyMember.java │ │ ├── meta │ │ │ ├── PartyMemberMeta.java │ │ │ ├── assignments │ │ │ │ └── MemberSquadAssignmentRequest.java │ │ │ ├── banner │ │ │ │ └── AthenaBanner.java │ │ │ ├── battlepass │ │ │ │ └── BattlePass.java │ │ │ ├── challenges │ │ │ │ └── AssistedChallenge.java │ │ │ ├── cosmetic │ │ │ │ ├── CosmeticLoadout.java │ │ │ │ └── variant │ │ │ │ │ └── CosmeticVariant.java │ │ │ ├── emote │ │ │ │ └── FrontendEmote.java │ │ │ ├── hero │ │ │ │ └── CampaignHero.java │ │ │ ├── joinrequest │ │ │ │ └── JoinRequestUsers.java │ │ │ └── readiness │ │ │ │ └── GameReadiness.java │ │ └── role │ │ │ └── PartyRole.java │ ├── meta │ │ ├── PartyMeta.java │ │ └── invites │ │ │ └── PingOrInvitationMeta.java │ ├── notification │ │ ├── UndeliveredNotifications.java │ │ ├── interactions │ │ │ └── InteractionType.java │ │ └── regular │ │ │ └── PartyNotification.java │ ├── ping │ │ └── PartyPing.java │ ├── playlist │ │ └── PartyPlaylistData.java │ ├── requests │ │ ├── PartyCreateRequest.java │ │ ├── PartyInvitationRequest.java │ │ ├── PartyJoinRequest.java │ │ └── status │ │ │ └── PartyJoinStatus.java │ └── user │ │ └── UserPartyProfile.java ├── service │ └── PartyService.java └── xmpp │ ├── annotation │ └── PartyEvent.java │ └── event │ ├── invite │ ├── PartyInviteEvent.java │ └── PartyPingEvent.java │ ├── member │ ├── PartyMemberConnectedEvent.java │ ├── PartyMemberDisconnectedEvent.java │ ├── PartyMemberExpiredEvent.java │ ├── PartyMemberJoinedEvent.java │ ├── PartyMemberKickedEvent.java │ ├── PartyMemberLeftEvent.java │ ├── PartyMemberNewCaptainEvent.java │ ├── PartyMemberRequireConfirmationEvent.java │ └── PartyMemberUpdatedEvent.java │ └── party │ └── PartyUpdatedEvent.java ├── presence ├── Presences.java ├── resource │ ├── FortnitePresence.java │ ├── LastOnlineResponse.java │ ├── annotation │ │ └── PresenceEvent.java │ ├── filter │ │ └── PresenceFilter.java │ ├── listener │ │ └── FortnitePresenceListener.java │ └── subscription │ │ ├── PresenceSubscription.java │ │ └── SubscriptionSettings.java └── service │ └── PresencePublicService.java ├── social └── SocialBanPublicService.java ├── stats ├── StatisticsV2.java ├── resource │ ├── Statistic.java │ ├── StatisticValue.java │ ├── UnfilteredStatistic.java │ ├── leaderboard │ │ ├── LeaderboardEntry.java │ │ └── LeaderboardResponse.java │ ├── query │ │ ├── IndividualQueryResponse.java │ │ └── StatisticsQuery.java │ └── type │ │ └── StatisticType.java └── service │ └── StatsproxyPublicService.java ├── types ├── Input.java ├── Platform.java └── Region.java ├── util ├── event │ ├── EventFactory.java │ └── EventFactoryImpl.java ├── json │ ├── JsonFind.java │ ├── builder │ │ ├── JsonArrayBuilder.java │ │ └── JsonObjectBuilder.java │ ├── converters │ │ ├── InputConverter.java │ │ ├── InstantConverter.java │ │ ├── JidConverter.java │ │ ├── LastOnlineResponseConverter.java │ │ ├── PlatformConverter.java │ │ └── RegionConverter.java │ ├── fortnite │ │ ├── FortniteTypeAdapterFactory.java │ │ └── annotation │ │ │ ├── FortniteArray.java │ │ │ └── FortniteObject.java │ ├── hooks │ │ ├── Hooks.java │ │ └── PostDeserialize.java │ └── request │ │ ├── Request.java │ │ └── Requestable.java ├── reflection │ └── MethodInspector.java └── request │ ├── Requests.java │ └── Result.java └── xmpp └── XMPPConnectionManager.java /.gitignore: -------------------------------------------------------------------------------- 1 | .idea/ 2 | .gradle/ 3 | build/ 4 | out/ 5 | src/main/java/athena/main 6 | *.class 7 | gradlew 8 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2019 Vrekt 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Athena2 2 | Athena is a java library for interacting with the Fortnite/Epic Games API. 3 | 4 | # Features 5 | Check out all the features of Athena [here](https://github.com/Vrekt/Athena2/wiki/Features). 6 | 7 | This list is probably outdated but will give you a good idea of capabilities! 8 | 9 | # Examples 10 | 11 | ### Basic usage with only the API (Disables XMPP) 12 | ```java 13 | final var athena = Athena.athenaWithoutXMPP("username", "password"); 14 | ``` 15 | 16 | ### Full usage with XMPP. 17 | ```java 18 | final var athena = Athena.athenaWithXMPP("username", "password"); 19 | ``` 20 | 21 | These are only default configurations, if you want more customization then check out [this](https://github.com/Vrekt/Athena2/wiki/Authenticating). 22 | 23 | You can find party example code [here](https://github.com/Vrekt/Athena2/wiki/Parties). 24 | 25 | Check out other examples [here](https://github.com/Vrekt/Athena2/wiki/Examples) 26 | 27 | # Notes 28 | It is recommended that if you are going to create a bot that will be constantly re-logging from testing and other events then you should use Device Auth. After awhile, Epic will prevent you from logging in and you will have to complete a captcha. To get around this you can use Device Auth. The documentation can be found [here](https://github.com/Vrekt/Athena2/wiki/Authenticating) 29 | 30 | # Documentation 31 | The wiki will cover some stuff, but not all. Contact me on discord `vrekt#4387` for further help or questions. 32 | 33 | # TODO 34 | - Make events system better 35 | - Finish parties 36 | - General cleanup and QOL 37 | - GraphQL stuff 38 | - MCP 39 | - Fix shop 40 | 41 | # Credits 42 | - [Mix](https://github.com/MixV2/EpicResearch) 43 | - iXyles 44 | - [Terbau](https://github.com/Terbau/fortnitepy) 45 | - Bad_Mate | Pat 46 | - [Roberto](https://github.com/RobertoGraham) 47 | - [Kysune](https://github.com/SzymonLisowiec/node-epicgames-client) 48 | -------------------------------------------------------------------------------- /build.gradle: -------------------------------------------------------------------------------- 1 | plugins { 2 | id 'java' 3 | } 4 | 5 | group 'me.vrekt' 6 | version '1.0-SNAPSHOT' 7 | 8 | repositories { 9 | mavenCentral() 10 | } 11 | 12 | dependencies { 13 | compile group: 'com.google.flogger', name: 'flogger', version: '0.4' 14 | runtime group: 'com.google.flogger', name: 'flogger-system-backend', version: '0.4' 15 | compile group: 'org.apache.commons', name: 'commons-lang3', version: '3.8.1' 16 | 17 | implementation 'com.google.code.gson:gson:2.8.6' 18 | implementation("com.squareup.okhttp3:okhttp:4.2.1") 19 | compile group: 'com.squareup.okhttp3', name: 'okhttp-urlconnection', version: '4.2.2' 20 | implementation 'com.squareup.retrofit2:retrofit:2.6.2' 21 | compile group: 'com.squareup.retrofit2', name: 'converter-gson', version: '2.6.2' 22 | compile group: 'com.google.guava', name: 'guava', version: '28.1-jre' 23 | 24 | compile group: 'org.igniterealtime.smack', name: 'smack-tcp', version: '4.3.3' 25 | compile group: 'org.igniterealtime.smack', name: 'smack-extensions', version: '4.3.3' 26 | compile group: 'org.igniterealtime.smack', name: 'smack-java7', version: '4.3.3' 27 | } 28 | -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Vrekt/Athena/67101209f3c51a1de747abcb8ee3ffdbff8304ce/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | #Thu Oct 10 15:25:16 CDT 2019 2 | distributionBase=GRADLE_USER_HOME 3 | distributionPath=wrapper/dists 4 | zipStoreBase=GRADLE_USER_HOME 5 | zipStorePath=wrapper/dists 6 | distributionUrl=https\://services.gradle.org/distributions/gradle-4.10.3-all.zip 7 | -------------------------------------------------------------------------------- /gradlew.bat: -------------------------------------------------------------------------------- 1 | @if "%DEBUG%" == "" @echo off 2 | @rem ########################################################################## 3 | @rem 4 | @rem Gradle startup script for Windows 5 | @rem 6 | @rem ########################################################################## 7 | 8 | @rem Set local scope for the variables with windows NT shell 9 | if "%OS%"=="Windows_NT" setlocal 10 | 11 | set DIRNAME=%~dp0 12 | if "%DIRNAME%" == "" set DIRNAME=. 13 | set APP_BASE_NAME=%~n0 14 | set APP_HOME=%DIRNAME% 15 | 16 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 17 | set DEFAULT_JVM_OPTS= 18 | 19 | @rem Find java.exe 20 | if defined JAVA_HOME goto findJavaFromJavaHome 21 | 22 | set JAVA_EXE=java.exe 23 | %JAVA_EXE% -version >NUL 2>&1 24 | if "%ERRORLEVEL%" == "0" goto init 25 | 26 | echo. 27 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 28 | echo. 29 | echo Please set the JAVA_HOME variable in your environment to match the 30 | echo location of your Java installation. 31 | 32 | goto fail 33 | 34 | :findJavaFromJavaHome 35 | set JAVA_HOME=%JAVA_HOME:"=% 36 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe 37 | 38 | if exist "%JAVA_EXE%" goto init 39 | 40 | echo. 41 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 42 | echo. 43 | echo Please set the JAVA_HOME variable in your environment to match the 44 | echo location of your Java installation. 45 | 46 | goto fail 47 | 48 | :init 49 | @rem Get command-line arguments, handling Windows variants 50 | 51 | if not "%OS%" == "Windows_NT" goto win9xME_args 52 | 53 | :win9xME_args 54 | @rem Slurp the command line arguments. 55 | set CMD_LINE_ARGS= 56 | set _SKIP=2 57 | 58 | :win9xME_args_slurp 59 | if "x%~1" == "x" goto execute 60 | 61 | set CMD_LINE_ARGS=%* 62 | 63 | :execute 64 | @rem Setup the command line 65 | 66 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar 67 | 68 | @rem Execute Gradle 69 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% 70 | 71 | :end 72 | @rem End local scope for the variables with windows NT shell 73 | if "%ERRORLEVEL%"=="0" goto mainEnd 74 | 75 | :fail 76 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of 77 | rem the _cmd.exe /c_ return code! 78 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 79 | exit /b 1 80 | 81 | :mainEnd 82 | if "%OS%"=="Windows_NT" endlocal 83 | 84 | :omega 85 | -------------------------------------------------------------------------------- /jitpack.yml: -------------------------------------------------------------------------------- 1 | jdk: openjdk11 -------------------------------------------------------------------------------- /settings.gradle: -------------------------------------------------------------------------------- 1 | rootProject.name = 'Athena2' 2 | 3 | -------------------------------------------------------------------------------- /src/main/java/athena/account/resource/action/FriendAcceptor.java: -------------------------------------------------------------------------------- 1 | package athena.account.resource.action; 2 | 3 | import athena.friend.resource.summary.Profile; 4 | 5 | import java.util.function.Consumer; 6 | 7 | /** 8 | * An interface that manages accepting friends. 9 | */ 10 | public interface FriendAcceptor { 11 | 12 | /** 13 | * Wait {@code seconds} for the friend request before timing out. 14 | * 15 | * @param seconds the time to wait. 16 | */ 17 | FriendAcceptor waitUntil(int seconds); 18 | 19 | /** 20 | * After the wait time from {@code waitUntil} is reached without a friend request the provided {@code run} is called. 21 | * 22 | * @param run the action to run. 23 | */ 24 | FriendAcceptor onExpired(Runnable run); 25 | 26 | /** 27 | * Once the friend request is accepted the {@code profileConsumer} will be accepted. 28 | * 29 | * @param profileConsumer the consumer 30 | */ 31 | FriendAcceptor onAccepted(Consumer profileConsumer); 32 | 33 | } 34 | -------------------------------------------------------------------------------- /src/main/java/athena/account/resource/address/AccountAddress.java: -------------------------------------------------------------------------------- 1 | package athena.account.resource.address; 2 | 3 | import com.google.gson.annotations.SerializedName; 4 | 5 | /** 6 | * Represents an address inside an account. 7 | * @author Vrekt 8 | */ 9 | public final class AccountAddress { 10 | 11 | /** 12 | * The account ID. 13 | */ 14 | @SerializedName("id") 15 | private String accountId; 16 | 17 | /** 18 | * The address information. 19 | */ 20 | private String line1, line2, city, region, postalCode, country; 21 | /** 22 | * {@code true} if this address is the default. 23 | */ 24 | private boolean defaultAddress; 25 | 26 | /** 27 | * @return the account ID. 28 | */ 29 | public String accountId() { 30 | return accountId; 31 | } 32 | 33 | /** 34 | * @return the line 1 address. 35 | */ 36 | public String line1() { 37 | return line1; 38 | } 39 | 40 | /** 41 | * @return the line 2 address. 42 | */ 43 | public String line2() { 44 | return line2; 45 | } 46 | 47 | /** 48 | * @return the city 49 | */ 50 | public String city() { 51 | return city; 52 | } 53 | 54 | /** 55 | * @return the region 56 | */ 57 | public String region() { 58 | return region; 59 | } 60 | 61 | /** 62 | * @return the postal code. 63 | */ 64 | public String postalCode() { 65 | return postalCode; 66 | } 67 | 68 | /** 69 | * @return the country 70 | */ 71 | public String country() { 72 | return country; 73 | } 74 | 75 | /** 76 | * @return {@code true} if this address is the default. 77 | */ 78 | public boolean defaultAddress() { 79 | return defaultAddress; 80 | } 81 | } 82 | -------------------------------------------------------------------------------- /src/main/java/athena/account/resource/device/Device.java: -------------------------------------------------------------------------------- 1 | package athena.account.resource.device; 2 | 3 | /** 4 | * Represents device info. 5 | */ 6 | public final class Device { 7 | 8 | /** 9 | * Type, ex: "LGE" 10 | * Model, ex: "LG-H918" 11 | * OS:, ex: "9.0" 12 | */ 13 | private String type, model, os; 14 | 15 | public Device(String type, String model, String os) { 16 | this.type = type; 17 | this.model = model; 18 | this.os = os; 19 | } 20 | 21 | /** 22 | * @return type/manufacturer 23 | */ 24 | public String type() { 25 | return type; 26 | } 27 | 28 | /** 29 | * @return device model 30 | */ 31 | public String model() { 32 | return model; 33 | } 34 | 35 | /** 36 | * @return device OS. 37 | */ 38 | public String os() { 39 | return os; 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /src/main/java/athena/account/resource/device/DeviceAuth.java: -------------------------------------------------------------------------------- 1 | package athena.account.resource.device; 2 | 3 | import java.time.Instant; 4 | 5 | /** 6 | * Represents a device-auth. 7 | */ 8 | public final class DeviceAuth { 9 | 10 | /** 11 | * Device ID, account ID, secret and user agent registered with. 12 | * Secret is used to login with device_auth, its only present after creating one - not retrieving. 13 | */ 14 | private String deviceId, accountId, secret, userAgent; 15 | 16 | /** 17 | * The device info of this auth. 18 | */ 19 | private Device deviceInfo; 20 | 21 | /** 22 | * Location, IP and created time of this device-auth. 23 | */ 24 | private Created created; 25 | 26 | /** 27 | * @return the device ID. 28 | */ 29 | public String deviceId() { 30 | return deviceId; 31 | } 32 | 33 | /** 34 | * @return the account ID. 35 | */ 36 | public String accountId() { 37 | return accountId; 38 | } 39 | 40 | /** 41 | * @return the secret, only present after the response from creating a device auth. 42 | */ 43 | public String secret() { 44 | return secret; 45 | } 46 | 47 | /** 48 | * @return the user-agent. 49 | */ 50 | public String userAgent() { 51 | return userAgent; 52 | } 53 | 54 | /** 55 | * @return type/manufacturer 56 | */ 57 | public String type() { 58 | return deviceInfo.type(); 59 | } 60 | 61 | /** 62 | * @return device model 63 | */ 64 | public String model() { 65 | return deviceInfo.model(); 66 | } 67 | 68 | /** 69 | * @return device OS. 70 | */ 71 | public String os() { 72 | return deviceInfo.os(); 73 | } 74 | 75 | /** 76 | * @return the location of who created this device-auth. 77 | */ 78 | public String location() { 79 | return created.location; 80 | } 81 | 82 | /** 83 | * @return the IP address of who created this device-auth. 84 | */ 85 | public String ipAddress() { 86 | return created.ipAddress; 87 | } 88 | 89 | /** 90 | * @return when this device-auth was created. 91 | */ 92 | public Instant created() { 93 | return created.dateTime; 94 | } 95 | 96 | /** 97 | * @return the device info 98 | */ 99 | public Device deviceInfo() { 100 | return deviceInfo; 101 | } 102 | 103 | /** 104 | * Information about when this device-auth was created. 105 | */ 106 | private static final class Created { 107 | 108 | /** 109 | * Location and IP. 110 | */ 111 | private String location, ipAddress; 112 | /** 113 | * When it was created. 114 | */ 115 | private Instant dateTime; 116 | 117 | } 118 | 119 | } 120 | -------------------------------------------------------------------------------- /src/main/java/athena/account/resource/external/ExternalAuth.java: -------------------------------------------------------------------------------- 1 | package athena.account.resource.external; 2 | 3 | import athena.types.Platform; 4 | 5 | import java.util.List; 6 | import java.util.Optional; 7 | 8 | /** 9 | * Holds data about external auths, the platform, id and display name. 10 | */ 11 | public final class ExternalAuth { 12 | 13 | /** 14 | * Platform type 15 | */ 16 | private Platform type; 17 | /** 18 | * "nintendo", 19 | * "XXX" (only present for PSN) 20 | * "psn_user_id, xuid, nsa_id" 21 | * "accountId", 22 | * external display name 23 | */ 24 | private String externalAuthId, externalAuthIdType, accountId, externalDisplayName; 25 | /** 26 | * List of external auth IDs. 27 | * { 28 | * "id": "xxx", 29 | * "type": "nintendo_id" 30 | * }, 31 | * { 32 | * "id": "xxx", 33 | * "type": "nsa_id" 34 | * } 35 | */ 36 | private List authIds; 37 | 38 | /** 39 | * Get a {@link ExternalAuthId} by the type. 40 | * 41 | * @param type the type 42 | * @return a {@link Optional} containing the type if found. 43 | */ 44 | public Optional getByType(String type) { 45 | return authIds.stream().filter(externalAuthId -> externalAuthId.type().equalsIgnoreCase(type)).findAny(); 46 | } 47 | 48 | /** 49 | * @return the external auth ID type. 50 | */ 51 | public String externalAuthIdType() { 52 | return externalAuthIdType; 53 | } 54 | 55 | /** 56 | * @return the account ID. 57 | */ 58 | public String accountId() { 59 | return accountId; 60 | } 61 | 62 | /** 63 | * @return the platform of this external auth 64 | */ 65 | public Platform platform() { 66 | return type; 67 | } 68 | 69 | /** 70 | * @return the ID of this external auth 71 | */ 72 | public String externalAuthId() { 73 | if (externalAuthId != null) return externalAuthId; 74 | final var authId = getByType(platform().primaryName()); 75 | if (authId.isEmpty()) return null; 76 | return authId.get().id(); 77 | } 78 | 79 | /** 80 | * @return the external display name 81 | */ 82 | public String externalDisplayName() { 83 | return externalDisplayName; 84 | } 85 | 86 | /** 87 | * @return the list of authIds. 88 | */ 89 | public List authIds() { 90 | return authIds; 91 | } 92 | 93 | } 94 | -------------------------------------------------------------------------------- /src/main/java/athena/account/resource/external/ExternalAuthId.java: -------------------------------------------------------------------------------- 1 | package athena.account.resource.external; 2 | 3 | /** 4 | * Represents an external auth ID. 5 | * * { 6 | * * "id": "xxx", 7 | * * "type": "nintendo_id" 8 | * * }, 9 | * * { 10 | * * "id": "xxx", 11 | * * "type": "nsa_id" 12 | * * } 13 | */ 14 | public final class ExternalAuthId { 15 | 16 | /** 17 | * The ID of the external auth and the type. 18 | */ 19 | private String id, type; 20 | 21 | /** 22 | * @return the ID. 23 | */ 24 | public String id() { 25 | return id; 26 | } 27 | 28 | /** 29 | * @return the type 30 | */ 31 | public String type() { 32 | return type; 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /src/main/java/athena/account/resource/password/AccountPassword.java: -------------------------------------------------------------------------------- 1 | package athena.account.resource.password; 2 | 3 | /** 4 | * Represents a request to change an account password. 5 | * @author Vrekt, Armisto 6 | */ 7 | public final class AccountPassword { 8 | 9 | /** 10 | * The current password and then the new one to set it to. 11 | */ 12 | private final String currentPassword, password; 13 | 14 | public AccountPassword(String currentPassword, String password) { 15 | this.currentPassword = currentPassword; 16 | this.password = password; 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /src/main/java/athena/authentication/exchange/Exchange.java: -------------------------------------------------------------------------------- 1 | package athena.authentication.exchange; 2 | 3 | /** 4 | * Represents the exchange response. 5 | */ 6 | public final class Exchange { 7 | 8 | /** 9 | * The exchange code; 10 | */ 11 | private String code; 12 | 13 | /** 14 | * @return the exchange code 15 | */ 16 | public String code() { 17 | return code; 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /src/main/java/athena/authentication/redirect/Redirect.java: -------------------------------------------------------------------------------- 1 | package athena.authentication.redirect; 2 | 3 | /** 4 | * Represents the redirect response. 5 | */ 6 | public final class Redirect { 7 | 8 | /** 9 | * The redirect URL and SID. 10 | */ 11 | private String redirectUrl, sid; 12 | 13 | /** 14 | * @return the redirect URL. 15 | */ 16 | public String redirectUrl() { 17 | return redirectUrl; 18 | } 19 | 20 | /** 21 | * @return the SID, sometimes {@code null} 22 | */ 23 | public String sid() { 24 | return sid; 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /src/main/java/athena/authentication/reputation/Reputation.java: -------------------------------------------------------------------------------- 1 | package athena.authentication.reputation; 2 | 3 | import com.google.gson.JsonObject; 4 | import com.google.gson.annotations.SerializedName; 5 | 6 | /** 7 | * Represents the reputation response. 8 | */ 9 | public final class Reputation { 10 | 11 | /** 12 | * The verdict. 13 | */ 14 | private String verdict; 15 | 16 | /** 17 | * The captcha data. 18 | * "arkose_data":{"blob":"xxx"}} 19 | */ 20 | @SerializedName("arkose_data") 21 | private JsonObject arkoseData; 22 | 23 | /** 24 | * @return the verdict 25 | */ 26 | public String verdict() { 27 | return verdict; 28 | } 29 | 30 | /** 31 | * @return the arkose data. 32 | */ 33 | public JsonObject arkoseData() { 34 | return arkoseData; 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /src/main/java/athena/authentication/service/AuthenticationService.java: -------------------------------------------------------------------------------- 1 | package athena.authentication.service; 2 | 3 | import athena.authentication.exchange.Exchange; 4 | import athena.authentication.redirect.Redirect; 5 | import athena.authentication.reputation.Reputation; 6 | import okhttp3.FormBody; 7 | import retrofit2.Call; 8 | import retrofit2.http.*; 9 | 10 | /** 11 | * Used for authentication 12 | */ 13 | public interface AuthenticationService { 14 | 15 | /** 16 | * Base URL 17 | */ 18 | String BASE_URL = "https://www.epicgames.com/id/api/"; 19 | 20 | /** 21 | * GETs on csrf, retrieving the XSRF-TOKEN. 22 | * 23 | * @return Void 24 | */ 25 | @GET("csrf") 26 | Call csrf(); 27 | 28 | /** 29 | * Gets the reputation. 30 | * 31 | * @param xsrfToken the XSRF token 32 | * @return the {@link Reputation} 33 | */ 34 | @GET("reputation") 35 | Call reputation(@Header("x-xsrf-token") String xsrfToken); 36 | 37 | /** 38 | * Login using 2FA. 39 | * 40 | * @param xsrfToken the XSRF token 41 | * @param body the form 42 | * @return Void 43 | */ 44 | @POST("login/mfa") 45 | Call loginMfa(@Header("x-xsrf-token") String xsrfToken, @Query("client_id") String clientId, @Query("response_type") String responseType, @Body FormBody body); 46 | 47 | /** 48 | * Login using the specified client ID and response type. 49 | * 50 | * @param xsrfToken the XSRF token 51 | * @param clientId the client ID. {@link athena.authentication.type.AuthClient} 52 | * @param responseType the response type, usually "code" 53 | * @param body the form 54 | * @return Void 55 | */ 56 | @POST("login") 57 | Call login(@Header("x-xsrf-token") String xsrfToken, @Query("client_id") String clientId, @Query("response_type") String responseType, @Body FormBody body); 58 | 59 | /** 60 | * Retrieve the exchange code. 61 | * 62 | * @param xsrfToken the XSRF token 63 | * @return the {@link Exchange} 64 | */ 65 | @POST("exchange/generate") 66 | Call exchange(@Header("x-xsrf-token") String xsrfToken); 67 | 68 | /** 69 | * Redirect, used for kairos. 70 | * 71 | * @param xsrfToken the token 72 | * @param responseType the response type, usually "code" 73 | * @param clientId the client ID. {@link athena.authentication.type.AuthClient} 74 | * @return the {@link Redirect} 75 | */ 76 | @GET("redirect") 77 | Call redirect(@Header("x-xsrf-token") String xsrfToken, @Query("responseType") String responseType, @Query("clientId") String clientId); 78 | 79 | } 80 | -------------------------------------------------------------------------------- /src/main/java/athena/authentication/session/Session.java: -------------------------------------------------------------------------------- 1 | package athena.authentication.session; 2 | 3 | import com.google.gson.annotations.SerializedName; 4 | 5 | import java.time.Instant; 6 | 7 | /** 8 | * Represents an authenticated session. 9 | */ 10 | public final class Session { 11 | 12 | @SerializedName("access_token") 13 | private String accessToken; 14 | @SerializedName("refresh_token") 15 | private String refreshToken; 16 | @SerializedName("account_id") 17 | private String accountId; 18 | @SerializedName("expires_at") 19 | private Instant accessTokenExpiresAt; 20 | @SerializedName("refresh_expires_at") 21 | private Instant refreshTokenExpiresAt; 22 | @SerializedName("client_id") 23 | private String clientId; 24 | @SerializedName("in_app_id") 25 | private String inAppId; 26 | @SerializedName("device_id") 27 | private String deviceId; 28 | 29 | /** 30 | * @return the access token. 31 | */ 32 | public String accessToken() { 33 | return accessToken; 34 | } 35 | 36 | /** 37 | * @return the refresh token. 38 | */ 39 | public String refreshToken() { 40 | return refreshToken; 41 | } 42 | 43 | /** 44 | * @return the account ID this session belongs to. 45 | */ 46 | public String accountId() { 47 | return accountId; 48 | } 49 | 50 | /** 51 | * @return when the access token expires. 52 | */ 53 | public Instant accessTokenExpiresAt() { 54 | return accessTokenExpiresAt; 55 | } 56 | 57 | /** 58 | * @return when the refresh token expires. 59 | */ 60 | public Instant refreshTokenExpiresAt() { 61 | return refreshTokenExpiresAt; 62 | } 63 | 64 | /** 65 | * @return the client ID. 66 | */ 67 | public String clientId() { 68 | return clientId; 69 | } 70 | 71 | /** 72 | * @return the in-app ID. 73 | */ 74 | public String inAppId() { 75 | return inAppId; 76 | } 77 | 78 | /** 79 | * @return the device ID. 80 | */ 81 | public String deviceId() { 82 | return deviceId; 83 | } 84 | } 85 | -------------------------------------------------------------------------------- /src/main/java/athena/authentication/type/AuthClient.java: -------------------------------------------------------------------------------- 1 | package athena.authentication.type; 2 | 3 | import java.util.Base64; 4 | 5 | /** 6 | * A collection of client IDs and secret tokens that are used for authentication. 7 | * Allows access to certain services only accessible through a certain client. 8 | * 9 | * @author Vrekt, mix 10 | */ 11 | public enum AuthClient { 12 | 13 | FORTNITE_PC_GAME_CLIENT("ec684b8c687f479fadea3cb2ad83f5c6", "e1f31c211f28413186262d37a13fc84d"), 14 | FORTNITE_IOS_GAME_CLIENT("3446cd72694c4a4485d81b77adbb2141", "9209d4a5e25a457fb9b07489d313b41a"), 15 | FORTNITE_ANDROID_GAME_CLIENT("3f69e56c7649492c8cc29f1af08a8a12", "b51ee9cb12234f50a69efa67ef53812e"), 16 | FORTNITE_CHINA_GAME_CLIENT("efe3cbb938804c74b20e109d0efc1548", "6e31bdbae6a44f258474733db74f39ba"), 17 | KAIROS_PC_CLIENT("5b685653b9904c1d92495ee8859dcb00", "7Q2mcmneyuvPmoRYfwM7gfErA6iUjhXr"), 18 | KAIROS_IOS_CLIENT("61d2f70175e84a6bba80a5089e597e1c", "FbiZv3wbiKpvVKrAeMxiR6WhxZWVbrvA"), 19 | KAIROS_ANDROID_CLIENT("0716a69cb8b2422fbb2a8b0879501471", "cGthdfG68tyE7M3ZHMu3sXUBwqhibKFp"); 20 | 21 | private String clientId; 22 | private String secret; 23 | 24 | AuthClient(String clientId, String secret) { 25 | this.clientId = clientId; 26 | this.secret = secret; 27 | } 28 | 29 | public String clientId() { 30 | return this.clientId; 31 | } 32 | 33 | public String secret() { 34 | return this.secret; 35 | } 36 | 37 | /** 38 | * Get a valid authentication token. 39 | * 40 | * @return authentication token that can be used on account service. 41 | */ 42 | public String asToken() { 43 | String plainToken = this.clientId + ":" + this.secret; 44 | return new String(Base64.getEncoder().encode(plainToken.getBytes())); 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /src/main/java/athena/authentication/type/GrantType.java: -------------------------------------------------------------------------------- 1 | package athena.authentication.type; 2 | 3 | /** 4 | * list of supported grant types supported by Athena. 5 | */ 6 | public enum GrantType { 7 | 8 | EXCHANGE_CODE, REFRESH_TOKEN, DEVICE_AUTH, AUTHORIZATION_CODE 9 | 10 | } 11 | -------------------------------------------------------------------------------- /src/main/java/athena/channels/Channels.java: -------------------------------------------------------------------------------- 1 | package athena.channels; 2 | 3 | /** 4 | * TODO: {@link athena.channels.service.ChannelsPublicService} 5 | */ 6 | public final class Channels { 7 | } 8 | -------------------------------------------------------------------------------- /src/main/java/athena/channels/resource/channel/Channel.java: -------------------------------------------------------------------------------- 1 | package athena.channels.resource.channel; 2 | 3 | import athena.channels.resource.channel.badge.Badge; 4 | import athena.channels.resource.channel.member.ChannelMember; 5 | 6 | import java.util.List; 7 | 8 | /** 9 | * Represents a channel. 10 | */ 11 | public final class Channel { 12 | /** 13 | * The channel ID and name and number of unread messages? 14 | */ 15 | private String channelId, name, unreadCount; 16 | /** 17 | * The badge of this channel. 18 | */ 19 | private Badge badge; 20 | /** 21 | * The badge colors. 22 | */ 23 | private List badgeColor; 24 | /** 25 | * List of members in this channel. 26 | */ 27 | private List members; 28 | 29 | /** 30 | * @return the ID of this channel. 31 | */ 32 | public String channelId() { 33 | return channelId; 34 | } 35 | 36 | /** 37 | * @return the name of this channel. 38 | */ 39 | public String name() { 40 | return name; 41 | } 42 | 43 | /** 44 | * @return the badge of this channel. 45 | */ 46 | public Badge badge() { 47 | return badge; 48 | } 49 | 50 | /** 51 | * @return the badge colors. 52 | */ 53 | public List badgeColor() { 54 | return badgeColor; 55 | } 56 | 57 | /** 58 | * @return list of members in this channel. 59 | */ 60 | public List members() { 61 | return members; 62 | } 63 | 64 | /** 65 | * @return number of unread messages? 66 | */ 67 | public int unreadCount() { 68 | return Integer.parseInt(unreadCount); 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /src/main/java/athena/channels/resource/channel/badge/Badge.java: -------------------------------------------------------------------------------- 1 | package athena.channels.resource.channel.badge; 2 | 3 | /** 4 | * Badges for channels. 5 | * 6 | * @author Armisto 7 | */ 8 | public enum Badge { 9 | ace, 10 | arm, 11 | bush, 12 | clown, 13 | crown, 14 | crab, 15 | dog, 16 | donut, 17 | finger, 18 | ghost, 19 | mushroom, 20 | ninja, 21 | pot, 22 | potato, 23 | radio, 24 | rainbow, 25 | seal, 26 | skele, 27 | unicorn 28 | } 29 | -------------------------------------------------------------------------------- /src/main/java/athena/channels/resource/channel/member/ChannelMember.java: -------------------------------------------------------------------------------- 1 | package athena.channels.resource.channel.member; 2 | 3 | /** 4 | * Represents a member inside a {@link athena.channels.resource.channel.Channel} 5 | */ 6 | public final class ChannelMember { 7 | 8 | /** 9 | * The account ID, displayName and status of this member. 10 | * NOTE: Status is not always given, only when querying for a {@link athena.channels.resource.channel.Channel}, 11 | * other times it will be {@code null} 12 | */ 13 | private String accountId, displayName, status; 14 | 15 | /** 16 | * @return the account ID of this member. 17 | */ 18 | public String accountId() { 19 | return accountId; 20 | } 21 | 22 | /** 23 | * @return the display name of this member. 24 | */ 25 | public String displayName() { 26 | return displayName; 27 | } 28 | 29 | /** 30 | * @return the status of this member, or {@code null} 31 | */ 32 | public String status() { 33 | return status; 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /src/main/java/athena/channels/resource/channel/message/ChannelMessage.java: -------------------------------------------------------------------------------- 1 | package athena.channels.resource.channel.message; 2 | 3 | import athena.channels.resource.channel.reaction.MessageReaction; 4 | 5 | import java.time.Instant; 6 | import java.util.List; 7 | 8 | /** 9 | * Represents a message in a {@link athena.channels.resource.channel.Channel} 10 | */ 11 | public final class ChannelMessage { 12 | 13 | /** 14 | * The id of the message 15 | * the container type, ex: 'channel' 16 | * the channel/container ID. 17 | * the account ID of who sent the message 18 | * the message 19 | * the timestamp, unix epoch milli 20 | */ 21 | private String id, containerType, containerId, accountId, message, timestamp; 22 | /** 23 | * List of reactions 24 | */ 25 | private List reactions; 26 | /** 27 | * List of attached entities. 28 | */ 29 | private List entities; 30 | 31 | /** 32 | * @return the message ID. 33 | */ 34 | public String id() { 35 | return id; 36 | } 37 | 38 | /** 39 | * @return the container type, ex: 'channel' 40 | */ 41 | public String containerType() { 42 | return containerType; 43 | } 44 | 45 | /** 46 | * @return the channel/container ID. 47 | */ 48 | public String containerId() { 49 | return containerId; 50 | } 51 | 52 | /** 53 | * @return the account ID of who sent the message. 54 | */ 55 | public String accountId() { 56 | return accountId; 57 | } 58 | 59 | /** 60 | * @return the message. 61 | */ 62 | public String message() { 63 | return message; 64 | } 65 | 66 | /** 67 | * @return timestamp of when the message was sent. 68 | */ 69 | public Instant timestamp() { 70 | return Instant.ofEpochMilli(Long.parseLong(timestamp)); 71 | } 72 | 73 | /** 74 | * @return list of reactions 75 | */ 76 | public List reactions() { 77 | return reactions; 78 | } 79 | 80 | /** 81 | * @return list of entities. 82 | */ 83 | public List entities() { 84 | return entities; 85 | } 86 | } 87 | -------------------------------------------------------------------------------- /src/main/java/athena/channels/resource/channel/message/MessageAttachedEntity.java: -------------------------------------------------------------------------------- 1 | package athena.channels.resource.channel.message; 2 | 3 | import athena.channels.resource.channel.message.entity.EntityMediaType; 4 | 5 | import java.util.Map; 6 | 7 | /** 8 | * An entity meant to be attached to a message. 9 | * 10 | * @author Vrekt, Armisto 11 | */ 12 | public final class MessageAttachedEntity { 13 | 14 | /** 15 | * The tag? 16 | * The title of this entity? 17 | * The description of this entity? 18 | * The content type, not sure why this is here also since we have {@code type} 19 | * The file-name. 20 | */ 21 | private String tag, title, description, contentType, filename; 22 | /** 23 | * The media type. 24 | */ 25 | private EntityMediaType type; 26 | /** 27 | * List of metadata associated with this entity. 28 | */ 29 | private Map metadata; 30 | 31 | /** 32 | * Initialize this entity. 33 | * 34 | * @param tag the tag 35 | * @param title the title 36 | * @param description the description 37 | * @param contentType the content-type 38 | * @param filename the file-name 39 | * @param type the media-type 40 | * @param metadata the metadata. 41 | */ 42 | public MessageAttachedEntity(String tag, String title, String description, String contentType, String filename, EntityMediaType type, Map metadata) { 43 | this.tag = tag; 44 | this.title = title; 45 | this.description = description; 46 | this.contentType = contentType; 47 | this.filename = filename; 48 | this.type = type; 49 | this.metadata = metadata; 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /src/main/java/athena/channels/resource/channel/message/entity/EntityMediaType.java: -------------------------------------------------------------------------------- 1 | package athena.channels.resource.channel.message.entity; 2 | 3 | /** 4 | * The media-type of an entity. 5 | * TODO: Incorrect 6 | */ 7 | public enum EntityMediaType { 8 | website, 9 | audio, 10 | video, 11 | image, 12 | gif, 13 | user, 14 | highlight, 15 | System, 16 | File, 17 | } 18 | -------------------------------------------------------------------------------- /src/main/java/athena/channels/resource/channel/metadata/Metadata.java: -------------------------------------------------------------------------------- 1 | package athena.channels.resource.channel.metadata; 2 | 3 | /** 4 | * A key/value pair system for storing metadata in entities and messages. 5 | */ 6 | public final class Metadata { 7 | 8 | /** 9 | * K/V 10 | */ 11 | private String key, value; 12 | 13 | public Metadata(String key, String value) { 14 | this.key = key; 15 | this.value = value; 16 | } 17 | 18 | /** 19 | * @return the key. 20 | */ 21 | public String key() { 22 | return key; 23 | } 24 | 25 | /** 26 | * @return the value. 27 | */ 28 | public String value() { 29 | return value; 30 | } 31 | 32 | } 33 | -------------------------------------------------------------------------------- /src/main/java/athena/channels/resource/channel/reaction/MessageReaction.java: -------------------------------------------------------------------------------- 1 | package athena.channels.resource.channel.reaction; 2 | 3 | import java.util.List; 4 | 5 | /** 6 | * Represents a {@link athena.channels.resource.channel.message.ChannelMessage} reaction. 7 | */ 8 | public final class MessageReaction { 9 | 10 | /** 11 | * The reaction. 12 | */ 13 | private String reaction; 14 | /** 15 | * List of users who reacted? 16 | */ 17 | private List users; 18 | 19 | /** 20 | * @return the reaction 21 | */ 22 | public String reaction() { 23 | return reaction; 24 | } 25 | 26 | /** 27 | * @return List of users who reacted? 28 | */ 29 | public List users() { 30 | return users; 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /src/main/java/athena/channels/resource/requests/channel/CreateChannel.java: -------------------------------------------------------------------------------- 1 | package athena.channels.resource.requests.channel; 2 | 3 | import athena.channels.resource.channel.badge.Badge; 4 | 5 | import java.util.List; 6 | 7 | /** 8 | * A request used to create channels. 9 | * 10 | * @author Vrekt, Armisto 11 | */ 12 | public final class CreateChannel { 13 | 14 | /** 15 | * The name of the channel. 16 | */ 17 | private String name; 18 | /** 19 | * The channel badge. 20 | */ 21 | private Badge badge; 22 | /** 23 | * List of badge colors. 24 | */ 25 | private List badgeColor; 26 | /** 27 | * List of channel members by account ID. 28 | */ 29 | private List members; 30 | 31 | /** 32 | * Initialize this request. 33 | * 34 | * @param name the name of the channel. 35 | * @param badge the badge 36 | * @param badgeColor the badge colors. 37 | * @param members list of members to initialize this channel with. 38 | */ 39 | public CreateChannel(String name, Badge badge, List badgeColor, List members) { 40 | this.name = name; 41 | this.badge = badge; 42 | this.badgeColor = badgeColor; 43 | this.members = members; 44 | } 45 | 46 | /** 47 | * Initialize this request. 48 | * 49 | * @param name the name. 50 | * @param members array of members to initialize this channel with. 51 | */ 52 | public CreateChannel(String name, String... members) { 53 | this.name = name; 54 | this.badge = Badge.ace; 55 | this.badgeColor = List.of("#FFFFFF"); 56 | this.members = List.of(members); 57 | } 58 | 59 | } 60 | -------------------------------------------------------------------------------- /src/main/java/athena/channels/resource/requests/channel/EditChannel.java: -------------------------------------------------------------------------------- 1 | package athena.channels.resource.requests.channel; 2 | 3 | import athena.channels.resource.channel.badge.Badge; 4 | 5 | import java.util.List; 6 | 7 | /** 8 | * A request used to edit a channel. 9 | * 10 | * @author Vrekt, Armisto 11 | */ 12 | public final class EditChannel { 13 | 14 | /** 15 | * The new name of the channel. 16 | */ 17 | private String name; 18 | /** 19 | * The new badge. 20 | */ 21 | private Badge badge; 22 | /** 23 | * List of new badge colors. 24 | */ 25 | private List badgeColor; 26 | 27 | /** 28 | * Initialize this request. 29 | * 30 | * @param name the name. 31 | * @param badge the badge 32 | * @param badgeColor list of badge colors. 33 | */ 34 | public EditChannel(String name, Badge badge, List badgeColor) { 35 | this.name = name; 36 | this.badge = badge; 37 | this.badgeColor = badgeColor; 38 | } 39 | 40 | } 41 | -------------------------------------------------------------------------------- /src/main/java/athena/channels/resource/requests/member/AddMembers.java: -------------------------------------------------------------------------------- 1 | package athena.channels.resource.requests.member; 2 | 3 | import java.util.List; 4 | 5 | /** 6 | * A request used to add members to a channel. 7 | * 8 | * @author Vrekt, Armisto 9 | */ 10 | public final class AddMembers { 11 | 12 | /** 13 | * The channel ID. 14 | */ 15 | private String containerId; 16 | /** 17 | * List of account IDs you want to add. 18 | */ 19 | private List members; 20 | 21 | /** 22 | * Initialize this request. 23 | * 24 | * @param channelId the channel ID. 25 | * @param accountIds list of account IDs. 26 | */ 27 | public AddMembers(String channelId, List accountIds) { 28 | this.containerId = channelId; 29 | this.members = accountIds; 30 | } 31 | 32 | } 33 | -------------------------------------------------------------------------------- /src/main/java/athena/channels/resource/requests/message/SendMessage.java: -------------------------------------------------------------------------------- 1 | package athena.channels.resource.requests.message; 2 | 3 | import athena.channels.resource.channel.message.MessageAttachedEntity; 4 | 5 | import java.util.List; 6 | 7 | /** 8 | * A request used to send messages to a {@link athena.channels.resource.channel.Channel} 9 | * 10 | * @author Vrekt, Armisto 11 | */ 12 | public final class SendMessage { 13 | 14 | /** 15 | * The message. 16 | */ 17 | private String message; 18 | /** 19 | * List of entities attached with this message. 20 | */ 21 | private List entities; 22 | 23 | /** 24 | * Initialize this request. 25 | * 26 | * @param message the message 27 | * @param entities the entities 28 | */ 29 | public SendMessage(String message, List entities) { 30 | this.message = message; 31 | this.entities = entities; 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /src/main/java/athena/channels/resource/responses/channel/UserChannel.java: -------------------------------------------------------------------------------- 1 | package athena.channels.resource.responses.channel; 2 | 3 | import athena.channels.resource.channel.badge.Badge; 4 | import athena.channels.resource.channel.message.ChannelMessage; 5 | import athena.channels.resource.responses.channel.message.MostRecentMessage; 6 | 7 | import java.util.List; 8 | 9 | /** 10 | * Represents a channel a user is in. 11 | * 12 | * @author Vrekt, Armisto 13 | */ 14 | public final class UserChannel { 15 | 16 | /** 17 | * The channel ID and name. 18 | */ 19 | private String channelId, name, unreadCount; 20 | /** 21 | * The badge of this channel. 22 | */ 23 | private Badge badge; 24 | /** 25 | * The badge colors and list of members by account ID. 26 | */ 27 | private List badgeColor, members; 28 | 29 | /** 30 | * The most recent message. 31 | */ 32 | private MostRecentMessage mostRecentMessage; 33 | 34 | /** 35 | * @return the channel ID. 36 | */ 37 | public String channelId() { 38 | return channelId; 39 | } 40 | 41 | /** 42 | * @return the name of the channel. 43 | */ 44 | public String name() { 45 | return name; 46 | } 47 | 48 | /** 49 | * @return number of unread messages. 50 | */ 51 | public int unreadCount() { 52 | return Integer.parseInt(unreadCount); 53 | } 54 | 55 | /** 56 | * @return the channel badge. 57 | */ 58 | public Badge badge() { 59 | return badge; 60 | } 61 | 62 | /** 63 | * @return list of badge colors. 64 | */ 65 | public List badgeColor() { 66 | return badgeColor; 67 | } 68 | 69 | /** 70 | * @return list of members by account ID. 71 | */ 72 | public List members() { 73 | return members; 74 | } 75 | 76 | /** 77 | * @return the most recent message. 78 | */ 79 | public ChannelMessage mostRecentMessage() { 80 | return mostRecentMessage == null ? null : mostRecentMessage.message(); 81 | } 82 | } 83 | -------------------------------------------------------------------------------- /src/main/java/athena/channels/resource/responses/channel/UserChannels.java: -------------------------------------------------------------------------------- 1 | package athena.channels.resource.responses.channel; 2 | 3 | import athena.channels.resource.responses.dm.DirectMessage; 4 | 5 | import java.util.List; 6 | import java.util.stream.Collectors; 7 | 8 | /** 9 | * A response of all channels and DMs a user is in. 10 | * 11 | * @author Vrekt, Armisto 12 | */ 13 | public final class UserChannels { 14 | 15 | /** 16 | * List of channels. 17 | */ 18 | private List channels; 19 | 20 | /** 21 | * List of direct messages. 22 | */ 23 | private List dms; 24 | 25 | /** 26 | * @return the channels. 27 | */ 28 | public List channels() { 29 | return channels; 30 | } 31 | 32 | /** 33 | * @return the dms. 34 | */ 35 | public List dms() { 36 | return dms; 37 | } 38 | 39 | /** 40 | * Get a channel by channel ID. 41 | * 42 | * @param channelId the channel ID. 43 | * @return the {@link UserChannel} or {@code null} if not found. 44 | */ 45 | public UserChannel getChannelById(String channelId) { 46 | return channels.stream().filter(userChannel -> userChannel.channelId().equals(channelId)).findAny().orElse(null); 47 | } 48 | 49 | /** 50 | * Get a list of channels by name. 51 | * 52 | * @param channelName the channel name. 53 | * @return a list of {@link UserChannel} 54 | */ 55 | public List getChannelsByName(String channelName) { 56 | return channels.stream().filter(userChannel -> userChannel.name().equals(channelName)).collect(Collectors.toList()); 57 | } 58 | 59 | /** 60 | * Get a direct message between you and another account. 61 | * 62 | * @param accountId the account ID. 63 | * @return the {@link DirectMessage} or {@code null} 64 | */ 65 | public DirectMessage getDirectMessage(String accountId) { 66 | return dms.stream().filter(directMessage -> directMessage.participants().contains(accountId)).findAny().orElse(null); 67 | } 68 | 69 | } 70 | -------------------------------------------------------------------------------- /src/main/java/athena/channels/resource/responses/channel/message/MostRecentMessage.java: -------------------------------------------------------------------------------- 1 | package athena.channels.resource.responses.channel.message; 2 | 3 | import athena.channels.resource.channel.message.ChannelMessage; 4 | 5 | /** 6 | * Represents the most recent message. 7 | * 8 | * @author Vrekt, Armisto 9 | */ 10 | public final class MostRecentMessage { 11 | 12 | /** 13 | * The message. 14 | */ 15 | private ChannelMessage message; 16 | 17 | /** 18 | * @return the message. 19 | */ 20 | public ChannelMessage message() { 21 | return message; 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /src/main/java/athena/channels/resource/responses/dm/DirectMessage.java: -------------------------------------------------------------------------------- 1 | package athena.channels.resource.responses.dm; 2 | 3 | import java.util.List; 4 | 5 | /** 6 | * Represents a direct message channel. 7 | * 8 | * @author Vrekt, Armisto 9 | */ 10 | public final class DirectMessage { 11 | 12 | /** 13 | * List of participants by account ID. 14 | */ 15 | private List participants; 16 | /** 17 | * Number of unread messages? 18 | */ 19 | private String unreadCount; 20 | 21 | /** 22 | * @return List of participants by account ID. 23 | */ 24 | public List participants() { 25 | return participants; 26 | } 27 | 28 | /** 29 | * @return Number of unread messages? 30 | */ 31 | public int unreadCount() { 32 | return Integer.parseInt(unreadCount); 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /src/main/java/athena/channels/resource/responses/message/GetMessage.java: -------------------------------------------------------------------------------- 1 | package athena.channels.resource.responses.message; 2 | 3 | import athena.channels.resource.channel.member.ChannelMember; 4 | import athena.channels.resource.channel.message.ChannelMessage; 5 | 6 | import java.util.List; 7 | 8 | /** 9 | * A response for getting a singular message in a {@link athena.channels.resource.channel.Channel} 10 | * 11 | * @author Vrekt, Armisto 12 | */ 13 | public final class GetMessage { 14 | 15 | /** 16 | * The message. 17 | */ 18 | private ChannelMessage message; 19 | /** 20 | * List of users associated with the message? 21 | */ 22 | private List users; 23 | 24 | /** 25 | * @return the message 26 | */ 27 | public ChannelMessage message() { 28 | return message; 29 | } 30 | 31 | /** 32 | * @return list of users. 33 | */ 34 | public List users() { 35 | return users; 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /src/main/java/athena/channels/resource/responses/message/Messages.java: -------------------------------------------------------------------------------- 1 | package athena.channels.resource.responses.message; 2 | 3 | import athena.channels.resource.channel.member.ChannelMember; 4 | import athena.channels.resource.channel.message.ChannelMessage; 5 | 6 | import java.util.List; 7 | import java.util.stream.Collectors; 8 | 9 | /** 10 | * A response of all messages. 11 | * TODO: metadata (probably a map right?) 12 | * 13 | * @author Vrekt, Armisto 14 | */ 15 | public final class Messages { 16 | 17 | /** 18 | * List of channel messages. 19 | */ 20 | private List messages; 21 | /** 22 | * List of users. 23 | */ 24 | private List users; 25 | 26 | /** 27 | * @return list of channel messages. 28 | */ 29 | public List messages() { 30 | return messages; 31 | } 32 | 33 | /** 34 | * @return list of users who sent a message? 35 | */ 36 | public List users() { 37 | return users; 38 | } 39 | 40 | /** 41 | * Filter messages by account ID. 42 | * 43 | * @param accountId the account ID. 44 | * @return a list of {@link ChannelMessage} 45 | */ 46 | public List filterByAccountId(String accountId) { 47 | return messages.stream().filter(channelMessage -> channelMessage.accountId().equals(accountId)).collect(Collectors.toList()); 48 | } 49 | 50 | /** 51 | * Get a channel message by ID. 52 | * 53 | * @param messageId the message ID. 54 | * @return the {@link ChannelMessage} or {@code null} if not found. 55 | */ 56 | public ChannelMessage getById(String messageId) { 57 | return messages.stream().filter(channelMessage -> channelMessage.id().equals(messageId)).findAny().orElse(null); 58 | } 59 | 60 | } 61 | -------------------------------------------------------------------------------- /src/main/java/athena/channels/resource/responses/message/SentMessage.java: -------------------------------------------------------------------------------- 1 | package athena.channels.resource.responses.message; 2 | 3 | import athena.channels.resource.channel.message.MessageAttachedEntity; 4 | 5 | import java.util.List; 6 | 7 | /** 8 | * The response of a sent message. 9 | * 10 | * @author Vrekt, Armisto 11 | */ 12 | public final class SentMessage { 13 | 14 | /** 15 | * The ID of the message. 16 | */ 17 | private String id; 18 | /** 19 | * List of entities attached with the message. 20 | */ 21 | private List entities; 22 | 23 | /** 24 | * @return ID of the message. 25 | */ 26 | public String id() { 27 | return id; 28 | } 29 | 30 | /** 31 | * @return list of entities. 32 | */ 33 | public List entities() { 34 | return entities; 35 | } 36 | 37 | } 38 | -------------------------------------------------------------------------------- /src/main/java/athena/chat/resource/listener/IncomingMessageListener.java: -------------------------------------------------------------------------------- 1 | package athena.chat.resource.listener; 2 | 3 | import athena.chat.FriendChat; 4 | import athena.chat.resource.BasicMessage; 5 | 6 | /** 7 | * A basic listener for incoming XMPP messages in {@link FriendChat} 8 | */ 9 | public interface IncomingMessageListener { 10 | 11 | /** 12 | * Invoked when a message is received 13 | * 14 | * @param message the message 15 | */ 16 | void onMessage(BasicMessage message); 17 | 18 | } 19 | -------------------------------------------------------------------------------- /src/main/java/athena/eula/resource/Eula.java: -------------------------------------------------------------------------------- 1 | package athena.eula.resource; 2 | 3 | /** 4 | * Represents a fortnite EULA. 5 | */ 6 | public final class Eula { 7 | 8 | /** 9 | * Key is usually FN, title of the EULA, body, locale and username/status. 10 | */ 11 | private String key, title, body, locale, agentUserName, status; 12 | 13 | /** 14 | * Version and revision 15 | */ 16 | private int version, revision; 17 | 18 | /** 19 | * Unknown values really 20 | */ 21 | private boolean custom, wasDeclined, hasResponse; 22 | 23 | /** 24 | * @return the key of the EULA, "FN" 25 | */ 26 | public String key() { 27 | return key; 28 | } 29 | 30 | /** 31 | * @return title of the EULA. 32 | */ 33 | public String title() { 34 | return title; 35 | } 36 | 37 | /** 38 | * @return the body of the EULA. 39 | */ 40 | public String body() { 41 | return body; 42 | } 43 | 44 | /** 45 | * @return the locale of the EULA. 46 | */ 47 | public String locale() { 48 | return locale; 49 | } 50 | 51 | /** 52 | * @return username who requested EULA. 53 | */ 54 | public String agentUserName() { 55 | return agentUserName; 56 | } 57 | 58 | /** 59 | * @return the status, usually "ACTIVE"? 60 | */ 61 | public String status() { 62 | return status; 63 | } 64 | 65 | /** 66 | * @return current EULA version. 67 | */ 68 | public int version() { 69 | return version; 70 | } 71 | 72 | /** 73 | * @return current EULA revision. 74 | */ 75 | public int revision() { 76 | return revision; 77 | } 78 | 79 | /** 80 | * @return unknown. 81 | */ 82 | public boolean custom() { 83 | return custom; 84 | } 85 | 86 | /** 87 | * @return {@code true} if the EULA was declined? 88 | */ 89 | public boolean wasDeclined() { 90 | return wasDeclined; 91 | } 92 | 93 | /** 94 | * @return unknown. 95 | */ 96 | public boolean hasResponse() { 97 | return hasResponse; 98 | } 99 | } 100 | -------------------------------------------------------------------------------- /src/main/java/athena/eula/service/EulatrackingPublicService.java: -------------------------------------------------------------------------------- 1 | package athena.eula.service; 2 | 3 | import athena.eula.resource.Eula; 4 | import retrofit2.Call; 5 | import retrofit2.http.GET; 6 | import retrofit2.http.POST; 7 | import retrofit2.http.Path; 8 | import retrofit2.http.Query; 9 | 10 | /** 11 | * Used for accepting/getting versions of the EULA. 12 | * 13 | * @author Vrekt, RobertoGraham 14 | */ 15 | public interface EulatrackingPublicService { 16 | 17 | String BASE_URL = "https://eulatracking-public-service-prod06.ol.epicgames.com/"; 18 | 19 | /** 20 | * Get the current EULA version. 21 | * 22 | * @param accountId the ID of the account 23 | * @param locale the locale, usually 'en-US' 24 | * @return a {@link Call} returned by retrofit containing the {@link Eula} if the call was successful. 25 | */ 26 | @GET("eulatracking/api/public/agreements/fn/account/{accountId}") 27 | Call eula(@Path("accountId") String accountId, @Query("locale") String locale); 28 | 29 | /** 30 | * Accept the EULA. 31 | * 32 | * @param version the current EULA version. 33 | * @param accountId the ID of the account 34 | * @param locale the locale, usually 'en-US' 35 | */ 36 | @POST("eulatracking/api/public/agreements/fn/version/{version}/{accountId}/accept") 37 | Call acceptEula(@Path("version") int version, @Path("accountId") String accountId, @Query("locale") String locale); 38 | 39 | } 40 | -------------------------------------------------------------------------------- /src/main/java/athena/events/resource/download/player/payouts/PendingPayouts.java: -------------------------------------------------------------------------------- 1 | package athena.events.resource.download.player.payouts; 2 | 3 | public class PendingPayouts { 4 | } 5 | -------------------------------------------------------------------------------- /src/main/java/athena/events/resource/download/template/payout/EventPayout.java: -------------------------------------------------------------------------------- 1 | package athena.events.resource.download.template.payout; 2 | 3 | /** 4 | * Represents an event payout for a {@link athena.events.resource.download.template.payout.rank.EventPayoutRank} 5 | * { 6 | * "rewardType": "token", 7 | * "rewardMode": "rolling", 8 | * "value": "ARENA_S11_Division8", 9 | * "quantity": 1 10 | * }, 11 | */ 12 | public final class EventPayout { 13 | 14 | /** 15 | * "ecomm" 16 | * "standard" 17 | * "USD" 18 | *

19 | * "persistentScore" 20 | * "standard" 21 | * "FNCS_S11_Points_NAE" 22 | */ 23 | private String rewardType, rewardMode, value; 24 | /** 25 | * Quantity of this payout. 26 | */ 27 | private int quantity; 28 | 29 | /** 30 | * @return the reward type, ex: "ecomm" 31 | */ 32 | public String rewardType() { 33 | return rewardType; 34 | } 35 | 36 | /** 37 | * @return the reward mode, ex: "standard" 38 | */ 39 | public String rewardMode() { 40 | return rewardMode; 41 | } 42 | 43 | /** 44 | * @return the value, ex: "USD" 45 | */ 46 | public String value() { 47 | return value; 48 | } 49 | 50 | /** 51 | * @return the quantity, $$$ payout or points 52 | */ 53 | public int quantity() { 54 | return quantity; 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /src/main/java/athena/events/resource/download/template/payout/EventPayoutTable.java: -------------------------------------------------------------------------------- 1 | package athena.events.resource.download.template.payout; 2 | 3 | import athena.events.resource.download.template.payout.rank.EventPayoutRank; 4 | 5 | import java.util.List; 6 | import java.util.Optional; 7 | 8 | /** 9 | * Represents a payout table for a {@link athena.events.resource.download.template.EventTemplate} 10 | */ 11 | public final class EventPayoutTable { 12 | 13 | /** 14 | * "null" 15 | * "rank" 16 | *

17 | * "Hype_S11" 18 | * "value" 19 | */ 20 | private String persistentScoreId, scoringType; 21 | 22 | /** 23 | * List of ranks. 24 | */ 25 | private List ranks; 26 | 27 | /** 28 | * @return persistent score ID, {@code null} sometimes. 29 | */ 30 | public String persistentScoreId() { 31 | return persistentScoreId; 32 | } 33 | 34 | /** 35 | * @return the scoring type. 36 | */ 37 | public String scoringType() { 38 | return scoringType; 39 | } 40 | 41 | /** 42 | * @return list of payout ranks. 43 | */ 44 | public List ranks() { 45 | return ranks; 46 | } 47 | 48 | /** 49 | * Get a list of {@link EventPayout} for the specified {@code threshold} 50 | * 51 | * @param threshold the threshold 52 | * @return a list of {@link EventPayout} or an empty {@link List} if threshold wasn't found. 53 | */ 54 | public List getPayoutsForThreshold(double threshold) { 55 | final var rank = ranks.stream().filter(eventPayoutRank -> eventPayoutRank.threshold() == threshold).findAny().orElse(null); 56 | if (rank == null) return List.of(); 57 | return rank.payouts(); 58 | } 59 | 60 | /** 61 | * Get a {@link EventPayoutRank} that has the specified {@code threshold} 62 | * 63 | * @param threshold the threshold 64 | * @return a {@link Optional} containing the {@link EventPayoutRank} if found 65 | */ 66 | public Optional getEventPayoutRankForThreshold(double threshold) { 67 | return ranks.stream().filter(eventPayoutRank -> eventPayoutRank.threshold() == threshold).findAny(); 68 | } 69 | 70 | } 71 | -------------------------------------------------------------------------------- /src/main/java/athena/events/resource/download/template/payout/rank/EventPayoutRank.java: -------------------------------------------------------------------------------- 1 | package athena.events.resource.download.template.payout.rank; 2 | 3 | import athena.events.resource.download.template.payout.EventPayout; 4 | 5 | import java.util.List; 6 | import java.util.stream.Collectors; 7 | 8 | /** 9 | * Represents a singular payout rank for {@link athena.events.resource.download.template.payout.EventPayoutTable} 10 | */ 11 | public final class EventPayoutRank { 12 | 13 | /** 14 | * The threshold for this payout rank. 15 | */ 16 | private double threshold; 17 | 18 | /** 19 | * List of payouts. 20 | */ 21 | private List payouts; 22 | 23 | /** 24 | * @return the threshold. 25 | */ 26 | public double threshold() { 27 | return threshold; 28 | } 29 | 30 | /** 31 | * @return the payouts. 32 | */ 33 | public List payouts() { 34 | return payouts; 35 | } 36 | 37 | /** 38 | * Get a list of payouts with the specified {@code rewardType} 39 | * 40 | * @param rewardType the reward type 41 | * @return a list of {@link EventPayout}s 42 | */ 43 | public List getPayoutsForRewardType(String rewardType) { 44 | return payouts.stream().filter(payout -> payout.rewardType().equalsIgnoreCase(rewardType)).collect(Collectors.toList()); 45 | } 46 | 47 | /** 48 | * Get a list of payouts with the specified {@code rewardMode} 49 | * 50 | * @param rewardMode the reward mode 51 | * @return a list of {@link EventPayout}s 52 | */ 53 | public List getPayoutsForRewardMode(String rewardMode) { 54 | return payouts.stream().filter(payout -> payout.rewardMode().equalsIgnoreCase(rewardMode)).collect(Collectors.toList()); 55 | } 56 | 57 | } 58 | -------------------------------------------------------------------------------- /src/main/java/athena/events/resource/download/template/scoring/EventRewardTier.java: -------------------------------------------------------------------------------- 1 | package athena.events.resource.download.template.scoring; 2 | 3 | /** 4 | * Represents a singular reward tier for a {@link EventScoringRule} 5 | *

6 | * "trackedStat": "PLACEMENT_STAT_INDEX", 7 | * "matchRule": "lte", 8 | * "rewardTiers": [ 9 | * { 10 | * "keyValue": 1, 11 | * "pointsEarned": 3, 12 | * "multiplicative": false 13 | * }, 14 | */ 15 | public final class EventRewardTier { 16 | /** 17 | * key value I think is what their earned, for example "5" for placing 5th. 18 | * Then the points earned for placing 5th would be {@code pointsEarned}, 3 points for 5th? 19 | */ 20 | private int keyValue, pointsEarned; 21 | /** 22 | * Don't know really 23 | */ 24 | private boolean multiplicative; 25 | 26 | /** 27 | * @return the key value 28 | */ 29 | public int keyValue() { 30 | return keyValue; 31 | } 32 | 33 | /** 34 | * @return points earned for achieving the key value? 35 | */ 36 | public int pointsEarned() { 37 | return pointsEarned; 38 | } 39 | 40 | /** 41 | * @return {@code true} if multiplicative 42 | */ 43 | public boolean multiplicative() { 44 | return multiplicative; 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /src/main/java/athena/events/resource/download/template/scoring/EventScoringRule.java: -------------------------------------------------------------------------------- 1 | package athena.events.resource.download.template.scoring; 2 | 3 | import java.util.List; 4 | 5 | /** 6 | * Represents a scoring rule for {@link athena.events.resource.download.template.EventTemplate} 7 | */ 8 | public final class EventScoringRule { 9 | 10 | /** 11 | * The tracked stat, ex: PLACEMENT_STAT_INDEX 12 | * The match rule, ex: 'lte' 13 | */ 14 | private String trackedStat, matchRule; 15 | /** 16 | * List of reward tiers. 17 | */ 18 | private List rewardTiers; 19 | 20 | /** 21 | * @return the tracked stat 22 | */ 23 | public String trackedStat() { 24 | return trackedStat; 25 | } 26 | 27 | /** 28 | * @return the match rule 29 | */ 30 | public String matchRule() { 31 | return matchRule; 32 | } 33 | 34 | /** 35 | * @return list of reward tiers. 36 | */ 37 | public List rewardTiers() { 38 | return rewardTiers; 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /src/main/java/athena/events/resource/download/template/tiebreaker/EventTiebreakerFormula.java: -------------------------------------------------------------------------------- 1 | package athena.events.resource.download.template.tiebreaker; 2 | 3 | import java.util.List; 4 | import java.util.Optional; 5 | 6 | /** 7 | * Tie-breaker formula for a {@link athena.events.resource.download.template.EventTemplate} 8 | */ 9 | public final class EventTiebreakerFormula { 10 | 11 | /** 12 | * Base bits. 13 | */ 14 | private int basePointsBits; 15 | /** 16 | * List of components for this formula. 17 | */ 18 | private List components; 19 | 20 | /** 21 | * @return base point bits. 22 | */ 23 | public int basePointsBits() { 24 | return basePointsBits; 25 | } 26 | 27 | /** 28 | * @return a list of components for this event. 29 | */ 30 | public List components() { 31 | return components; 32 | } 33 | 34 | /** 35 | * Get a {@link EventTiebreakerFormulaComponent} by the tracked stat name. 36 | * 37 | * @param trackedStat the tracked stat. 38 | * @return a {@link Optional} containing the {@link EventTiebreakerFormulaComponent} if found. 39 | */ 40 | public Optional get(String trackedStat) { 41 | return components.stream().filter(component -> component.trackedStat().equalsIgnoreCase(trackedStat)).findAny(); 42 | } 43 | 44 | } 45 | -------------------------------------------------------------------------------- /src/main/java/athena/events/resource/download/template/tiebreaker/EventTiebreakerFormulaComponent.java: -------------------------------------------------------------------------------- 1 | package athena.events.resource.download.template.tiebreaker; 2 | 3 | /** 4 | * A singular component for a {@link EventTiebreakerFormula} 5 | */ 6 | public final class EventTiebreakerFormulaComponent { 7 | 8 | /** 9 | * The tracked stat, ex: "VICTORY_ROYALE_STAT" 10 | * The aggregation, "avg", "sum" 11 | */ 12 | private String trackedStat, aggregation; 13 | /** 14 | * bits is X, multiplier can be null/0. 15 | */ 16 | private int bits, multiplier; 17 | 18 | /** 19 | * @return the tracked stat. 20 | */ 21 | public String trackedStat() { 22 | return trackedStat; 23 | } 24 | 25 | /** 26 | * @return the aggregation 27 | */ 28 | public String aggregation() { 29 | return aggregation; 30 | } 31 | 32 | /** 33 | * @return the bits 34 | */ 35 | public int bits() { 36 | return bits; 37 | } 38 | 39 | /** 40 | * @return the multiplier. 41 | */ 42 | public int multiplier() { 43 | return multiplier; 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /src/main/java/athena/events/resource/download/window/FortniteEventWindowMetadata.java: -------------------------------------------------------------------------------- 1 | package athena.events.resource.download.window; 2 | 3 | import com.google.gson.annotations.SerializedName; 4 | 5 | /** 6 | * Represents metadata of a {@link FortniteEventWindow} 7 | */ 8 | public final class FortniteEventWindowMetadata { 9 | 10 | /** 11 | * The round type of this event window: 12 | * "Arena" 13 | * "Finals" 14 | * "Qualifiers" 15 | * "SemiFinals" 16 | * etc. 17 | */ 18 | @SerializedName("RoundType") 19 | private String roundType; 20 | /** 21 | * The threshold to advance to the next division? 22 | */ 23 | @SerializedName("ThresholdToAdvanceDivision") 24 | private int thresholdToAdvanceDivision; 25 | /** 26 | * Division rank required? 27 | */ 28 | private int divisionRank; 29 | /** 30 | * {@code true} if server replays are enabled? 31 | */ 32 | @SerializedName("ServerReplays") 33 | private boolean serverReplays; 34 | /** 35 | * Matchmaking delay seconds. 36 | */ 37 | @SerializedName("ScheduledMatchmakingMatchDelaySeconds") 38 | private int scheduledMatchmakingDelaySeconds; 39 | /** 40 | * Initial matchmaking delay seconds. 41 | */ 42 | @SerializedName("ScheduledMatchmakingInitialDelaySeconds") 43 | private int scheduledMatchmakingInitialDelaySeconds; 44 | 45 | /** 46 | * @return the round type 47 | */ 48 | String roundType() { 49 | return roundType; 50 | } 51 | 52 | /** 53 | * @return threshold to advance to the next division? 54 | */ 55 | int thresholdToAdvanceDivision() { 56 | return thresholdToAdvanceDivision; 57 | } 58 | 59 | /** 60 | * @return division rank required? 61 | */ 62 | int divisionRank() { 63 | return divisionRank; 64 | } 65 | 66 | /** 67 | * @return {@code true} if server replays are enabled? 68 | */ 69 | boolean serverReplays() { 70 | return serverReplays; 71 | } 72 | 73 | /** 74 | * @return matchmaking delay. 75 | */ 76 | int scheduledMatchmakingDelaySeconds() { 77 | return scheduledMatchmakingDelaySeconds; 78 | } 79 | 80 | /** 81 | * @return initial matchmaking delay. 82 | */ 83 | int scheduledMatchmakingInitialDelaySeconds() { 84 | return scheduledMatchmakingInitialDelaySeconds; 85 | } 86 | } 87 | -------------------------------------------------------------------------------- /src/main/java/athena/events/resource/leaderboard/session/EventSession.java: -------------------------------------------------------------------------------- 1 | package athena.events.resource.leaderboard.session; 2 | 3 | import athena.events.resource.leaderboard.statistic.LeaderboardStatistic; 4 | import athena.events.resource.leaderboard.entry.EventLeaderboardEntry; 5 | 6 | import java.time.Instant; 7 | import java.util.Map; 8 | 9 | /** 10 | * Represents an event session for a {@link EventLeaderboardEntry} 11 | */ 12 | public final class EventSession { 13 | 14 | /** 15 | * The session ID for this session. 16 | */ 17 | private String sessionId; 18 | /** 19 | * When this session ended. 20 | */ 21 | private Instant endTime; 22 | 23 | /** 24 | * A map of tracked-stats. 25 | */ 26 | private Map trackedStats; 27 | 28 | /** 29 | * @return the session ID. 30 | */ 31 | public String sessionId() { 32 | return sessionId; 33 | } 34 | 35 | /** 36 | * @return when this session ended. 37 | */ 38 | public Instant endTime() { 39 | return endTime; 40 | } 41 | 42 | /** 43 | * @return the tracked stats for this session. 44 | */ 45 | public Map trackedStats() { 46 | return trackedStats; 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /src/main/java/athena/events/resource/leaderboard/statistic/LeaderboardStatistic.java: -------------------------------------------------------------------------------- 1 | package athena.events.resource.leaderboard.statistic; 2 | 3 | public enum LeaderboardStatistic { 4 | 5 | /** 6 | * Placement 7 | */ 8 | PLACEMENT_STAT_INDEX, 9 | /** 10 | * Time alive. 11 | */ 12 | TIME_ALIVE_STAT, 13 | /** 14 | * Eliminations 15 | */ 16 | TEAM_ELIMS_STAT_INDEX, 17 | /** 18 | * Matches played 19 | */ 20 | MATCH_PLAYED_STAT, 21 | /** 22 | * Tiebreaker 23 | */ 24 | PLACEMENT_TIEBREAKER_STAT, 25 | /** 26 | * Wins 27 | */ 28 | VICTORY_ROYALE_STAT 29 | 30 | } 31 | -------------------------------------------------------------------------------- /src/main/java/athena/events/resource/player/PlayerTokenResponse.java: -------------------------------------------------------------------------------- 1 | package athena.events.resource.player; 2 | 3 | import java.util.List; 4 | 5 | /** 6 | * Represents a response to the events tokens endpoint. 7 | */ 8 | public final class PlayerTokenResponse { 9 | 10 | /** 11 | * The list of accounts 12 | */ 13 | private List accounts; 14 | 15 | /** 16 | * Get the {@link TokenPlayer} from the {@code accountId} 17 | * 18 | * @param accountId the account ID 19 | * @return the {@link TokenPlayer} or {@code null} if not found. 20 | */ 21 | public TokenPlayer get(String accountId) { 22 | return accounts.stream().filter(player -> player.accountId().equals(accountId)).findAny().orElse(null); 23 | } 24 | 25 | /** 26 | * @return the accounts 27 | */ 28 | public List accounts() { 29 | return accounts; 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /src/main/java/athena/events/resource/player/TokenPlayer.java: -------------------------------------------------------------------------------- 1 | package athena.events.resource.player; 2 | 3 | import java.util.List; 4 | 5 | /** 6 | * Represents an account/player inside the token response 7 | */ 8 | public final class TokenPlayer { 9 | 10 | /** 11 | * The account ID of this player 12 | */ 13 | private String accountId; 14 | 15 | /** 16 | * The list of tokens 17 | */ 18 | private List tokens; 19 | 20 | /** 21 | * @return the account ID. 22 | */ 23 | public String accountId() { 24 | return accountId; 25 | } 26 | 27 | /** 28 | * @return the list of tokens 29 | */ 30 | public List tokens() { 31 | return tokens; 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /src/main/java/athena/exception/UnsupportedBuildException.java: -------------------------------------------------------------------------------- 1 | package athena.exception; 2 | 3 | /** 4 | * An exception thrown when the Athena builder is attempting to be built incomplete. 5 | */ 6 | public final class UnsupportedBuildException extends RuntimeException { 7 | 8 | public UnsupportedBuildException(String message) { 9 | super(message); 10 | } 11 | 12 | } 13 | -------------------------------------------------------------------------------- /src/main/java/athena/fortnite/Fortnite.java: -------------------------------------------------------------------------------- 1 | package athena.fortnite; 2 | 3 | import athena.fortnite.service.FortnitePublicService; 4 | import athena.fortnite.shop.Storefront; 5 | import athena.fortnite.shop.StorefrontCatalog; 6 | import athena.util.request.Requests; 7 | 8 | /** 9 | * Provides easy access to various things within {@link athena.fortnite.service.FortnitePublicService} 10 | */ 11 | public final class Fortnite { 12 | 13 | /** 14 | * The service 15 | */ 16 | private final FortnitePublicService service; 17 | 18 | public Fortnite(FortnitePublicService service) { 19 | this.service = service; 20 | } 21 | 22 | /** 23 | * Retrieve the entire catalog. 24 | * 25 | * @return the entire catalog. 26 | */ 27 | public StorefrontCatalog storefrontCatalog() { 28 | final var call = service.storefrontCatalog(); 29 | return Requests.executeCall(call); 30 | } 31 | 32 | /** 33 | * @return the daily store-front. 34 | */ 35 | public Storefront dailyStorefront() { 36 | return storefrontCatalog().get("BRDailyStorefront"); 37 | } 38 | 39 | /** 40 | * @return the weekly store-front. 41 | */ 42 | public Storefront weeklyStorefront() { 43 | return storefrontCatalog().get("BRWeeklyStorefront"); 44 | } 45 | 46 | /** 47 | * Get a specific storefront by name. 48 | * 49 | * @param name the name. 50 | * @return the storefront. 51 | */ 52 | public Storefront getStorefront(String name) { 53 | return storefrontCatalog().get(name); 54 | } 55 | 56 | } 57 | -------------------------------------------------------------------------------- /src/main/java/athena/fortnite/calendar/CalendarTimeline.java: -------------------------------------------------------------------------------- 1 | package athena.fortnite.calendar; 2 | 3 | import java.time.Instant; 4 | 5 | public final class CalendarTimeline { 6 | 7 | private int cacheIntervalMins; 8 | private Instant currentTime; 9 | 10 | } 11 | -------------------------------------------------------------------------------- /src/main/java/athena/fortnite/calendar/channel/CalendarChannel.java: -------------------------------------------------------------------------------- 1 | package athena.fortnite.calendar.channel; 2 | 3 | public final class CalendarChannel { 4 | 5 | 6 | 7 | } 8 | -------------------------------------------------------------------------------- /src/main/java/athena/fortnite/calendar/channel/states/ChannelState.java: -------------------------------------------------------------------------------- 1 | package athena.fortnite.calendar.channel.states; 2 | 3 | /** 4 | * Represents a singular state in a {@link athena.fortnite.calendar.channel.CalendarChannel} 5 | */ 6 | public final class ChannelState { 7 | 8 | 9 | 10 | } 11 | -------------------------------------------------------------------------------- /src/main/java/athena/fortnite/creative/CreativeHistoryResponse.java: -------------------------------------------------------------------------------- 1 | package athena.fortnite.creative; 2 | 3 | import athena.fortnite.service.FortnitePublicService; 4 | 5 | import java.util.List; 6 | 7 | /** 8 | * Represents response from "fortnite/api/game/v2/creative/history/{accountId}" {@link FortnitePublicService} 9 | */ 10 | public final class CreativeHistoryResponse { 11 | 12 | /** 13 | * List of results. 14 | */ 15 | private List results; 16 | 17 | /** 18 | * @return results 19 | */ 20 | public List results() { 21 | return results; 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /src/main/java/athena/fortnite/creative/data/CreativeLinkData.java: -------------------------------------------------------------------------------- 1 | package athena.fortnite.creative.data; 2 | 3 | /** 4 | * Represents link data inside a {@link athena.fortnite.creative.CreativeHistoryResult} 5 | */ 6 | public final class CreativeLinkData { 7 | 8 | /** 9 | * "7981-5279-7029", 10 | * "Creative:Island", 11 | * "xxx", 12 | * "name" 13 | */ 14 | private String mnemonic, linkType, accountId, creatorName; 15 | /** 16 | * {@code true} if this creative is active? 17 | */ 18 | private boolean active; 19 | /** 20 | * The version of this island/gamemode? 21 | */ 22 | private int version; 23 | /** 24 | * Meta-data for this creative 25 | */ 26 | private CreativeMetadata metadata; 27 | 28 | /** 29 | * @return the code/mnemonic 30 | */ 31 | public String mnemonic() { 32 | return mnemonic; 33 | } 34 | 35 | /** 36 | * @return the link type, ex: Creative:Island 37 | */ 38 | public String linkType() { 39 | return linkType; 40 | } 41 | 42 | /** 43 | * @return account ID owner of the island 44 | */ 45 | public String accountId() { 46 | return accountId; 47 | } 48 | 49 | /** 50 | * @return name of who made/owns the island 51 | */ 52 | public String creatorName() { 53 | return creatorName; 54 | } 55 | 56 | /** 57 | * @return {@code true} if this creative is active? 58 | */ 59 | public boolean active() { 60 | return active; 61 | } 62 | 63 | /** 64 | * @return the version, sometimes -1 65 | */ 66 | public int version() { 67 | return version; 68 | } 69 | 70 | /** 71 | * @return the meta-data. 72 | */ 73 | public CreativeMetadata metadata() { 74 | return metadata; 75 | } 76 | } 77 | -------------------------------------------------------------------------------- /src/main/java/athena/fortnite/creative/matchmaking/CreativeMatchmaking.java: -------------------------------------------------------------------------------- 1 | package athena.fortnite.creative.matchmaking; 2 | 3 | import com.google.gson.annotations.SerializedName; 4 | 5 | /** 6 | * Represents matchmaking data for a {@link athena.fortnite.creative.data.CreativeMetadata entry 7 | */ 8 | public final class CreativeMatchmaking { 9 | 10 | /** 11 | * "Spectate", 12 | * "off" 13 | */ 14 | private String joinInProgressType, mmsType; 15 | /** 16 | * Relating to teams and player count, etc. 17 | */ 18 | private int playersPerTeam, maximumNumberOfPlayers, playerCount, numberOfTeams, minimumNumberOfPlayers; 19 | /** 20 | * If join in progress is allowed. 21 | */ 22 | @SerializedName("bAllowJoinInProgress") 23 | private boolean allowJoinInProgress; 24 | 25 | /** 26 | * @return the join in progress type, eg "Spectate" 27 | */ 28 | public String joinInProgressType() { 29 | return joinInProgressType; 30 | } 31 | 32 | /** 33 | * @return mms type ? "off" 34 | */ 35 | public String mmsType() { 36 | return mmsType; 37 | } 38 | 39 | /** 40 | * @return players per team. 41 | */ 42 | public int playersPerTeam() { 43 | return playersPerTeam; 44 | } 45 | 46 | /** 47 | * @return max number of players 48 | */ 49 | public int maximumNumberOfPlayers() { 50 | return maximumNumberOfPlayers; 51 | } 52 | 53 | /** 54 | * @return the player count 55 | */ 56 | public int playerCount() { 57 | return playerCount; 58 | } 59 | 60 | /** 61 | * @return number of teams 62 | */ 63 | public int numberOfTeams() { 64 | return numberOfTeams; 65 | } 66 | 67 | /** 68 | * @return min number of players 69 | */ 70 | public int minimumNumberOfPlayers() { 71 | return minimumNumberOfPlayers; 72 | } 73 | 74 | /** 75 | * @return {@code true} if join in progress is allowed. 76 | */ 77 | public boolean allowJoinInProgress() { 78 | return allowJoinInProgress; 79 | } 80 | } 81 | -------------------------------------------------------------------------------- /src/main/java/athena/fortnite/receipt/Receipt.java: -------------------------------------------------------------------------------- 1 | package athena.fortnite.receipt; 2 | 3 | import athena.fortnite.service.FortnitePublicService; 4 | 5 | /** 6 | * Represents a receipt from "fortnite/api/receipts/v1/account/{accountId}/receipts" {@link FortnitePublicService} 7 | */ 8 | public final class Receipt { 9 | 10 | private String appStore, appStoreId, receiptId, receiptInfo; 11 | 12 | /** 13 | * @return the app store, ex: "EpicPurchasingService" 14 | */ 15 | public String appStore() { 16 | return appStore; 17 | } 18 | 19 | /** 20 | * @return the app store ID. 21 | */ 22 | public String appStoreId() { 23 | return appStoreId; 24 | } 25 | 26 | /** 27 | * @return the receipt ID. 28 | */ 29 | public String receiptId() { 30 | return receiptId; 31 | } 32 | 33 | /** 34 | * @return the receipt info, ex: "ENTITLEMENT" 35 | */ 36 | public String receiptInfo() { 37 | return receiptInfo; 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /src/main/java/athena/fortnite/shop/Storefront.java: -------------------------------------------------------------------------------- 1 | package athena.fortnite.shop; 2 | 3 | import athena.fortnite.shop.catalog.CatalogEntry; 4 | 5 | import java.util.List; 6 | import java.util.Optional; 7 | 8 | /** 9 | * Represents a singular storefront. 10 | */ 11 | public final class Storefront { 12 | 13 | /** 14 | * Name of this storefront. 15 | */ 16 | private String name; 17 | /** 18 | * List of entries. 19 | */ 20 | private List catalogEntries; 21 | 22 | /** 23 | * Get an entry via the {@code devName} 24 | * 25 | * @param devName the dev name. 26 | * @return a {@link Optional} containing the {@link CatalogEntry} if found. 27 | */ 28 | public Optional getEntryByDevName(String devName) { 29 | return catalogEntries.stream().filter(catalogEntry -> catalogEntry.devName().equalsIgnoreCase(devName)).findAny(); 30 | } 31 | 32 | /** 33 | * Get an entry via the {@code offerId} 34 | * 35 | * @param offerId the offer ID. 36 | * @return a {@link Optional} containing the {@link CatalogEntry} if found. 37 | */ 38 | public Optional getEntryByOfferId(String offerId) { 39 | return catalogEntries.stream().filter(catalogEntry -> catalogEntry.offerId().equalsIgnoreCase(offerId)).findAny(); 40 | } 41 | 42 | /** 43 | * @return the name of this store-front. 44 | */ 45 | public String name() { 46 | return name; 47 | } 48 | 49 | /** 50 | * @return list of catalog entries. 51 | */ 52 | public List catalogEntries() { 53 | return catalogEntries; 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /src/main/java/athena/fortnite/shop/StorefrontCatalog.java: -------------------------------------------------------------------------------- 1 | package athena.fortnite.shop; 2 | 3 | import java.time.Instant; 4 | import java.util.List; 5 | import java.util.Optional; 6 | 7 | public final class StorefrontCatalog { 8 | 9 | /** 10 | * Refresh interval and time to purchase items? 11 | */ 12 | private int refreshIntervalHrs, dailyPurchaseHrs; 13 | 14 | /** 15 | * When the catalog expires. 16 | */ 17 | private Instant expiration; 18 | 19 | /** 20 | * A list of storefronts. 21 | */ 22 | private List storefronts; 23 | 24 | /** 25 | * Get a store front. 26 | * 27 | * @param name the name of the store front. 28 | * @return the {@link Storefront} or {@code null} if not found. 29 | */ 30 | public Storefront get(String name) { 31 | return storefronts.stream().filter(storefront -> storefront.name().equalsIgnoreCase(name)).findAny().orElse(null); 32 | } 33 | 34 | /** 35 | * Get a store front. 36 | * 37 | * @param name the name of the store front. 38 | * @return a {@link Optional} containing the {@link Storefront} if found. 39 | */ 40 | public Optional getOptional(String name) { 41 | return Optional.ofNullable(get(name)); 42 | } 43 | 44 | } 45 | -------------------------------------------------------------------------------- /src/main/java/athena/fortnite/shop/gift/CatalogGiftInfo.java: -------------------------------------------------------------------------------- 1 | package athena.fortnite.shop.gift; 2 | 3 | import com.google.gson.annotations.SerializedName; 4 | 5 | import java.util.List; 6 | 7 | /** 8 | * Gifting info for a catalog entry. 9 | */ 10 | public final class CatalogGiftInfo { 11 | 12 | /** 13 | * If gifting is enabled for this catalog entry. 14 | */ 15 | @SerializedName("bIsEnabled") 16 | private boolean isEnabled; 17 | 18 | /** 19 | * ?? 20 | */ 21 | private String forcedGiftBoxTemplateId; 22 | 23 | /** 24 | * ?? 25 | */ 26 | private List purchaseRequirements, giftRecordIds; 27 | 28 | /** 29 | * @return {@code true} if gifting is enabled. 30 | */ 31 | public boolean isEnabled() { 32 | return isEnabled; 33 | } 34 | 35 | /** 36 | * @return ?? 37 | */ 38 | public String forcedGiftBoxTemplateId() { 39 | return forcedGiftBoxTemplateId; 40 | } 41 | 42 | /** 43 | * @return ?? 44 | */ 45 | public List purchaseRequirements() { 46 | return purchaseRequirements; 47 | } 48 | 49 | /** 50 | * @return ?? 51 | */ 52 | public List giftRecordIds() { 53 | return giftRecordIds; 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /src/main/java/athena/fortnite/shop/grant/CatalogEntryItemGrant.java: -------------------------------------------------------------------------------- 1 | package athena.fortnite.shop.grant; 2 | 3 | /** 4 | * Represents an item grant for an entry. 5 | */ 6 | public final class CatalogEntryItemGrant { 7 | 8 | /** 9 | * The template ID. 10 | */ 11 | private String templateId; 12 | /** 13 | * The quantity to give. 14 | */ 15 | private int quantity; 16 | 17 | /** 18 | * @return template ID. 19 | */ 20 | public String templateId() { 21 | return templateId; 22 | } 23 | 24 | /** 25 | * @return The quantity to grant. 26 | */ 27 | public int quantity() { 28 | return quantity; 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /src/main/java/athena/fortnite/shop/price/CatalogPrice.java: -------------------------------------------------------------------------------- 1 | package athena.fortnite.shop.price; 2 | 3 | import java.time.Instant; 4 | 5 | /** 6 | * Represents the price for a catalog/item. 7 | */ 8 | public final class CatalogPrice { 9 | 10 | /** 11 | * Currency types and subtypes, ex: "MtxCurrency", "" 12 | */ 13 | private String currencyType, currencySubType; 14 | /** 15 | * Various prices of the item. 16 | */ 17 | private int regularPrice, dynamicRegularPrice, finalPrice, basePrice; 18 | /** 19 | * When this sale expires. 20 | */ 21 | private Instant saleExpiration; 22 | 23 | /** 24 | * @return the currency type. 25 | */ 26 | public String currencyType() { 27 | return currencyType; 28 | } 29 | 30 | /** 31 | * @return the currency sub-type. 32 | */ 33 | public String currencySubType() { 34 | return currencySubType; 35 | } 36 | 37 | /** 38 | * @return the regular price. 39 | */ 40 | public int regularPrice() { 41 | return regularPrice; 42 | } 43 | 44 | /** 45 | * @return the dynamic regular price 46 | */ 47 | public int dynamicRegularPrice() { 48 | return dynamicRegularPrice; 49 | } 50 | 51 | /** 52 | * @return the final price. 53 | */ 54 | public int finalPrice() { 55 | return finalPrice; 56 | } 57 | 58 | /** 59 | * @return the base price. 60 | */ 61 | public int basePrice() { 62 | return basePrice; 63 | } 64 | 65 | /** 66 | * @return when the sale expires. 67 | */ 68 | public Instant saleExpiration() { 69 | return saleExpiration; 70 | } 71 | } 72 | -------------------------------------------------------------------------------- /src/main/java/athena/fortnite/shop/requirement/CatalogEntryRequirement.java: -------------------------------------------------------------------------------- 1 | package athena.fortnite.shop.requirement; 2 | 3 | /** 4 | * Represents requirements for the catalog entry. 5 | */ 6 | public final class CatalogEntryRequirement { 7 | 8 | /** 9 | * Requirement type and the ID. 10 | */ 11 | private String requirementType, requiredId; 12 | /** 13 | * Minimal quantity required. 14 | */ 15 | private int minQuantity; 16 | 17 | /** 18 | * @return the requirement-type. 19 | */ 20 | public String requirementType() { 21 | return requirementType; 22 | } 23 | 24 | /** 25 | * @return the required ID. 26 | */ 27 | public String requiredId() { 28 | return requiredId; 29 | } 30 | 31 | /** 32 | * @return the minimum quantity. 33 | */ 34 | public int minQuantity() { 35 | return minQuantity; 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /src/main/java/athena/friend/resource/blocked/Blocked.java: -------------------------------------------------------------------------------- 1 | package athena.friend.resource.blocked; 2 | 3 | /** 4 | * Represents a blocked account ID. 5 | */ 6 | public final class Blocked { 7 | 8 | /** 9 | * The account ID. 10 | */ 11 | private String accountId; 12 | 13 | private Blocked() { 14 | } 15 | 16 | /** 17 | * @return the account ID of this blocked account. 18 | */ 19 | public String accountId() { 20 | return accountId; 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /src/main/java/athena/friend/resource/settings/FriendSettings.java: -------------------------------------------------------------------------------- 1 | package athena.friend.resource.settings; 2 | 3 | /** 4 | * Represents friend settings. 5 | * Currently only one field known right now "acceptInvites" 6 | */ 7 | public final class FriendSettings { 8 | 9 | /** 10 | * "public" or "private" 11 | */ 12 | private String acceptInvites; 13 | 14 | /** 15 | * @param acceptInvites either "public" or "private" 16 | */ 17 | public FriendSettings(String acceptInvites) { 18 | this.acceptInvites = acceptInvites; 19 | } 20 | 21 | /** 22 | * @return the accept invites value. 23 | */ 24 | public String acceptInvites() { 25 | return acceptInvites; 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /src/main/java/athena/friend/resource/summary/Summary.java: -------------------------------------------------------------------------------- 1 | package athena.friend.resource.summary; 2 | 3 | import athena.friend.resource.settings.FriendSettings; 4 | import athena.friend.resource.summary.types.BasicFriend; 5 | 6 | import java.util.List; 7 | 8 | /** 9 | * Represents a summary response from {@link athena.friend.service.FriendsPublicService} 10 | */ 11 | public final class Summary { 12 | 13 | /** 14 | * List of friend summaries. 15 | */ 16 | private List friends; 17 | 18 | /** 19 | * List of incoming friends, outgoing suggested and the blocklist. 20 | */ 21 | private List incoming, outgoing, suggested, blocklist; 22 | 23 | /** 24 | * Friend settings. 25 | */ 26 | private FriendSettings settings; 27 | 28 | /** 29 | * @return list of friend summaries. 30 | */ 31 | public List friends() { 32 | return friends; 33 | } 34 | 35 | /** 36 | * Get a profile that has the {@code accountId} 37 | * 38 | * @param accountId the account ID 39 | * @return the profile or {@code null} if not found. 40 | */ 41 | public Profile profileFromAccountId(String accountId) { 42 | return friends.stream().filter(profile -> profile.accountId().equals(accountId)).findAny().orElse(null); 43 | } 44 | 45 | /** 46 | * Get a profile that has the {@code displayName} 47 | * 48 | * @param displayName the display name 49 | * @return the profile or {@code null} if not found. 50 | */ 51 | public Profile profileFromDisplayName(String displayName) { 52 | return friends.stream().filter(profile -> profile.displayName().equals(displayName)).findAny().orElse(null); 53 | } 54 | 55 | /** 56 | * @return list of incoming friend requests. 57 | */ 58 | public List incoming() { 59 | return incoming; 60 | } 61 | 62 | /** 63 | * @return list of outgoing friend requests. 64 | */ 65 | public List outgoing() { 66 | return outgoing; 67 | } 68 | 69 | /** 70 | * @return list of suggested friends. 71 | */ 72 | public List suggested() { 73 | return suggested; 74 | } 75 | 76 | /** 77 | * @return the blocklist. 78 | */ 79 | public List blocklist() { 80 | return blocklist; 81 | } 82 | 83 | /** 84 | * @return the friend settings. 85 | */ 86 | public FriendSettings settings() { 87 | return settings; 88 | } 89 | 90 | /** 91 | * @return the accept invites setting. 92 | */ 93 | public String acceptInvites() { 94 | return settings.acceptInvites(); 95 | } 96 | 97 | } 98 | -------------------------------------------------------------------------------- /src/main/java/athena/friend/resource/summary/types/BasicFriend.java: -------------------------------------------------------------------------------- 1 | package athena.friend.resource.summary.types; 2 | 3 | /** 4 | * Represents outgoing/incoming friend object. 5 | * TODO: Add method to accept? 6 | */ 7 | public final class BasicFriend { 8 | 9 | /** 10 | * The account ID and display name. 11 | * Display name is only ever present if the query ?displayNames=true is in the URL. 12 | */ 13 | private String accountId, displayName; 14 | /** 15 | * {@code true} if they are a favorite - unimplemented 16 | */ 17 | private boolean favorite; 18 | 19 | private BasicFriend() { 20 | } 21 | 22 | /** 23 | * @return the account ID. 24 | */ 25 | public String accountId() { 26 | return accountId; 27 | } 28 | 29 | /** 30 | * @return the display name. 31 | */ 32 | public String displayName() { 33 | return displayName; 34 | } 35 | 36 | /** 37 | * @return {@code true} if they are a favorite - unimplemented 38 | */ 39 | public boolean favorite() { 40 | return favorite; 41 | } 42 | 43 | } 44 | -------------------------------------------------------------------------------- /src/main/java/athena/friend/resource/types/FriendDirection.java: -------------------------------------------------------------------------------- 1 | package athena.friend.resource.types; 2 | 3 | /** 4 | * An constants of friend directions. 5 | */ 6 | public enum FriendDirection { 7 | 8 | OUTBOUND, INBOUND, UNKNOWN; 9 | 10 | /** 11 | * @return {@code true} if this friend request was sent by the current account. 12 | */ 13 | public boolean sent() { 14 | return this == OUTBOUND; 15 | } 16 | 17 | /** 18 | * @return {@code true} if this friend request was received by the friend. 19 | */ 20 | public boolean received() { 21 | return this == INBOUND; 22 | } 23 | 24 | } 25 | -------------------------------------------------------------------------------- /src/main/java/athena/friend/resource/types/FriendStatus.java: -------------------------------------------------------------------------------- 1 | package athena.friend.resource.types; 2 | 3 | /** 4 | * An constants of friend statuses. 5 | */ 6 | public enum FriendStatus { 7 | 8 | ACCEPTED, PENDING, UNKNOWN 9 | 10 | } 11 | -------------------------------------------------------------------------------- /src/main/java/athena/friend/xmpp/annotation/FriendEvent.java: -------------------------------------------------------------------------------- 1 | package athena.friend.xmpp.annotation; 2 | 3 | import java.lang.annotation.ElementType; 4 | import java.lang.annotation.Retention; 5 | import java.lang.annotation.RetentionPolicy; 6 | import java.lang.annotation.Target; 7 | 8 | /** 9 | * Annotation used for friend events. 10 | * Put the annotation above a method and then register it with 11 | * {@code athena.friend().registerEventListener} 12 | */ 13 | @Target(ElementType.METHOD) 14 | @Retention(RetentionPolicy.RUNTIME) 15 | public @interface FriendEvent { 16 | } 17 | -------------------------------------------------------------------------------- /src/main/java/athena/friend/xmpp/event/AbstractFriendEvent.java: -------------------------------------------------------------------------------- 1 | package athena.friend.xmpp.event; 2 | 3 | import athena.friend.xmpp.type.FriendType; 4 | import athena.friend.xmpp.types.friend.FriendApiObject; 5 | import athena.friend.xmpp.types.friend.Friendship; 6 | 7 | import java.time.Instant; 8 | 9 | /** 10 | * Used as a base for all friend events. 11 | */ 12 | public abstract class AbstractFriendEvent { 13 | 14 | /** 15 | * The {@link Friendship} object. 16 | */ 17 | protected final Friendship friendship; 18 | /** 19 | * The {@link FriendApiObject} object. 20 | */ 21 | protected final FriendApiObject friendApiObject; 22 | 23 | /** 24 | * Account ID of this event. 25 | */ 26 | protected final String accountId; 27 | /** 28 | * Timestamp of the event. 29 | */ 30 | protected final Instant timestamp; 31 | /** 32 | * The friend-type. 33 | */ 34 | protected final FriendType friendType; 35 | 36 | public AbstractFriendEvent(Friendship friendship, FriendType friendType) { 37 | this.friendship = friendship; 38 | this.friendApiObject = null; 39 | this.friendType = friendType; 40 | 41 | this.accountId = friendship.from(); 42 | this.timestamp = friendship.timestamp(); 43 | } 44 | 45 | public AbstractFriendEvent(FriendApiObject friendApiObject, FriendType friendType) { 46 | this.friendApiObject = friendApiObject; 47 | this.friendship = null; 48 | this.friendType = friendType; 49 | 50 | this.accountId = friendApiObject.accountId(); 51 | this.timestamp = friendApiObject.timestamp(); 52 | } 53 | 54 | /** 55 | * @return the friendship object, or {@code null} if this event was initialized with {@link FriendApiObject} 56 | */ 57 | public Friendship friendship() { 58 | return friendship; 59 | } 60 | 61 | /** 62 | * @return the friend-type object, or {@code null} if this event was initialized with {@link Friendship} 63 | */ 64 | public FriendApiObject friendType() { 65 | return friendApiObject; 66 | } 67 | 68 | /** 69 | * @return the account ID. 70 | */ 71 | public String accountId() { 72 | return accountId; 73 | } 74 | 75 | /** 76 | * @return the timestamp. 77 | */ 78 | public Instant timestamp() { 79 | return timestamp; 80 | } 81 | 82 | /** 83 | * @return the types type 84 | */ 85 | public FriendType type() { 86 | return friendType; 87 | } 88 | } 89 | -------------------------------------------------------------------------------- /src/main/java/athena/friend/xmpp/event/events/FriendAbortedEvent.java: -------------------------------------------------------------------------------- 1 | package athena.friend.xmpp.event.events; 2 | 3 | import athena.account.Accounts; 4 | import athena.account.resource.Account; 5 | import athena.friend.xmpp.event.AbstractFriendEvent; 6 | import athena.friend.xmpp.type.FriendType; 7 | import athena.friend.xmpp.types.friend.Friendship; 8 | import athena.util.json.request.Request; 9 | 10 | /** 11 | * An event for when somebody cancels their friend request. 12 | */ 13 | public final class FriendAbortedEvent extends AbstractFriendEvent { 14 | 15 | /** 16 | * The accounts provider. 17 | */ 18 | @Request(item = Accounts.class) 19 | private Accounts accounts; 20 | 21 | public FriendAbortedEvent(Friendship friendship, FriendType friendType) { 22 | super(friendship, friendType); 23 | } 24 | 25 | /** 26 | * Retrieve the account of this friend request. 27 | * 28 | * @return their account. 29 | */ 30 | public Account account() { 31 | return accounts.findByAccountId(accountId); 32 | } 33 | 34 | } -------------------------------------------------------------------------------- /src/main/java/athena/friend/xmpp/event/events/FriendAcceptedEvent.java: -------------------------------------------------------------------------------- 1 | package athena.friend.xmpp.event.events; 2 | 3 | import athena.account.Accounts; 4 | import athena.account.resource.Account; 5 | import athena.friend.resource.summary.Profile; 6 | import athena.friend.service.FriendsPublicService; 7 | import athena.friend.xmpp.event.AbstractFriendEvent; 8 | import athena.friend.xmpp.type.FriendType; 9 | import athena.friend.xmpp.types.friend.Friendship; 10 | import athena.util.json.request.Request; 11 | import athena.util.request.Requests; 12 | 13 | /** 14 | * An event for when a friend request is accepted. 15 | */ 16 | public final class FriendAcceptedEvent extends AbstractFriendEvent { 17 | 18 | /** 19 | * The local account 20 | */ 21 | @Request(item = Account.class, local = true) 22 | private Account account; 23 | 24 | /** 25 | * The accounts provider. 26 | */ 27 | @Request(item = Accounts.class) 28 | private Accounts accounts; 29 | 30 | /** 31 | * The friends public service 32 | */ 33 | @Request(item = FriendsPublicService.class) 34 | private FriendsPublicService service; 35 | 36 | public FriendAcceptedEvent(Friendship friendship, FriendType friendType) { 37 | super(friendship, friendType); 38 | } 39 | 40 | /** 41 | * Retrieve the account of this friend request. 42 | * 43 | * @return their account. 44 | */ 45 | public Account account() { 46 | return accounts.findByAccountId(accountId); 47 | } 48 | 49 | /** 50 | * @return their profile 51 | */ 52 | public Profile profile() { 53 | return Requests.executeCall(service.profile(account.accountId(), accountId, true)); 54 | } 55 | 56 | } 57 | -------------------------------------------------------------------------------- /src/main/java/athena/friend/xmpp/event/events/FriendDeletedEvent.java: -------------------------------------------------------------------------------- 1 | package athena.friend.xmpp.event.events; 2 | 3 | import athena.account.Accounts; 4 | import athena.account.resource.Account; 5 | import athena.friend.xmpp.event.AbstractFriendEvent; 6 | import athena.friend.xmpp.type.FriendType; 7 | import athena.friend.xmpp.types.friend.FriendApiObject; 8 | import athena.util.json.request.Request; 9 | 10 | /** 11 | * An event for when a friend is deleted. 12 | */ 13 | public final class FriendDeletedEvent extends AbstractFriendEvent { 14 | 15 | /** 16 | * The accounts provider. 17 | */ 18 | @Request(item = Accounts.class) 19 | private Accounts accounts; 20 | 21 | public FriendDeletedEvent(FriendApiObject friendApiObject, FriendType friendType) { 22 | super(friendApiObject, friendType); 23 | } 24 | 25 | /** 26 | * Retrieve the account of this event. 27 | * 28 | * @return their account. 29 | */ 30 | public Account account() { 31 | return accounts.findByAccountId(accountId); 32 | } 33 | 34 | } 35 | -------------------------------------------------------------------------------- /src/main/java/athena/friend/xmpp/event/events/FriendRejectedEvent.java: -------------------------------------------------------------------------------- 1 | package athena.friend.xmpp.event.events; 2 | 3 | import athena.account.Accounts; 4 | import athena.account.resource.Account; 5 | import athena.friend.xmpp.event.AbstractFriendEvent; 6 | import athena.friend.xmpp.type.FriendType; 7 | import athena.friend.xmpp.types.friend.Friendship; 8 | import athena.util.json.request.Request; 9 | 10 | /** 11 | * An event for when somebody rejects the friend request. 12 | */ 13 | public final class FriendRejectedEvent extends AbstractFriendEvent { 14 | 15 | /** 16 | * The accounts provider. 17 | */ 18 | @Request(item = Accounts.class) 19 | private Accounts accounts; 20 | 21 | public FriendRejectedEvent(Friendship friendship, FriendType friendType) { 22 | super(friendship, friendType); 23 | } 24 | 25 | /** 26 | * Retrieve the account of this friend request. 27 | * 28 | * @return their account. 29 | */ 30 | public Account account() { 31 | return accounts.findByAccountId(accountId); 32 | } 33 | 34 | } 35 | -------------------------------------------------------------------------------- /src/main/java/athena/friend/xmpp/event/events/FriendRequestEvent.java: -------------------------------------------------------------------------------- 1 | package athena.friend.xmpp.event.events; 2 | 3 | import athena.account.Accounts; 4 | import athena.account.resource.Account; 5 | import athena.friend.resource.summary.Profile; 6 | import athena.friend.service.FriendsPublicService; 7 | import athena.friend.xmpp.event.AbstractFriendEvent; 8 | import athena.friend.xmpp.type.FriendType; 9 | import athena.friend.xmpp.types.friend.FriendApiObject; 10 | import athena.util.json.request.Request; 11 | import athena.util.request.Requests; 12 | 13 | /** 14 | * An event that is invoked when a friend request is received. 15 | */ 16 | public final class FriendRequestEvent extends AbstractFriendEvent { 17 | 18 | /** 19 | * The local account 20 | */ 21 | @Request(item = Account.class, local = true) 22 | private Account account; 23 | 24 | /** 25 | * The accounts provider. 26 | */ 27 | @Request(item = Accounts.class) 28 | private Accounts accounts; 29 | 30 | /** 31 | * The friends service 32 | */ 33 | @Request(item = FriendsPublicService.class) 34 | private FriendsPublicService friendsPublicService; 35 | 36 | public FriendRequestEvent(FriendApiObject friendApiObject, FriendType friendType) { 37 | super(friendApiObject, friendType); 38 | } 39 | 40 | /** 41 | * Retrieve the account of this friend request. 42 | * 43 | * @return their account. 44 | */ 45 | public Account account() { 46 | return accounts.findByAccountId(accountId); 47 | } 48 | 49 | /** 50 | * Accept the friend request. 51 | * 52 | * @return their profile, or {@code null} if none was found. 53 | */ 54 | public Profile accept() { 55 | Requests.executeVoidCall(friendsPublicService.add(account.accountId(), accountId)); 56 | return Requests.executeCall(friendsPublicService.profile(account.accountId(), accountId, true)); 57 | } 58 | 59 | 60 | /** 61 | * Decline the friend request. 62 | */ 63 | public void decline() { 64 | Requests.executeVoidCall(friendsPublicService.remove(account.accountId(), accountId)); 65 | } 66 | 67 | } 68 | -------------------------------------------------------------------------------- /src/main/java/athena/friend/xmpp/listener/FriendEventListener.java: -------------------------------------------------------------------------------- 1 | package athena.friend.xmpp.listener; 2 | 3 | import athena.friend.xmpp.event.events.*; 4 | import athena.friend.xmpp.types.blocklist.BlockListEntry; 5 | import athena.friend.xmpp.types.blocklist.BlockListUpdate; 6 | 7 | /** 8 | * Interface used to listen for friend events. 9 | */ 10 | public interface FriendEventListener { 11 | 12 | /** 13 | * Invoked when a friend request is received. 14 | * 15 | * @param event the event. 16 | */ 17 | default void friendRequest(FriendRequestEvent event) { 18 | } 19 | 20 | /** 21 | * Invoked when a friend removes you. 22 | * 23 | * @param event the event. 24 | */ 25 | default void friendDeleted(FriendDeletedEvent event) { 26 | } 27 | 28 | /** 29 | * Invoked when a friend rejects the friend request. 30 | * 31 | * @param event the event. 32 | */ 33 | default void friendRejected(FriendRejectedEvent event) { 34 | } 35 | 36 | /** 37 | * Invoked when a friend cancels their friend request. 38 | * 39 | * @param event the event. 40 | */ 41 | default void friendAborted(FriendAbortedEvent event) { 42 | } 43 | 44 | /** 45 | * Invoked when a friend accepts the friend request. 46 | * 47 | * @param event the event. 48 | */ 49 | default void friendAccepted(FriendAcceptedEvent event) { 50 | } 51 | 52 | /** 53 | * Invoked when a block list entry is removed. 54 | * Either method is fine to use 55 | * 56 | * @param blockListEntryApiObject the API object. 57 | */ 58 | default void blockListEntryRemoved(BlockListEntry blockListEntryApiObject) { 59 | 60 | } 61 | 62 | /** 63 | * Invoked when a block list entry is removed. 64 | * Either method is fine to use 65 | * 66 | * @param blockListUpdate the block list update. 67 | */ 68 | default void blockListEntryRemoved(BlockListUpdate blockListUpdate) { 69 | 70 | } 71 | 72 | /** 73 | * Invoked when a block list entry is added. 74 | * Either method is fine to use 75 | * 76 | * @param blockListEntryApiObject the API object. 77 | */ 78 | default void blockListEntryAdded(BlockListEntry blockListEntryApiObject) { 79 | 80 | } 81 | 82 | /** 83 | * Invoked when a block list entry is removed. 84 | * Either method is fine to use 85 | * 86 | * @param blockListUpdate the block list update. 87 | */ 88 | default void blockListEntryAdded(BlockListUpdate blockListUpdate) { 89 | 90 | } 91 | 92 | } 93 | -------------------------------------------------------------------------------- /src/main/java/athena/friend/xmpp/type/FriendType.java: -------------------------------------------------------------------------------- 1 | package athena.friend.xmpp.type; 2 | 3 | import java.util.List; 4 | 5 | /** 6 | * Represents a friend types type. 7 | */ 8 | public enum FriendType { 9 | 10 | /** 11 | * Indicates an entry was added to the blocklist. 12 | */ 13 | BLOCK_LIST_ENTRY_ADDED("com.epicgames.friends.core.apiobjects.BlockListEntryAdded"), 14 | /** 15 | * Indicates an entry was removed from the blocklist. 16 | */ 17 | BLOCK_LIST_ENTRY_REMOVED("com.epicgames.friends.core.apiobjects.BlockListEntryRemoved"), 18 | /** 19 | * Indicates a blocklist update. 20 | */ 21 | USER_BLOCKLIST_UPDATE("USER_BLOCKLIST_UPDATE"), 22 | /** 23 | * Indicates a friendship request. 24 | */ 25 | FRIENDSHIP_REQUEST("FRIENDSHIP_REQUEST"), 26 | /** 27 | * Indicates a friendship remove. 28 | */ 29 | FRIENDSHIP_REMOVE("FRIENDSHIP_REMOVE"), 30 | /** 31 | * Indicates a friendship remove. 32 | */ 33 | FRIEND_REMOVAL("com.epicgames.friends.core.apiobjects.FriendRemoval"), 34 | /** 35 | * Indicates a friendship action 36 | */ 37 | FRIEND("com.epicgames.friends.core.apiobjects.Friend"), 38 | /** 39 | * Default. 40 | */ 41 | UNKNOWN("UNKNOWN"); 42 | 43 | /** 44 | * List of types. 45 | */ 46 | private static final List TYPES = List.of(values()); 47 | /** 48 | * The type name. 49 | */ 50 | private final String type; 51 | 52 | FriendType(String type) { 53 | this.type = type; 54 | } 55 | 56 | public String type() { 57 | return type; 58 | } 59 | 60 | /** 61 | * Find the type. 62 | * 63 | * @param type the type 64 | * @return the types type. 65 | */ 66 | public static FriendType typeOf(String type) { 67 | return TYPES.stream().filter(friendType -> friendType.type.equalsIgnoreCase(type)).findAny().orElse(UNKNOWN); 68 | } 69 | 70 | } 71 | -------------------------------------------------------------------------------- /src/main/java/athena/friend/xmpp/types/blocklist/BlockListEntry.java: -------------------------------------------------------------------------------- 1 | package athena.friend.xmpp.types.blocklist; 2 | 3 | import java.time.Instant; 4 | 5 | /** 6 | * Represents a blocklist entry api object. 7 | */ 8 | public final class BlockListEntry { 9 | 10 | /** 11 | * The payload 12 | */ 13 | private Payload payload; 14 | /** 15 | * The timestamp 16 | */ 17 | private Instant timestamp; 18 | 19 | /** 20 | * @return The owner who did the blocklist update 21 | */ 22 | public String ownerId() { 23 | return payload.ownerId; 24 | } 25 | 26 | /** 27 | * @return who the blocklist update is for 28 | */ 29 | public String accountId() { 30 | return payload.accountId; 31 | } 32 | 33 | /** 34 | * @return the timestamp 35 | */ 36 | public Instant timestamp() { 37 | return timestamp; 38 | } 39 | 40 | private static final class Payload { 41 | /** 42 | * The owner who did the blocklist update 43 | * who the blocklist update is for 44 | */ 45 | private String ownerId, accountId; 46 | } 47 | 48 | } 49 | -------------------------------------------------------------------------------- /src/main/java/athena/friend/xmpp/types/blocklist/BlockListUpdate.java: -------------------------------------------------------------------------------- 1 | package athena.friend.xmpp.types.blocklist; 2 | 3 | import java.time.Instant; 4 | 5 | /** 6 | * Represents a blocklist update 7 | */ 8 | public final class BlockListUpdate { 9 | 10 | /** 11 | * The owner who did the blocklist update 12 | * who the blocklist update is for 13 | * the status, "BLOCKED" "UNBLOCKED" 14 | */ 15 | private String ownerId, accountId, status; 16 | /** 17 | * The timestamp. 18 | */ 19 | private Instant timestamp; 20 | 21 | /** 22 | * @return The owner who did the blocklist update 23 | */ 24 | public String ownerId() { 25 | return ownerId; 26 | } 27 | 28 | /** 29 | * @return who the blocklist update is for 30 | */ 31 | public String accountId() { 32 | return accountId; 33 | } 34 | 35 | /** 36 | * @return the status "BLOCKED" "UNBLOCKED" 37 | */ 38 | public String status() { 39 | return status; 40 | } 41 | 42 | /** 43 | * @return the timestamp 44 | */ 45 | public Instant timestamp() { 46 | return timestamp; 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /src/main/java/athena/friend/xmpp/types/friend/FriendApiObject.java: -------------------------------------------------------------------------------- 1 | package athena.friend.xmpp.types.friend; 2 | 3 | import com.google.gson.annotations.SerializedName; 4 | 5 | import java.time.Instant; 6 | 7 | /** 8 | * Provides support for the "com.epicgames.friends.core.apiobjects.Friend" type. 9 | */ 10 | public final class FriendApiObject { 11 | 12 | /** 13 | * The type "com.epicgames.friends.core.apiobjects.Friend" 14 | */ 15 | private String type; 16 | /** 17 | * The timestamp 18 | */ 19 | private Instant timestamp; 20 | 21 | /** 22 | * The payload. 23 | */ 24 | private Payload payload; 25 | 26 | /** 27 | * @return the type. 28 | */ 29 | public String type() { 30 | return type; 31 | } 32 | 33 | /** 34 | * @return the timestamp. 35 | */ 36 | public Instant timestamp() { 37 | return timestamp; 38 | } 39 | 40 | /** 41 | * @return the account ID of who its from. 42 | */ 43 | public String accountId() { 44 | return payload.accountId; 45 | } 46 | 47 | /** 48 | * @return the direction 49 | */ 50 | public String direction() { 51 | return payload.direction; 52 | } 53 | 54 | /** 55 | * @return when it was created. 56 | */ 57 | public Instant created() { 58 | return payload.created; 59 | } 60 | 61 | /** 62 | * @return the status or reason 63 | */ 64 | public String status() { 65 | return payload.status; 66 | } 67 | 68 | /** 69 | * @return {@code true} if they are a favorite. 70 | */ 71 | public boolean favorite() { 72 | return payload.favorite; 73 | } 74 | 75 | private static final class Payload { 76 | 77 | /** 78 | * "XXX", 79 | * "OUTBOUND/INBOUND", 80 | * UTC created. 81 | */ 82 | private String accountId, direction; 83 | /** 84 | * When it was created. 85 | */ 86 | private Instant created; 87 | /** 88 | * Status/reason, ex: "PENDING"/"REJECTED" 89 | */ 90 | @SerializedName(value = "status", alternate = {"reason"}) 91 | private String status; 92 | 93 | /** 94 | * {@code true} if they are a favorite. 95 | */ 96 | private boolean favorite; 97 | } 98 | 99 | } 100 | -------------------------------------------------------------------------------- /src/main/java/athena/friend/xmpp/types/friend/Friendship.java: -------------------------------------------------------------------------------- 1 | package athena.friend.xmpp.types.friend; 2 | 3 | import com.google.gson.annotations.SerializedName; 4 | 5 | import java.time.Instant; 6 | 7 | /** 8 | * Provides support for the "FRIENDSHIP_XXX" type. 9 | */ 10 | public final class Friendship { 11 | 12 | /** 13 | * FRIENDSHIP_XXX 14 | * who its from 15 | * who its to 16 | * the timestamp 17 | */ 18 | private String type, from, to; 19 | 20 | /** 21 | * The timestamp. 22 | */ 23 | private Instant timestamp; 24 | 25 | /** 26 | * Status/reason, ex: "PENDING"/"REJECTED" 27 | */ 28 | @SerializedName(value = "status", alternate = {"reason"}) 29 | private String status; 30 | 31 | /** 32 | * @return the type 33 | */ 34 | public String type() { 35 | return type; 36 | } 37 | 38 | /** 39 | * @return who its from 40 | */ 41 | public String from() { 42 | return from; 43 | } 44 | 45 | /** 46 | * @return who its to 47 | */ 48 | public String to() { 49 | return to; 50 | } 51 | 52 | /** 53 | * @return the timestamp 54 | */ 55 | public Instant timestamp() { 56 | return timestamp; 57 | } 58 | 59 | /** 60 | * @return the status or reason. 61 | */ 62 | public String status() { 63 | return status; 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /src/main/java/athena/groups/application/GroupApplication.java: -------------------------------------------------------------------------------- 1 | package athena.groups.application; 2 | 3 | import java.time.Instant; 4 | 5 | /** 6 | * Represents a group application. 7 | */ 8 | public final class GroupApplication { 9 | 10 | /** 11 | * The account ID of who applied. 12 | * The group ID 13 | * the namespace, "kairos" 14 | * the name of the group. 15 | */ 16 | private String accountId, groupId, namespace, name; 17 | /** 18 | * When the application was sent. 19 | */ 20 | private Instant sentAt; 21 | 22 | private GroupApplication() {} 23 | 24 | /** 25 | * @return The account ID of who applied. 26 | */ 27 | public String accountId() { 28 | return accountId; 29 | } 30 | 31 | /** 32 | * Not always present if this object is a response from submitting an application. 33 | * 34 | * @return the group ID. 35 | */ 36 | public String groupId() { 37 | return groupId; 38 | } 39 | 40 | /** 41 | * Not always present if this object is a response from submitting an application. 42 | * 43 | * @return the namespace 44 | */ 45 | public String namespace() { 46 | return namespace; 47 | } 48 | 49 | /** 50 | * Not always present if this object is a response from submitting an application. 51 | * 52 | * @return the name of the group, or {@code null} 53 | */ 54 | public String name() { 55 | return name; 56 | } 57 | 58 | /** 59 | * @return When the application was sent. 60 | */ 61 | public Instant sentAt() { 62 | return sentAt; 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /src/main/java/athena/groups/application/response/GroupApplicationsResponse.java: -------------------------------------------------------------------------------- 1 | package athena.groups.application.response; 2 | 3 | import athena.groups.application.GroupApplication; 4 | import athena.groups.paging.Pageable; 5 | 6 | import java.util.List; 7 | 8 | /** 9 | * Represents group applications response 10 | */ 11 | public final class GroupApplicationsResponse extends Pageable { 12 | 13 | /** 14 | * List of group applications. 15 | */ 16 | private List elements; 17 | 18 | private GroupApplicationsResponse() {} 19 | 20 | /** 21 | * @return list of applications 22 | */ 23 | public List applications() { 24 | return elements; 25 | } 26 | 27 | /** 28 | * Get a {@link GroupApplication} by {@code groupName} 29 | * 30 | * @param groupName the group name. 31 | * @return the {@link GroupApplication} if found or {@code null} 32 | */ 33 | public GroupApplication getByName(String groupName) { 34 | return elements 35 | .stream() 36 | .filter(groupApplication -> groupApplication.name().equals(groupName)) 37 | .findAny() 38 | .orElse(null); 39 | } 40 | 41 | /** 42 | * Get a {@link GroupApplication} by {@code groupId} 43 | * 44 | * @param groupId the group ID. 45 | * @return the {@link GroupApplication} if found or {@code null} 46 | */ 47 | public GroupApplication getById(String groupId) { 48 | return elements 49 | .stream() 50 | .filter(groupApplication -> groupApplication.groupId().equals(groupId)) 51 | .findAny() 52 | .orElse(null); 53 | } 54 | 55 | /** 56 | * @return count of applications 57 | */ 58 | public int countApplications() { 59 | return count(); 60 | } 61 | 62 | /** 63 | * @return start index? 64 | */ 65 | public int startApplications() { 66 | return start(); 67 | } 68 | 69 | /** 70 | * @return total number of applications 71 | */ 72 | public int totalApplications() { 73 | return total(); 74 | } 75 | 76 | } 77 | -------------------------------------------------------------------------------- /src/main/java/athena/groups/invitation/GroupInvitation.java: -------------------------------------------------------------------------------- 1 | package athena.groups.invitation; 2 | 3 | import java.time.Instant; 4 | 5 | /** 6 | * Represents a group invitation. 7 | */ 8 | public final class GroupInvitation { 9 | 10 | /** 11 | * Account ID of who the invite is to. 12 | * The group host account ID 13 | * The join message if any. 14 | * the group ID 15 | * the namespace, "kairos" 16 | * the name of the group 17 | */ 18 | private String accountId, groupHost, message, groupId, namespace, name; 19 | 20 | /** 21 | * When the invite was sent. 22 | */ 23 | private Instant sentAt; 24 | 25 | private GroupInvitation() { 26 | } 27 | 28 | /** 29 | * @return Account ID of who the invite is to. 30 | */ 31 | public String accountId() { 32 | return accountId; 33 | } 34 | 35 | /** 36 | * @return The group host account ID 37 | */ 38 | public String groupHost() { 39 | return groupHost; 40 | } 41 | 42 | /** 43 | * @return the join message, or {@code null} 44 | */ 45 | public String message() { 46 | return message; 47 | } 48 | 49 | /** 50 | * @return the group ID. 51 | */ 52 | public String groupId() { 53 | return groupId; 54 | } 55 | 56 | /** 57 | * @return the namespace 58 | */ 59 | public String namespace() { 60 | return namespace; 61 | } 62 | 63 | /** 64 | * @return the name of the group invited to 65 | */ 66 | public String name() { 67 | return name; 68 | } 69 | 70 | /** 71 | * @return when the invite was sent. 72 | */ 73 | public Instant sentAt() { 74 | return sentAt; 75 | } 76 | } 77 | -------------------------------------------------------------------------------- /src/main/java/athena/groups/invitation/response/GroupInvitationsResponse.java: -------------------------------------------------------------------------------- 1 | package athena.groups.invitation.response; 2 | 3 | import athena.groups.invitation.GroupInvitation; 4 | import athena.groups.paging.Pageable; 5 | 6 | import java.util.List; 7 | 8 | /** 9 | * Represents a group invitation response. 10 | */ 11 | public final class GroupInvitationsResponse extends Pageable { 12 | 13 | /** 14 | * List of group invitations 15 | */ 16 | private List elements; 17 | 18 | private GroupInvitationsResponse() { 19 | } 20 | 21 | 22 | /** 23 | * @return list of invitations 24 | */ 25 | public List invitations() { 26 | return elements; 27 | } 28 | 29 | /** 30 | * Get a {@link GroupInvitation} by {@code groupName} 31 | * 32 | * @param groupName the group name. 33 | * @return the {@link GroupInvitation} if found or {@code null} 34 | */ 35 | public GroupInvitation getByName(String groupName) { 36 | return elements 37 | .stream() 38 | .filter(groupInvitation -> groupInvitation.name().equals(groupName)) 39 | .findAny() 40 | .orElse(null); 41 | } 42 | 43 | /** 44 | * Get a {@link GroupInvitation} by {@code groupId} 45 | * 46 | * @param groupId the group ID. 47 | * @return the {@link GroupInvitation} if found or {@code null} 48 | */ 49 | public GroupInvitation getById(String groupId) { 50 | return elements 51 | .stream() 52 | .filter(groupInvitation -> groupInvitation.groupId().equals(groupId)) 53 | .findAny() 54 | .orElse(null); 55 | } 56 | 57 | /** 58 | * @return count of invitations 59 | */ 60 | public int countinvitations() { 61 | return count(); 62 | } 63 | 64 | /** 65 | * @return start index? 66 | */ 67 | public int startinvitations() { 68 | return start(); 69 | } 70 | 71 | /** 72 | * @return total number of invitations 73 | */ 74 | public int totalinvitations() { 75 | return total(); 76 | } 77 | } 78 | -------------------------------------------------------------------------------- /src/main/java/athena/groups/membership/GroupMember.java: -------------------------------------------------------------------------------- 1 | package athena.groups.membership; 2 | 3 | import java.time.Instant; 4 | 5 | /** 6 | * Represents a group member. 7 | */ 8 | public final class GroupMember { 9 | 10 | /** 11 | * The account ID of the member. 12 | */ 13 | private String accountId; 14 | 15 | /** 16 | * If the member is an admin or owner. 17 | */ 18 | private boolean admin, isOwner; 19 | 20 | /** 21 | * When this member joined the group. 22 | */ 23 | private Instant joinedAt; 24 | 25 | /** 26 | * @return the account ID of this member. 27 | */ 28 | public String accountId() { 29 | return accountId; 30 | } 31 | 32 | /** 33 | * @return {@code true} if this member is an admin. 34 | */ 35 | public boolean admin() { 36 | return admin; 37 | } 38 | 39 | /** 40 | * @return {@code true} if this member is an owner. 41 | */ 42 | public boolean isOwner() { 43 | return isOwner; 44 | } 45 | 46 | /** 47 | * @return when this member joined the group. 48 | */ 49 | public Instant joinedAt() { 50 | return joinedAt; 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /src/main/java/athena/groups/membership/MembershipOf.java: -------------------------------------------------------------------------------- 1 | package athena.groups.membership; 2 | 3 | import com.google.gson.JsonObject; 4 | import com.google.gson.annotations.SerializedName; 5 | 6 | import java.time.Instant; 7 | import java.util.List; 8 | 9 | /** 10 | * Represents a group somebody is a member of 11 | */ 12 | public final class MembershipOf { 13 | 14 | /** 15 | * The account ID 16 | * The group ID 17 | * the name of the group. 18 | */ 19 | private String accountId, groupId, name; 20 | 21 | /** 22 | * The group owner account ID. 23 | */ 24 | @SerializedName("owner") 25 | private String ownerId; 26 | 27 | /** 28 | * {@code true} if the provided account ID is admin 29 | * {@code true} if the provided account ID is owner. 30 | */ 31 | private boolean admin, isOwner; 32 | 33 | /** 34 | * When the provided account ID joined. 35 | */ 36 | private Instant joinedAt; 37 | 38 | /** 39 | * The group size. 40 | */ 41 | private int size; 42 | 43 | /** 44 | * TODO: 45 | */ 46 | private JsonObject metadata; 47 | 48 | /** 49 | * List of "top oldest members" for this group. 50 | */ 51 | private List topOldestMembers; 52 | 53 | /** 54 | * @return the account ID of this membership 55 | */ 56 | public String accountId() { 57 | return accountId; 58 | } 59 | 60 | /** 61 | * @return the group ID this member is in. 62 | */ 63 | public String groupId() { 64 | return groupId; 65 | } 66 | 67 | /** 68 | * @return the name of the group this member is in. 69 | */ 70 | public String name() { 71 | return name; 72 | } 73 | 74 | /** 75 | * @return the owner account ID of the group. 76 | */ 77 | public String ownerId() { 78 | return ownerId; 79 | } 80 | 81 | /** 82 | * @return {@code true} if the provided account ID is admin. 83 | */ 84 | public boolean admin() { 85 | return admin; 86 | } 87 | 88 | /** 89 | * @return {@code true} if the provided account ID is owner. 90 | */ 91 | public boolean isOwner() { 92 | return isOwner; 93 | } 94 | 95 | /** 96 | * @return when this member joined. 97 | */ 98 | public Instant joinedAt() { 99 | return joinedAt; 100 | } 101 | 102 | /** 103 | * @return the size of the group. 104 | */ 105 | public int size() { 106 | return size; 107 | } 108 | 109 | /** 110 | * TODO: Metadata. 111 | * 112 | * @return ?? 113 | */ 114 | public JsonObject metadata() { 115 | return metadata; 116 | } 117 | 118 | /** 119 | * @return list of "top oldest members" ? 120 | */ 121 | public List topOldestMembers() { 122 | return topOldestMembers; 123 | } 124 | } 125 | 126 | -------------------------------------------------------------------------------- /src/main/java/athena/groups/membership/response/GroupsMembershipResponse.java: -------------------------------------------------------------------------------- 1 | package athena.groups.membership.response; 2 | 3 | import athena.groups.membership.MembershipOf; 4 | import athena.groups.paging.Pageable; 5 | import com.google.gson.annotations.SerializedName; 6 | 7 | import java.util.List; 8 | 9 | /** 10 | * Represents a response when you query the membership of an account ID. 11 | */ 12 | public final class GroupsMembershipResponse extends Pageable { 13 | 14 | /** 15 | * List of groups the member is in. 16 | */ 17 | @SerializedName("elements") 18 | private List membership; 19 | 20 | /** 21 | * Get a {@link MembershipOf} by {@code groupId} 22 | * 23 | * @param groupId the ID of the group. 24 | * @return the {@link MembershipOf} or {@code null} 25 | */ 26 | public MembershipOf getById(String groupId) { 27 | return membership.stream().filter(group -> group.groupId().equals(groupId)).findAny().orElse(null); 28 | } 29 | 30 | /** 31 | * Get a {@link MembershipOf} by {@code groupName} 32 | * 33 | * @param groupName the group name. 34 | * @return the {@link MembershipOf} or {@code null} 35 | */ 36 | public MembershipOf getByName(String groupName) { 37 | return membership.stream().filter(group -> group.name().equals(groupName)).findAny().orElse(null); 38 | } 39 | 40 | /** 41 | * @return count of groups. 42 | */ 43 | public int countGroups() { 44 | return count(); 45 | } 46 | 47 | /** 48 | * @return start index? 49 | */ 50 | public int startGroups() { 51 | return start(); 52 | } 53 | 54 | /** 55 | * @return total number of groups 56 | */ 57 | public int totalGroups() { 58 | return total(); 59 | } 60 | 61 | } 62 | -------------------------------------------------------------------------------- /src/main/java/athena/groups/paging/Pageable.java: -------------------------------------------------------------------------------- 1 | package athena.groups.paging; 2 | 3 | /** 4 | * Abstract class providing paging support 5 | */ 6 | public abstract class Pageable { 7 | 8 | /** 9 | * The paging 10 | */ 11 | private Paging paging; 12 | 13 | /** 14 | * @return count of groups. 15 | */ 16 | public int count() { 17 | return paging.count; 18 | } 19 | 20 | /** 21 | * @return start index? 22 | */ 23 | public int start() { 24 | return paging.start; 25 | } 26 | 27 | /** 28 | * @return total number 29 | */ 30 | public int total() { 31 | return paging.total; 32 | } 33 | 34 | private static final class Paging { 35 | 36 | /** 37 | * Count 38 | * Starting point 39 | * Total 40 | */ 41 | private int count, start, total; 42 | 43 | } 44 | 45 | } 46 | -------------------------------------------------------------------------------- /src/main/java/athena/groups/privacy/GroupPrivacy.java: -------------------------------------------------------------------------------- 1 | package athena.groups.privacy; 2 | 3 | /** 4 | * Represents group privacy. 5 | */ 6 | public enum GroupPrivacy { 7 | 8 | PUBLIC, PRIVATE 9 | 10 | } 11 | -------------------------------------------------------------------------------- /src/main/java/athena/groups/requests/creating/CreateGroupRequest.java: -------------------------------------------------------------------------------- 1 | package athena.groups.requests.creating; 2 | 3 | import athena.groups.privacy.GroupPrivacy; 4 | 5 | /** 6 | * A request used to create a group. 7 | * 8 | * @author Vrekt, Armisto 9 | */ 10 | public final class CreateGroupRequest { 11 | 12 | /** 13 | * The name, motto, description and language of this group. 14 | */ 15 | private String name, motto, description, lang, mode; 16 | 17 | /** 18 | * Static factory method to create a new {@link CreateGroupRequest} 19 | * 20 | * @param name the name of the group. 21 | * @return a new {@link CreateGroupRequest} 22 | */ 23 | public static CreateGroupRequest create(String name) { 24 | return new CreateGroupRequest(name, name, name, "en", GroupPrivacy.PUBLIC); 25 | } 26 | 27 | /** 28 | * Static factory method to create a new {@link CreateGroupRequest} 29 | * 30 | * @param name the name of the group. 31 | * @param motto the motto of the group. 32 | * @param description the description of the group. 33 | * @return a new {@link CreateGroupRequest} 34 | */ 35 | public static CreateGroupRequest create(String name, String motto, String description) { 36 | return new CreateGroupRequest(name, motto, description, "en", GroupPrivacy.PUBLIC); 37 | } 38 | 39 | /** 40 | * Static factory method to create a new {@link CreateGroupRequest} 41 | * 42 | * @param name the name of the group. 43 | * @param motto the motto of the group. 44 | * @param description the description of the group. 45 | * @param lang the language of the group, "en" for example 46 | * @return a new {@link CreateGroupRequest} 47 | */ 48 | public static CreateGroupRequest create(String name, String motto, String description, String lang) { 49 | return new CreateGroupRequest(name, motto, description, lang, GroupPrivacy.PUBLIC); 50 | } 51 | 52 | /** 53 | * Static factory method to create a new {@link CreateGroupRequest} 54 | * 55 | * @param name the name of the group. 56 | * @param motto the motto of the group. 57 | * @param description the description of the group. 58 | * @param lang the language of the group, "en" for example 59 | * @param privacy the privacy of the group - cannot be changed later. 60 | * @return a new {@link CreateGroupRequest} 61 | */ 62 | public static CreateGroupRequest create(String name, String motto, String description, String lang, GroupPrivacy privacy) { 63 | return new CreateGroupRequest(name, motto, description, lang, privacy); 64 | } 65 | 66 | private CreateGroupRequest(String name, String motto, String description, String lang, GroupPrivacy privacy) { 67 | this.name = name; 68 | this.motto = motto; 69 | this.description = description; 70 | this.lang = lang; 71 | this.mode = privacy.name(); 72 | } 73 | 74 | } 75 | -------------------------------------------------------------------------------- /src/main/java/athena/groups/requests/invitation/GroupInvitationRequest.java: -------------------------------------------------------------------------------- 1 | package athena.groups.requests.invitation; 2 | 3 | /** 4 | * A request used to invite another member. 5 | * TODO: Might need more to work 6 | * 7 | * @author Vrekt, Armisto 8 | */ 9 | public final class GroupInvitationRequest { 10 | 11 | /** 12 | * The invite message. 13 | */ 14 | private String message; 15 | 16 | /** 17 | * Static factory method to create a new {@link GroupInvitationRequest} 18 | * 19 | * @param message the invite message 20 | * @return a new {@link GroupInvitationRequest} 21 | */ 22 | public static GroupInvitationRequest create(String message) { 23 | return new GroupInvitationRequest(message); 24 | } 25 | 26 | private GroupInvitationRequest(String message) { 27 | this.message = message; 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /src/main/java/athena/groups/requests/updating/UpdateGroupRequest.java: -------------------------------------------------------------------------------- 1 | package athena.groups.requests.updating; 2 | 3 | /** 4 | * A request used to update a group. 5 | * 6 | * @author Vrekt, Armisto 7 | */ 8 | public final class UpdateGroupRequest { 9 | 10 | /** 11 | * Motto, description and language. 12 | */ 13 | private final String motto, description, lang; 14 | 15 | /** 16 | * Static factory method to create a new {@link UpdateGroupRequest} 17 | * 18 | * @param motto the new motto 19 | * @param description the new description 20 | * @param lang the new lang 21 | * @return a new {@link UpdateGroupRequest} 22 | */ 23 | public static UpdateGroupRequest create(String motto, String description, String lang) { 24 | return new UpdateGroupRequest(motto, description, lang); 25 | } 26 | 27 | private UpdateGroupRequest(String motto, String description, String lang) { 28 | this.motto = motto; 29 | this.description = description; 30 | this.lang = lang; 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /src/main/java/athena/groups/response/BaseGroupsResponse.java: -------------------------------------------------------------------------------- 1 | package athena.groups.response; 2 | 3 | import athena.groups.group.Group; 4 | import athena.groups.paging.Pageable; 5 | 6 | import java.util.List; 7 | import java.util.stream.Collectors; 8 | 9 | /** 10 | * Represents a response of all groups. 11 | */ 12 | public final class BaseGroupsResponse extends Pageable { 13 | 14 | /** 15 | * All groups registered. 16 | */ 17 | private List elements; 18 | 19 | /** 20 | * Get a {@link Group} by {@code groupId} 21 | * 22 | * @param groupId the ID of the group. 23 | * @return the {@link Group} or {@code null} 24 | */ 25 | public Group getById(String groupId) { 26 | return elements.stream().filter(group -> group.groupId().equals(groupId)).findAny().orElse(null); 27 | } 28 | 29 | /** 30 | * Get a {@link Group} by {@code groupName} 31 | * 32 | * @param groupName the group name. 33 | * @return the {@link Group} or {@code null} 34 | */ 35 | public Group getByName(String groupName) { 36 | return elements.stream().filter(group -> group.name().equals(groupName)).findAny().orElse(null); 37 | } 38 | 39 | /** 40 | * Collect groups that only match the language of the provided {@code language} 41 | * This method will use {@code equalsIgnoreCase} 42 | * 43 | * @param language the language, ex: "en" 44 | * @return a list of {@link Group} 45 | */ 46 | public List filterByLanguage(String language) { 47 | return elements.stream().filter(group -> group.lang().equalsIgnoreCase(language)).collect(Collectors.toList()); 48 | } 49 | 50 | /** 51 | * @return the list of groups. 52 | */ 53 | public List groups() { 54 | return elements; 55 | } 56 | 57 | /** 58 | * @return count of groups. 59 | */ 60 | public int countGroups() { 61 | return count(); 62 | } 63 | 64 | /** 65 | * @return start index? 66 | */ 67 | public int startGroups() { 68 | return start(); 69 | } 70 | 71 | /** 72 | * @return total number of groups 73 | */ 74 | public int totalGroups() { 75 | return total(); 76 | } 77 | 78 | } 79 | -------------------------------------------------------------------------------- /src/main/java/athena/interceptor/InterceptorAction.java: -------------------------------------------------------------------------------- 1 | package athena.interceptor; 2 | 3 | import okhttp3.Request; 4 | 5 | /** 6 | * An interface which allows the user to implement custom actions upon interception of the main HTTP client. 7 | */ 8 | public interface InterceptorAction { 9 | 10 | /** 11 | * Run the action on the chain. 12 | * 13 | * @param request the request. 14 | * @return a new request to proceed with 15 | */ 16 | Request run(Request request); 17 | 18 | } 19 | -------------------------------------------------------------------------------- /src/main/java/athena/party/resource/assignment/SquadAssignment.java: -------------------------------------------------------------------------------- 1 | package athena.party.resource.assignment; 2 | 3 | import com.google.gson.annotations.SerializedName; 4 | 5 | /** 6 | * Represents squad assignments inside a party. 7 | */ 8 | public final class SquadAssignment { 9 | 10 | /** 11 | * The account ID. 12 | */ 13 | private String memberId; 14 | 15 | /** 16 | * The index or position they are in. 17 | */ 18 | @SerializedName("absoluteMemberIdx") 19 | private int memberIndex; 20 | 21 | public SquadAssignment(String memberId, int memberIndex) { 22 | this.memberId = memberId; 23 | this.memberIndex = memberIndex; 24 | } 25 | 26 | /** 27 | * @return the member ID. 28 | */ 29 | public String memberId() { 30 | return memberId; 31 | } 32 | 33 | /** 34 | * @return the member index or position. 35 | */ 36 | public int memberIndex() { 37 | return memberIndex; 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /src/main/java/athena/party/resource/configuration/privacy/PartyPrivacy.java: -------------------------------------------------------------------------------- 1 | package athena.party.resource.configuration.privacy; 2 | 3 | import com.google.gson.annotations.SerializedName; 4 | 5 | /** 6 | * Represents party privacy settings, different from a {@link athena.party.resource.configuration.PartyConfiguration} 7 | */ 8 | public final class PartyPrivacy { 9 | 10 | /** 11 | * The party type and invite restrictions. 12 | * For example: "Private" and "AnyMember" 13 | */ 14 | private String partyType, partyInviteRestriction; 15 | 16 | /** 17 | * if {@code true} only friends of the leader can join. 18 | */ 19 | @SerializedName("bOnlyLeaderFriendsCanJoin") 20 | private boolean onlyLeaderFriendsCanJoin; 21 | 22 | /** 23 | * Public privacy settings 24 | */ 25 | public static PartyPrivacy PUBLIC = new PartyPrivacy("Public", "AnyMember", false); 26 | /** 27 | * Friends only privacy settings 28 | */ 29 | public static PartyPrivacy FRIENDS_ONLY = new PartyPrivacy("FriendsOnly", "AnyMember", false); 30 | /** 31 | * Private privacy settings 32 | */ 33 | public static PartyPrivacy PRIVATE = new PartyPrivacy("Private", "NoInvites", false); 34 | 35 | private PartyPrivacy(String partyType, String partyInviteRestriction, boolean onlyLeaderFriendsCanJoin) { 36 | this.partyType = partyType; 37 | this.partyInviteRestriction = partyInviteRestriction; 38 | this.onlyLeaderFriendsCanJoin = onlyLeaderFriendsCanJoin; 39 | } 40 | 41 | /** 42 | * @return the privacy type. 43 | */ 44 | public String partyType() { 45 | return partyType; 46 | } 47 | 48 | /** 49 | * @return the invite restriction. 50 | */ 51 | public String partyInviteRestriction() { 52 | return partyInviteRestriction; 53 | } 54 | 55 | /** 56 | * @return {@code true} if only friends of the leader can join. 57 | */ 58 | public boolean onlyLeaderFriendsCanJoin() { 59 | return onlyLeaderFriendsCanJoin; 60 | } 61 | 62 | /** 63 | * @return {@code true} if this privacy is private. 64 | */ 65 | public boolean isPrivate() { 66 | return partyType.equalsIgnoreCase("Private"); 67 | } 68 | 69 | } 70 | -------------------------------------------------------------------------------- /src/main/java/athena/party/resource/configuration/types/Joinability.java: -------------------------------------------------------------------------------- 1 | package athena.party.resource.configuration.types; 2 | 3 | /** 4 | * Represents party joinability. 5 | */ 6 | public enum Joinability { 7 | 8 | /** 9 | * Open to the public. 10 | */ 11 | OPEN, 12 | /** 13 | * Invite only and former members. 14 | */ 15 | INVITE_AND_FORMER 16 | 17 | } 18 | -------------------------------------------------------------------------------- /src/main/java/athena/party/resource/connection/Connection.java: -------------------------------------------------------------------------------- 1 | package athena.party.resource.connection; 2 | 3 | import athena.types.Platform; 4 | import com.google.gson.annotations.SerializedName; 5 | import org.jxmpp.jid.Jid; 6 | 7 | import java.time.Instant; 8 | 9 | /** 10 | * Represents the connection of a party member. 11 | */ 12 | public final class Connection { 13 | 14 | /** 15 | * The JID of this connection. 16 | */ 17 | private Jid id; 18 | 19 | /** 20 | * When they connected. 21 | */ 22 | @SerializedName("connected_at") 23 | private Instant connectedAt; 24 | /** 25 | * When the connection was updated. 26 | */ 27 | @SerializedName("updated_at") 28 | private Instant updatedAt; 29 | 30 | /** 31 | * if {@code true} leadership cannot be given to the person. 32 | */ 33 | @SerializedName("yield_leadership") 34 | private boolean yieldLeadership; 35 | 36 | /** 37 | * The meta of this connection. 38 | */ 39 | private ConnectionMeta meta; 40 | 41 | /** 42 | * @return the JID of this connection. 43 | */ 44 | public Jid jid() { 45 | return id; 46 | } 47 | 48 | /** 49 | * @return when they connected. 50 | */ 51 | public Instant connectedAt() { 52 | return connectedAt; 53 | } 54 | 55 | /** 56 | * @return when the connection was updated. 57 | */ 58 | public Instant updatedAt() { 59 | return updatedAt; 60 | } 61 | 62 | /** 63 | * @return {@code true} if leadership shouldn't be accepted. 64 | */ 65 | public boolean yieldLeadership() { 66 | return yieldLeadership; 67 | } 68 | 69 | /** 70 | * @return the platform of this connection. 71 | */ 72 | public Platform platform() { 73 | return meta.connectionPlatform; 74 | } 75 | 76 | /** 77 | * @return the type of connection, usually "GAME" 78 | */ 79 | public String type() { 80 | return meta.connectionType; 81 | } 82 | 83 | /** 84 | * Represents meta inside connection. 85 | */ 86 | private static final class ConnectionMeta { 87 | 88 | /** 89 | * The platform of this connection 90 | */ 91 | @SerializedName("urn:epic:conn:platform_s") 92 | private Platform connectionPlatform; 93 | /** 94 | * The connection type - "game"/??? 95 | */ 96 | @SerializedName("urn:epic:conn:type_s") 97 | private String connectionType; 98 | } 99 | 100 | } 101 | -------------------------------------------------------------------------------- /src/main/java/athena/party/resource/member/meta/assignments/MemberSquadAssignmentRequest.java: -------------------------------------------------------------------------------- 1 | package athena.party.resource.member.meta.assignments; 2 | 3 | /** 4 | * Represents the squad assignment request of a member. 5 | */ 6 | public final class MemberSquadAssignmentRequest { 7 | 8 | /** 9 | * The starting index, target index 10 | * The swap target member ID to change with, sometimes is "INVALID" if no request. 11 | */ 12 | private int startingAbsoluteIdx = -1, targetAbsoluteIdx = -1; 13 | private String swapTargetMemberId = "INVALID"; 14 | /** 15 | * Version? 16 | */ 17 | private int version = 0; 18 | 19 | /** 20 | * @return The starting index. 21 | */ 22 | public int startingAbsoluteIdx() { 23 | return startingAbsoluteIdx; 24 | } 25 | 26 | /** 27 | * Set the starting index. 28 | * 29 | * @param startingAbsoluteIdx The starting index. 30 | */ 31 | public MemberSquadAssignmentRequest startingAbsoluteIdx(int startingAbsoluteIdx) { 32 | this.startingAbsoluteIdx = startingAbsoluteIdx; 33 | return this; 34 | } 35 | 36 | /** 37 | * @return The target index 38 | */ 39 | public int targetAbsoluteIdx() { 40 | return targetAbsoluteIdx; 41 | } 42 | 43 | /** 44 | * Set the target index. 45 | * 46 | * @param targetAbsoluteIdx The target index 47 | */ 48 | public MemberSquadAssignmentRequest targetAbsoluteIdx(int targetAbsoluteIdx) { 49 | this.targetAbsoluteIdx = targetAbsoluteIdx; 50 | return this; 51 | } 52 | 53 | /** 54 | * @return the version (?) 55 | */ 56 | public int version() { 57 | return version; 58 | } 59 | 60 | /** 61 | * Set the version 62 | * 63 | * @param version the version 64 | */ 65 | public MemberSquadAssignmentRequest version(int version) { 66 | this.version = version; 67 | return this; 68 | } 69 | 70 | /** 71 | * @return the account ID of who to swap with. 72 | */ 73 | public String swapTargetMemberId() { 74 | return swapTargetMemberId; 75 | } 76 | 77 | /** 78 | * Set the account ID of who to swap with 79 | * 80 | * @param swapTargetMemberId the account ID. 81 | */ 82 | public MemberSquadAssignmentRequest swapTargetMemberId(String swapTargetMemberId) { 83 | this.swapTargetMemberId = swapTargetMemberId; 84 | return this; 85 | } 86 | } 87 | -------------------------------------------------------------------------------- /src/main/java/athena/party/resource/member/meta/banner/AthenaBanner.java: -------------------------------------------------------------------------------- 1 | package athena.party.resource.member.meta.banner; 2 | 3 | /** 4 | * Represents banner information for a member. 5 | */ 6 | public final class AthenaBanner { 7 | 8 | /** 9 | * The banner icon ID, eg "standardbanner15" 10 | * The banner color ID, eg "defaultcolor17" 11 | */ 12 | private String bannerIconId = "standardbanner15", bannerColorId = "defaultcolor17"; 13 | /** 14 | * The current season level. 15 | */ 16 | private int seasonLevel = 1; 17 | 18 | public AthenaBanner() { 19 | } 20 | 21 | public AthenaBanner(String bannerIconId, String bannerColorId, int seasonLevel) { 22 | this.bannerIconId = bannerIconId; 23 | this.bannerColorId = bannerColorId; 24 | this.seasonLevel = seasonLevel; 25 | } 26 | 27 | /** 28 | * @return the banner icon ID. 29 | */ 30 | public String bannerIconId() { 31 | return bannerIconId; 32 | } 33 | 34 | /** 35 | * Set the banner icon ID. 36 | * 37 | * @param bannerIconId the banner icon ID. 38 | */ 39 | public void bannerIconId(String bannerIconId) { 40 | this.bannerIconId = bannerIconId; 41 | } 42 | 43 | /** 44 | * @return the banner color ID. 45 | */ 46 | public String bannerColorId() { 47 | return bannerColorId; 48 | } 49 | 50 | /** 51 | * Set the banner color ID. 52 | * 53 | * @param bannerColorId the banner color ID. 54 | */ 55 | public void bannerColorId(String bannerColorId) { 56 | this.bannerColorId = bannerColorId; 57 | } 58 | 59 | /** 60 | * @return the season level. 61 | */ 62 | public int seasonLevel() { 63 | return seasonLevel; 64 | } 65 | 66 | /** 67 | * Set the season level 68 | * 69 | * @param seasonLevel the season level 70 | */ 71 | public void seasonLevel(int seasonLevel) { 72 | this.seasonLevel = seasonLevel; 73 | } 74 | } 75 | -------------------------------------------------------------------------------- /src/main/java/athena/party/resource/member/meta/battlepass/BattlePass.java: -------------------------------------------------------------------------------- 1 | package athena.party.resource.member.meta.battlepass; 2 | 3 | /** 4 | * Represents member battle pass information. 5 | */ 6 | public final class BattlePass { 7 | 8 | /** 9 | * {@code true} if the battle-pass is purchased. 10 | */ 11 | private boolean bHasPurchasedPass = false; 12 | /** 13 | * Level, and other related XP. 14 | */ 15 | private int passLevel = 1, selfBoostXp = 0, friendBoostXp = 0; 16 | 17 | /** 18 | * @return {@code true} if the battle pass has been purchased. 19 | */ 20 | public boolean hasPurchasedPass() { 21 | return bHasPurchasedPass; 22 | } 23 | 24 | public BattlePass() { 25 | } 26 | 27 | public BattlePass(boolean bHasPurchasedPass, int passLevel, int selfBoostXp, int friendBoostXp) { 28 | this.bHasPurchasedPass = bHasPurchasedPass; 29 | this.passLevel = passLevel; 30 | this.selfBoostXp = selfBoostXp; 31 | this.friendBoostXp = friendBoostXp; 32 | } 33 | 34 | /** 35 | * Set has purchased the battle pass. 36 | * 37 | * @param bHasPurchasedPass the value 38 | */ 39 | public void hasPurchasedPass(boolean bHasPurchasedPass) { 40 | this.bHasPurchasedPass = bHasPurchasedPass; 41 | } 42 | 43 | /** 44 | * @return the battle pass level 45 | */ 46 | public int passLevel() { 47 | return passLevel; 48 | } 49 | 50 | /** 51 | * Set the battle pass level 52 | * 53 | * @param passLevel the pass level 54 | */ 55 | public void passLevel(int passLevel) { 56 | this.passLevel = passLevel; 57 | } 58 | 59 | /** 60 | * @return the client boost XP. 61 | */ 62 | public int selfBoostXp() { 63 | return selfBoostXp; 64 | } 65 | 66 | /** 67 | * Set the client boost XP. 68 | * 69 | * @param selfBoostXp the client boost XP. 70 | */ 71 | public void selfBoostXp(int selfBoostXp) { 72 | this.selfBoostXp = selfBoostXp; 73 | } 74 | 75 | /** 76 | * @return the friend boost XP. 77 | */ 78 | public int friendBoostXp() { 79 | return friendBoostXp; 80 | } 81 | 82 | /** 83 | * Set the friend boost XP. 84 | * 85 | * @param friendBoostXp the friend boost XP. 86 | */ 87 | public void friendBoostXp(int friendBoostXp) { 88 | this.friendBoostXp = friendBoostXp; 89 | } 90 | } 91 | -------------------------------------------------------------------------------- /src/main/java/athena/party/resource/member/meta/challenges/AssistedChallenge.java: -------------------------------------------------------------------------------- 1 | package athena.party.resource.member.meta.challenges; 2 | 3 | /** 4 | * Represents assisted challenges. 5 | */ 6 | public final class AssistedChallenge { 7 | 8 | /** 9 | * The quest item definition. 10 | */ 11 | private String questItemDef = "None"; 12 | /** 13 | * How many objectives have been completed. 14 | */ 15 | private int objectivesCompleted = 0; 16 | 17 | public AssistedChallenge() { 18 | 19 | } 20 | 21 | public AssistedChallenge(String questItemDef, int objectivesCompleted) { 22 | this.questItemDef = questItemDef; 23 | this.objectivesCompleted = objectivesCompleted; 24 | } 25 | 26 | /** 27 | * @return the quest item definition. 28 | */ 29 | public String questItemDef() { 30 | return questItemDef; 31 | } 32 | 33 | /** 34 | * Set the quest item definition 35 | * 36 | * @param questItemDef the item definition 37 | */ 38 | public void questItemDef(String questItemDef) { 39 | this.questItemDef = questItemDef; 40 | } 41 | 42 | /** 43 | * @return how many objectives have been completed. 44 | */ 45 | public int objectivesCompleted() { 46 | return objectivesCompleted; 47 | } 48 | 49 | /** 50 | * Set how many objectives have been completed. 51 | * 52 | * @param objectivesCompleted how many objectives have been completed. 53 | */ 54 | public void objectivesCompleted(int objectivesCompleted) { 55 | this.objectivesCompleted = objectivesCompleted; 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /src/main/java/athena/party/resource/member/meta/cosmetic/variant/CosmeticVariant.java: -------------------------------------------------------------------------------- 1 | package athena.party.resource.member.meta.cosmetic.variant; 2 | 3 | /** 4 | * Represents a cosmetic variant/stage. 5 | */ 6 | public final class CosmeticVariant { 7 | 8 | /** 9 | * AthenaCharacter, 10 | * "Parts", 11 | * "Stage1" 12 | */ 13 | private String item = "AthenaCharacter", channel = "Parts", variant = "Stage1"; 14 | 15 | /** 16 | * @return the item 17 | */ 18 | public String item() { 19 | return item; 20 | } 21 | 22 | /** 23 | * Set the item 24 | * 25 | * @param item the item 26 | */ 27 | public void item(String item) { 28 | this.item = item; 29 | } 30 | 31 | /** 32 | * @return the channel. 33 | */ 34 | public String channel() { 35 | return channel; 36 | } 37 | 38 | /** 39 | * Set the channel 40 | * 41 | * @param channel the channel 42 | */ 43 | public void channel(String channel) { 44 | this.channel = channel; 45 | } 46 | 47 | /** 48 | * @return the variant 49 | */ 50 | public String variant() { 51 | return variant; 52 | } 53 | 54 | /** 55 | * Set the variant 56 | * 57 | * @param variant the variant 58 | */ 59 | public void variant(String variant) { 60 | this.variant = variant; 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /src/main/java/athena/party/resource/member/meta/emote/FrontendEmote.java: -------------------------------------------------------------------------------- 1 | package athena.party.resource.member.meta.emote; 2 | 3 | /** 4 | * Represents the emote playing. 5 | */ 6 | public final class FrontendEmote { 7 | 8 | /** 9 | * The emote item definition and encryption key. 10 | */ 11 | private String emoteItemDef = "None", emoteEKey = ""; 12 | /** 13 | * -1 = stop, -2 = start 14 | */ 15 | private int emoteSection = -1; 16 | 17 | public FrontendEmote() { 18 | } 19 | 20 | public FrontendEmote(String emoteItemDef, String emoteEKey, int emoteSection) { 21 | this.emoteItemDef = emoteItemDef; 22 | this.emoteEKey = emoteEKey; 23 | this.emoteSection = emoteSection; 24 | } 25 | 26 | /** 27 | * @return the emote item definition 28 | */ 29 | public String emoteItemDef() { 30 | return emoteItemDef; 31 | } 32 | 33 | /** 34 | * Set the emote item definition 35 | * 36 | * @param emoteItemDef the emote item definition. 37 | */ 38 | public void emoteItemDef(String emoteItemDef) { 39 | this.emoteItemDef = emoteItemDef; 40 | } 41 | 42 | /** 43 | * @return the emote encryption key 44 | */ 45 | public String emoteEKey() { 46 | return emoteEKey; 47 | } 48 | 49 | /** 50 | * Set the emote encryption key 51 | * 52 | * @param emoteEKey the key 53 | */ 54 | public void emoteEKey(String emoteEKey) { 55 | this.emoteEKey = emoteEKey; 56 | } 57 | 58 | /** 59 | * @return the section, -1 = stopped, -2 = started 60 | */ 61 | public int emoteSection() { 62 | return emoteSection; 63 | } 64 | 65 | /** 66 | * Set the emote section 67 | * 68 | * @param emoteSection the emote section 69 | */ 70 | public void emoteSection(int emoteSection) { 71 | this.emoteSection = emoteSection; 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /src/main/java/athena/party/resource/member/meta/hero/CampaignHero.java: -------------------------------------------------------------------------------- 1 | package athena.party.resource.member.meta.hero; 2 | 3 | /** 4 | * Represents a hero definition. 5 | */ 6 | public final class CampaignHero { 7 | 8 | /** 9 | * The instance ID is ?? usually "" 10 | * Hero type is HID skin type. 11 | */ 12 | private String heroItemInstanceId = "", heroType; 13 | 14 | /** 15 | * @return "" 16 | */ 17 | public String heroItemInstanceId() { 18 | return heroItemInstanceId; 19 | } 20 | 21 | /** 22 | * Set the hero item instance ID. 23 | * 24 | * @param heroItemInstanceId the instance ID. 25 | */ 26 | public void heroItemInstanceId(String heroItemInstanceId) { 27 | this.heroItemInstanceId = heroItemInstanceId; 28 | } 29 | 30 | /** 31 | * @return the hero type HID. 32 | */ 33 | public String heroType() { 34 | return heroType; 35 | } 36 | 37 | /** 38 | * Set the hero type. 39 | * 40 | * @param heroType the hero type. 41 | */ 42 | public void heroType(String heroType) { 43 | this.heroType = heroType; 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /src/main/java/athena/party/resource/member/meta/joinrequest/JoinRequestUsers.java: -------------------------------------------------------------------------------- 1 | package athena.party.resource.member.meta.joinrequest; 2 | 3 | import athena.types.Platform; 4 | import athena.util.json.fortnite.annotation.FortniteArray; 5 | import com.google.gson.annotations.SerializedName; 6 | 7 | import java.util.List; 8 | 9 | public final class JoinRequestUsers { 10 | 11 | // "urn:epic:member:joinrequestusers_j": "{\"users\":[{\"id\":\"192fd8eb7a144605bfda0e386f10ed18\",\"dn\":\"vrekt_\",\"plat\":\"WIN\",\"data\":\"{\\\"CrossplayPreference_i\\\":\\\"1\\\",\\\"SubGame_u\\\":\\\"1\\\"}\"}]}" 12 | 13 | /** 14 | * List of users. 15 | */ 16 | @FortniteArray(value = "users", type = User.class) 17 | private List users; 18 | 19 | /** 20 | * @return the users 21 | */ 22 | public List users() { 23 | return users; 24 | } 25 | 26 | /** 27 | * Represents the joining user. 28 | */ 29 | public static final class User { 30 | 31 | /** 32 | * Account ID, display name and platform. 33 | */ 34 | private String id, dn; 35 | private Platform plat; 36 | /** 37 | * The user data. 38 | */ 39 | private UserData data; 40 | 41 | public String id() { 42 | return id; 43 | } 44 | 45 | public String dn() { 46 | return dn; 47 | } 48 | 49 | public Platform plat() { 50 | return plat; 51 | } 52 | 53 | public UserData data() { 54 | return data; 55 | } 56 | } 57 | 58 | /** 59 | * Represents the user join data. 60 | */ 61 | public static final class UserData { 62 | /** 63 | * The crossplay preference, usually 1 64 | */ 65 | @SerializedName("CrossplayPreference_i") 66 | private String crossPlayPreference; 67 | /** 68 | * The sub-game, usually 1 69 | */ 70 | @SerializedName("SubGame_u") 71 | private String subGame; 72 | 73 | public String crossPlayPreference() { 74 | return crossPlayPreference; 75 | } 76 | 77 | public String subGame() { 78 | return subGame; 79 | } 80 | } 81 | 82 | } 83 | -------------------------------------------------------------------------------- /src/main/java/athena/party/resource/member/meta/readiness/GameReadiness.java: -------------------------------------------------------------------------------- 1 | package athena.party.resource.member.meta.readiness; 2 | 3 | /** 4 | * Represents game readiness values. 5 | */ 6 | public enum GameReadiness { 7 | 8 | READY("Ready"), NOT_READY("NotReady"), SITTING_OUT("SittingOut"); 9 | 10 | private final String name; 11 | 12 | GameReadiness(final String name) { 13 | this.name = name; 14 | } 15 | 16 | public String getName() { 17 | return name; 18 | } 19 | 20 | } 21 | -------------------------------------------------------------------------------- /src/main/java/athena/party/resource/member/role/PartyRole.java: -------------------------------------------------------------------------------- 1 | package athena.party.resource.member.role; 2 | 3 | /** 4 | * Represents the role within a party. 5 | */ 6 | public enum PartyRole { 7 | 8 | /** 9 | * The party leader. 10 | */ 11 | CAPTAIN, 12 | /** 13 | * A party member. 14 | */ 15 | MEMBER; 16 | 17 | /** 18 | * @return {@code true} if this role is leader/captain. 19 | */ 20 | public boolean isLeader() { 21 | return this == CAPTAIN; 22 | } 23 | 24 | /** 25 | * @return {@code true} if this role is member. 26 | */ 27 | public boolean isMember() { 28 | return this == MEMBER; 29 | } 30 | 31 | } 32 | -------------------------------------------------------------------------------- /src/main/java/athena/party/resource/meta/invites/PingOrInvitationMeta.java: -------------------------------------------------------------------------------- 1 | package athena.party.resource.meta.invites; 2 | 3 | import athena.types.Platform; 4 | import com.google.gson.annotations.SerializedName; 5 | 6 | /** 7 | * Represents metadata for a ping or an invitation. 8 | */ 9 | public final class PingOrInvitationMeta { 10 | 11 | 12 | /** 13 | * The type of connection, usually "game" 14 | */ 15 | @SerializedName("urn:epic:conn:type_s") 16 | private String type; 17 | 18 | /** 19 | * The platform of who sent the invite 20 | */ 21 | @SerializedName("urn:epic:conn:platform_s") 22 | private Platform platform; 23 | 24 | /** 25 | * The display name of who sent the invite 26 | */ 27 | @SerializedName("urn:epic:member:dn_s") 28 | private String displayName; 29 | 30 | /** 31 | * The build ID. 32 | */ 33 | @SerializedName("urn:epic:cfg:build-id_s") 34 | private String buildId; 35 | 36 | /** 37 | * The platform data. 38 | */ 39 | @SerializedName("urn:epic:invite:platformdata_s") 40 | private String platformData; 41 | 42 | /** 43 | * @return the type of connection 44 | */ 45 | public String type() { 46 | return type; 47 | } 48 | 49 | /** 50 | * @return their platform 51 | */ 52 | public Platform platform() { 53 | return platform; 54 | } 55 | 56 | /** 57 | * @return their display name 58 | */ 59 | public String displayName() { 60 | return displayName; 61 | } 62 | 63 | /** 64 | * @return the current build ID. 65 | */ 66 | public String buildId() { 67 | return buildId; 68 | } 69 | 70 | /** 71 | * @return usually {@code ""} 72 | */ 73 | public String platformData() { 74 | return platformData; 75 | } 76 | } 77 | -------------------------------------------------------------------------------- /src/main/java/athena/party/resource/notification/UndeliveredNotifications.java: -------------------------------------------------------------------------------- 1 | package athena.party.resource.notification; 2 | 3 | /** 4 | * The count of undelivered party notifications. 5 | */ 6 | public final class UndeliveredNotifications { 7 | 8 | /** 9 | * Number of undelivered invites and pings. 10 | */ 11 | private int invites, pings; 12 | 13 | /** 14 | * @return number of invites 15 | */ 16 | public int invites() { 17 | return invites; 18 | } 19 | 20 | /** 21 | * @return number of pings 22 | */ 23 | public int pings() { 24 | return pings; 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /src/main/java/athena/party/resource/notification/interactions/InteractionType.java: -------------------------------------------------------------------------------- 1 | package athena.party.resource.notification.interactions; 2 | 3 | /** 4 | * Represents an interaction type 5 | * TODO 6 | */ 7 | public enum InteractionType { 8 | 9 | /** 10 | * A ping has been sent. 11 | */ 12 | PING_SENT("PingSent"), 13 | /** 14 | * A party invite has been sent. 15 | */ 16 | PARTY_INVITE_SENT("PartyInviteSent"), 17 | /** 18 | * The party has been joined 19 | */ 20 | PARTY_JOINED("PartyJoined"), 21 | /** 22 | * The party has been left. 23 | */ 24 | PARTY_LEFT("PartyLeft"); 25 | 26 | /** 27 | * The name of the interaction 28 | */ 29 | private final String name; 30 | 31 | InteractionType(String name) { 32 | this.name = name; 33 | } 34 | 35 | } 36 | -------------------------------------------------------------------------------- /src/main/java/athena/party/resource/notification/regular/PartyNotification.java: -------------------------------------------------------------------------------- 1 | package athena.party.resource.notification.regular; 2 | 3 | import java.util.List; 4 | 5 | /** 6 | * Represents a party notification. 7 | */ 8 | public enum PartyNotification { 9 | 10 | /** 11 | * Represents a ping. 12 | */ 13 | PING("com.epicgames.social.party.notification.v0.PING"), 14 | /** 15 | * Represents an invite. 16 | */ 17 | INITIAL_INVITE("com.epicgames.social.party.notification.v0.INITIAL_INVITE"), 18 | /** 19 | * Represents a member joining. 20 | */ 21 | MEMBER_JOINED("com.epicgames.social.party.notification.v0.MEMBER_JOINED"), 22 | /** 23 | * Represents a member leaving. 24 | */ 25 | MEMBER_LEFT("com.epicgames.social.party.notification.v0.MEMBER_LEFT"), 26 | /** 27 | * Represents when a member updates their metadata. 28 | */ 29 | MEMBER_STATE_UPDATED("com.epicgames.social.party.notification.v0.MEMBER_STATE_UPDATED"), 30 | /** 31 | * Represents when a member gets promoted. 32 | */ 33 | MEMBER_NEW_CAPTAIN("com.epicgames.social.party.notification.v0.MEMBER_NEW_CAPTAIN"), 34 | /** 35 | * Represents when a member gets kicked. 36 | */ 37 | MEMBER_KICKED("com.epicgames.social.party.notification.v0.MEMBER_KICKED"), 38 | /** 39 | * Represents when a member disconnects from the party by closing their game. 40 | */ 41 | MEMBER_DISCONNECTED("com.epicgames.social.party.notification.v0.MEMBER_DISCONNECTED"), 42 | /** 43 | * Represents when a member expires after disconnecting. 44 | */ 45 | MEMBER_EXPIRED("com.epicgames.social.party.notification.v0.MEMBER_EXPIRED"), 46 | /** 47 | * Represents when a member requires confirmation to join. 48 | */ 49 | MEMBER_REQUIRE_CONFIRMATION("com.epicgames.social.party.notification.v0.MEMBER_REQUIRE_CONFIRMATION"), 50 | 51 | /** 52 | * Represents when the party gets updated 53 | */ 54 | PARTY_UPDATED("com.epicgames.social.party.notification.v0.PARTY_UPDATED"), 55 | 56 | /** 57 | * An unknown notification. 58 | */ 59 | UNKNOWN("UNKNOWN"); 60 | 61 | /** 62 | * List of all notifications. 63 | */ 64 | private static final List VALUES = List.of(values()); 65 | /** 66 | * The type. 67 | */ 68 | private final String type; 69 | 70 | PartyNotification(String type) { 71 | this.type = type; 72 | } 73 | 74 | /** 75 | * Get the {@link PartyNotification} from the provided {@code type} 76 | * 77 | * @param type the type 78 | * @return the party notification. 79 | */ 80 | public static PartyNotification of(String type) { 81 | return VALUES.stream().filter(partyNotification -> partyNotification.type.equals(type)).findAny().orElse(UNKNOWN); 82 | } 83 | 84 | } 85 | -------------------------------------------------------------------------------- /src/main/java/athena/party/resource/playlist/PartyPlaylistData.java: -------------------------------------------------------------------------------- 1 | package athena.party.resource.playlist; 2 | 3 | /** 4 | * Represents playlist-data for a party. 5 | */ 6 | public final class PartyPlaylistData { 7 | 8 | /** 9 | * Playlist related information and region. 10 | * see {@link athena.events.Events} 11 | */ 12 | private String playlistName, tournamentId, eventWindowId, regionId; 13 | 14 | public PartyPlaylistData(String playlistName, String tournamentId, String eventWindowId, String regionId) { 15 | this.playlistName = playlistName; 16 | this.tournamentId = tournamentId; 17 | this.eventWindowId = eventWindowId; 18 | this.regionId = regionId; 19 | } 20 | 21 | /** 22 | * @return the playlist name. 23 | */ 24 | public String playlistName() { 25 | return playlistName; 26 | } 27 | 28 | /** 29 | * @return the tournament ID or {@code ""} 30 | */ 31 | public String tournamentId() { 32 | return tournamentId; 33 | } 34 | 35 | /** 36 | * @return the event window ID or {@code ""} 37 | */ 38 | public String eventWindowId() { 39 | return eventWindowId; 40 | } 41 | 42 | /** 43 | * @return the region, ex: "NAE" 44 | */ 45 | public String regionId() { 46 | return regionId; 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /src/main/java/athena/party/resource/requests/PartyCreateRequest.java: -------------------------------------------------------------------------------- 1 | package athena.party.resource.requests; 2 | 3 | import athena.party.Parties; 4 | import athena.party.resource.configuration.PartyConfiguration; 5 | import athena.types.Platform; 6 | import athena.util.json.builder.JsonObjectBuilder; 7 | import com.google.gson.JsonObject; 8 | 9 | /** 10 | * A request for creating parties. 11 | */ 12 | public final class PartyCreateRequest { 13 | 14 | /** 15 | * Creates the request for the new party. 16 | * 17 | * @param configuration the configuration 18 | * @param jid the user JID 19 | * @param platform the user platform 20 | * @return a {@link JsonObject} representing the payload. 21 | */ 22 | public static JsonObject forParty(PartyConfiguration configuration, String jid, Platform platform) { 23 | return new JsonObjectBuilder() 24 | .add("config", new JsonObjectBuilder() 25 | .add("join_confirmation", configuration.joinConfirmation()) 26 | .add("joinability", configuration.joinability().name()) 27 | .add("max_size", configuration.maxSize()).build()) 28 | .add("join_info", new JsonObjectBuilder() 29 | .add("connection", new JsonObjectBuilder() 30 | .add("id", jid) 31 | .add("meta", new JsonObjectBuilder() 32 | .add("urn:epic:conn:platform_s", platform.primaryName()) 33 | .add("urn:epic:conn:type_s", "game").build()).build()).build()) 34 | .add("meta", new JsonObjectBuilder() 35 | .add("urn:epic:cfg:party-type-id_s", "default") 36 | .add("urn:epic:cfg:build-id_s", Parties.BUILD_ID) 37 | .add("urn:epic:cfg:join-request-action_s", "Manual") 38 | .add("urn:epic:cfg:chat-enabled_b", true) 39 | .build()) 40 | .build(); 41 | } 42 | 43 | } 44 | -------------------------------------------------------------------------------- /src/main/java/athena/party/resource/requests/PartyInvitationRequest.java: -------------------------------------------------------------------------------- 1 | package athena.party.resource.requests; 2 | 3 | import athena.party.Parties; 4 | import athena.types.Platform; 5 | import com.google.gson.annotations.SerializedName; 6 | 7 | /** 8 | * A request used to invite a user. 9 | */ 10 | public final class PartyInvitationRequest { 11 | 12 | /** 13 | * The connection type 14 | */ 15 | @SerializedName("urn:epic:conn:type_s") 16 | private final String connectionType = "game"; 17 | 18 | /** 19 | * the display name 20 | */ 21 | @SerializedName("urn:epic:member:dn_s") 22 | private final String displayName; 23 | 24 | /** 25 | * The platform 26 | */ 27 | @SerializedName("urn:epic:conn:platform_s") 28 | private final Platform platform; 29 | 30 | /** 31 | * The build ID. 32 | */ 33 | @SerializedName("urn:epic:cfg:build-id_s") 34 | private final String buildId = Parties.BUILD_ID; 35 | 36 | /** 37 | * Platform data. 38 | */ 39 | @SerializedName("urn:epic:invite:platformdata_s") 40 | private final String platformData = ""; 41 | 42 | /** 43 | * Initialize this request. 44 | * 45 | * @param displayName the display name 46 | * @param platform the platform 47 | */ 48 | public PartyInvitationRequest(String displayName, Platform platform) { 49 | this.displayName = displayName; 50 | this.platform = platform; 51 | } 52 | 53 | } 54 | -------------------------------------------------------------------------------- /src/main/java/athena/party/resource/requests/PartyJoinRequest.java: -------------------------------------------------------------------------------- 1 | package athena.party.resource.requests; 2 | 3 | import athena.types.Platform; 4 | import athena.util.json.builder.JsonArrayBuilder; 5 | import athena.util.json.builder.JsonObjectBuilder; 6 | import com.google.gson.JsonObject; 7 | import org.jxmpp.jid.Jid; 8 | 9 | /** 10 | * A party join request. 11 | */ 12 | public final class PartyJoinRequest { 13 | 14 | /** 15 | * Creates the party join request payload for the specified user. 16 | * 17 | * @param accountId their account ID. 18 | * @param displayName their display name. 19 | * @param userJid their user JID. 20 | * @param platform their platform. 21 | * @return a new {@link JsonObject} payload 22 | */ 23 | public static JsonObject forUser(String accountId, String displayName, Jid userJid, Platform platform) { 24 | return new JsonObjectBuilder() 25 | .add("connection", new JsonObjectBuilder() 26 | .add("id", userJid.asUnescapedString()) 27 | .add("meta", new JsonObjectBuilder() 28 | .add("urn:epic:conn:platform_s", platform.primaryName()) 29 | .add("urn:epic:conn:type_s", "game").build()) 30 | .add("yield_leadership", false) 31 | .build()) 32 | .add("meta", new JsonObjectBuilder() 33 | .add("urn:epic:member:dn_s", displayName) 34 | .add("urn:epic:member:joinrequestusers_j", new JsonObjectBuilder() 35 | .add("users", new JsonArrayBuilder() 36 | .add(new JsonObjectBuilder() 37 | .add("id", accountId) 38 | .add("dn", displayName) 39 | .add("plat", platform.primaryName()) 40 | .add("data", new JsonObjectBuilder() 41 | .add("CrossplayPreference", "1") 42 | .add("SubGame_u", "1").build().toString()) 43 | .build()) 44 | .build()) 45 | .build().toString()) 46 | .build()) 47 | .build(); 48 | } 49 | 50 | } 51 | -------------------------------------------------------------------------------- /src/main/java/athena/party/resource/requests/status/PartyJoinStatus.java: -------------------------------------------------------------------------------- 1 | package athena.party.resource.requests.status; 2 | 3 | import com.google.gson.annotations.SerializedName; 4 | 5 | /** 6 | * Represents the response when you try to join a party. 7 | */ 8 | public final class PartyJoinStatus { 9 | 10 | /** 11 | * The status: "PENDING_CONFIRMATION" 12 | */ 13 | private String status; 14 | /** 15 | * The party ID. 16 | */ 17 | @SerializedName("party_id") 18 | private String partyId; 19 | 20 | /** 21 | * @return The status, ex: "PENDING_CONFIRMATION" 22 | */ 23 | public String status() { 24 | return status; 25 | } 26 | 27 | /** 28 | * @return the party ID. 29 | */ 30 | public String partyId() { 31 | return partyId; 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /src/main/java/athena/party/resource/user/UserPartyProfile.java: -------------------------------------------------------------------------------- 1 | package athena.party.resource.user; 2 | 3 | import athena.party.resource.Party; 4 | import athena.party.resource.invite.PartyInvitation; 5 | import athena.party.resource.ping.PartyPing; 6 | 7 | import java.util.List; 8 | 9 | /** 10 | * Represents data for a user. 11 | * Current party, pending, invites and pings. 12 | */ 13 | public final class UserPartyProfile { 14 | 15 | /** 16 | * The current party. 17 | * TODO: Pending? I'm assuming for joining parties. 18 | */ 19 | private List current, pending; 20 | /** 21 | * List of party invitations 22 | */ 23 | private List invites; 24 | /** 25 | * List of party pings 26 | */ 27 | private List pings; 28 | 29 | /** 30 | * @return list of all current parties 31 | */ 32 | public List parties() { 33 | return current; 34 | } 35 | 36 | /** 37 | * @return the current party. 38 | */ 39 | public Party current() { 40 | return current.size() > 0 ? current.get(0) : null; 41 | } 42 | 43 | /** 44 | * @return list of pending parties 45 | */ 46 | public List pending() { 47 | return pending; 48 | } 49 | 50 | /** 51 | * @return list of party invites 52 | */ 53 | public List invites() { 54 | return invites; 55 | } 56 | 57 | /** 58 | * @return list of party pings 59 | */ 60 | public List pings() { 61 | return pings; 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /src/main/java/athena/party/xmpp/annotation/PartyEvent.java: -------------------------------------------------------------------------------- 1 | package athena.party.xmpp.annotation; 2 | 3 | import java.lang.annotation.ElementType; 4 | import java.lang.annotation.Retention; 5 | import java.lang.annotation.RetentionPolicy; 6 | import java.lang.annotation.Target; 7 | 8 | /** 9 | * Annotation used for party event 10 | * Put the annotation above a method and then register it with 11 | * {@code athena.party().registerEventListener} 12 | */ 13 | @Target(ElementType.METHOD) 14 | @Retention(RetentionPolicy.RUNTIME) 15 | public @interface PartyEvent { 16 | } 17 | -------------------------------------------------------------------------------- /src/main/java/athena/party/xmpp/event/invite/PartyPingEvent.java: -------------------------------------------------------------------------------- 1 | package athena.party.xmpp.event.invite; 2 | 3 | import athena.party.Parties; 4 | import athena.party.resource.Party; 5 | import athena.party.resource.meta.invites.PingOrInvitationMeta; 6 | import athena.util.json.request.Request; 7 | import com.google.gson.annotations.SerializedName; 8 | 9 | import java.time.Instant; 10 | 11 | /** 12 | * Represents a ping event. 13 | */ 14 | public final class PartyPingEvent { 15 | 16 | /** 17 | * The account ID of who sent the ping. 18 | */ 19 | @SerializedName("pinger_id") 20 | private String fromAccountId; 21 | 22 | /** 23 | * The display name of who sent the ping. 24 | */ 25 | @SerializedName("pinger_dn") 26 | private String fromDisplayName; 27 | 28 | /** 29 | * When this ping expires and when it was sent. 30 | */ 31 | private Instant expires, sent; 32 | 33 | /** 34 | * The metadata of this event. 35 | */ 36 | private PingOrInvitationMeta meta; 37 | 38 | /** 39 | * The party for this ping. 40 | */ 41 | private Party party; 42 | 43 | /** 44 | * Parties 45 | */ 46 | @Request(item = Parties.class) 47 | private Parties parties; 48 | 49 | /** 50 | * @return The account ID of who sent the ping. 51 | */ 52 | public String fromAccountId() { 53 | return fromAccountId; 54 | } 55 | 56 | /** 57 | * @return The display name of who sent the ping. 58 | */ 59 | public String fromDisplayName() { 60 | return fromDisplayName; 61 | } 62 | 63 | /** 64 | * @return When this ping expires. 65 | */ 66 | public Instant expires() { 67 | return expires; 68 | } 69 | 70 | /** 71 | * @return when this ping was sent. 72 | */ 73 | public Instant sent() { 74 | return sent; 75 | } 76 | 77 | /** 78 | * @return The metadata of this event. 79 | */ 80 | public PingOrInvitationMeta meta() { 81 | return meta; 82 | } 83 | 84 | /** 85 | * @return the party of this ping. 86 | */ 87 | public Party party() { 88 | return party; 89 | } 90 | 91 | /** 92 | * Sets the party for this ping. 93 | * 94 | * @param party the party. 95 | */ 96 | public void party(Party party) { 97 | this.party = party; 98 | } 99 | 100 | /** 101 | * Joins the party that this ping belongs to. 102 | * 103 | * @return the party. 104 | */ 105 | public Party joinParty() { 106 | if (party == null) throw new IllegalStateException("No party to join!"); 107 | this.party = parties.joinParty(party.partyId()); 108 | return this.party; 109 | } 110 | 111 | } 112 | -------------------------------------------------------------------------------- /src/main/java/athena/party/xmpp/event/member/PartyMemberConnectedEvent.java: -------------------------------------------------------------------------------- 1 | package athena.party.xmpp.event.member; 2 | 3 | /** 4 | * TODO: 5 | * {"sent":"2020-05-30T10:08:15.848Z","type":"com.epicgames.social.party.notification.v0.MEMBER_CONNECTED","connection":{"id":"192fd8eb7a144605bfda0e386f10ed18@prod.ol.epicgames.com/V2:Fortnite:IOS::65A7F415B34F1449233AA18CD8747482","meta":{"urn:epic:conn:platform_s":"IOS","urn:epic:conn:type_s":"embedded"},"connected_at":"2020-05-30T09:47:16.836Z","updated_at":"2020-05-30T10:08:15.837Z","yield_leadership":true},"revision":36,"ns":"Fortnite","party_id":"1c2715d218564df888412deeda32edd8","account_id":"192fd8eb7a144605bfda0e386f10ed18","account_dn":"vrekt_","joined_at":"2020-05-30T09:49:12.243Z","updated_at":"2020-05-30T10:02:02.812Z"} 6 | * Received unknown notification party type, please report this. 7 | * {"sent":"2020-05-30T10:08:15.848Z","type":"com.epicgames.social.party.notification.v0.MEMBER_CONNECTED","connection":{"id":"192fd8eb7a144605bfda0e386f10ed18@prod.ol.epicgames.com/V2:Fortnite:IOS::65A7F415B34F1449233AA18CD8747482","meta":{"urn:epic:conn:platform_s":"IOS","urn:epic:conn:type_s":"embedded"},"connected_at":"2020-05-30T09:47:16.836Z","updated_at":"2020-05-30T10:08:15.837Z","yield_leadership":true},"revision":36,"ns":"Fortnite","party_id":"1c2715d218564df888412deeda32edd8","account_id":"192fd8eb7a144605bfda0e386f10ed18","account_dn":"vrekt_","joined_at":"2020-05-30T09:49:12.243Z","updated_at":"2020-05-30T10:02:02.812Z"} 8 | */ 9 | public final class PartyMemberConnectedEvent { 10 | } 11 | -------------------------------------------------------------------------------- /src/main/java/athena/presence/resource/annotation/PresenceEvent.java: -------------------------------------------------------------------------------- 1 | package athena.presence.resource.annotation; 2 | 3 | import java.lang.annotation.ElementType; 4 | import java.lang.annotation.Retention; 5 | import java.lang.annotation.RetentionPolicy; 6 | import java.lang.annotation.Target; 7 | 8 | /** 9 | * Annotation for receiving presences. 10 | */ 11 | @Target(ElementType.METHOD) 12 | @Retention(RetentionPolicy.RUNTIME) 13 | public @interface PresenceEvent { 14 | } 15 | -------------------------------------------------------------------------------- /src/main/java/athena/presence/resource/filter/PresenceFilter.java: -------------------------------------------------------------------------------- 1 | package athena.presence.resource.filter; 2 | 3 | import athena.presence.resource.FortnitePresence; 4 | 5 | /** 6 | * Used to filter {@link athena.presence.resource.FortnitePresence}s 7 | */ 8 | public interface PresenceFilter { 9 | 10 | /** 11 | * @return {@code true} if this filter is ready to accept presences. 12 | */ 13 | boolean ready(); 14 | 15 | /** 16 | * @return {@code true} if this filter is active. 17 | */ 18 | boolean active(); 19 | 20 | /** 21 | * @param accountId the account ID of who the presence came from. 22 | * @return {@code true} if the presence is relevant. 23 | */ 24 | boolean isRelevant(String accountId); 25 | 26 | /** 27 | * Consume the presence, only invoked if {@code ready} is {@code true} and {@code active} is {@code true} and {@code isRelevant} is {@code true} 28 | * 29 | * @param presence the presence 30 | */ 31 | void consume(FortnitePresence presence); 32 | 33 | } 34 | -------------------------------------------------------------------------------- /src/main/java/athena/presence/resource/listener/FortnitePresenceListener.java: -------------------------------------------------------------------------------- 1 | package athena.presence.resource.listener; 2 | 3 | import athena.presence.resource.FortnitePresence; 4 | 5 | /** 6 | * Used to listen for presences. 7 | */ 8 | public interface FortnitePresenceListener { 9 | 10 | /** 11 | * Invoked when a presence is received. 12 | * 13 | * @param presence the presence. 14 | */ 15 | void presenceReceived(FortnitePresence presence); 16 | 17 | } 18 | -------------------------------------------------------------------------------- /src/main/java/athena/presence/resource/subscription/PresenceSubscription.java: -------------------------------------------------------------------------------- 1 | package athena.presence.resource.subscription; 2 | 3 | import com.google.gson.annotations.SerializedName; 4 | 5 | import java.time.Instant; 6 | 7 | /** 8 | * A single presence subscription. 9 | */ 10 | public final class PresenceSubscription { 11 | 12 | /** 13 | * The account ID. 14 | */ 15 | @SerializedName("account_id") 16 | private String accountId; 17 | /** 18 | * The time subscribed at. 19 | */ 20 | @SerializedName("subscribed_at") 21 | private Instant subscribedAt; 22 | 23 | /** 24 | * @return the account ID. 25 | */ 26 | public String accountId() { 27 | return accountId; 28 | } 29 | 30 | /** 31 | * @return The time subscribed at. 32 | */ 33 | public Instant subscribedAt() { 34 | return subscribedAt; 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /src/main/java/athena/presence/resource/subscription/SubscriptionSettings.java: -------------------------------------------------------------------------------- 1 | package athena.presence.resource.subscription; 2 | 3 | /** 4 | * Provides response/request for subscription settings in {@link athena.presence.service.PresencePublicService} 5 | */ 6 | public final class SubscriptionSettings { 7 | 8 | /** 9 | * The broadcast settings. 10 | */ 11 | private Broadcast broadcast; 12 | 13 | public SubscriptionSettings(boolean enableBroadcast) { 14 | broadcast = new Broadcast(); 15 | broadcast.enabled = enableBroadcast; 16 | } 17 | 18 | /** 19 | * @return {@code true} if broadcast is enabled. 20 | */ 21 | public boolean enabled() { 22 | return broadcast.enabled; 23 | } 24 | 25 | /** 26 | * Broadcast settings. 27 | */ 28 | private static final class Broadcast { 29 | private boolean enabled; 30 | } 31 | 32 | } 33 | -------------------------------------------------------------------------------- /src/main/java/athena/social/SocialBanPublicService.java: -------------------------------------------------------------------------------- 1 | package athena.social; 2 | 3 | /** 4 | * Provides access to the social ban service. 5 | */ 6 | public interface SocialBanPublicService { 7 | } 8 | -------------------------------------------------------------------------------- /src/main/java/athena/stats/resource/StatisticValue.java: -------------------------------------------------------------------------------- 1 | package athena.stats.resource; 2 | 3 | import athena.stats.resource.type.StatisticType; 4 | import athena.types.Input; 5 | import org.apache.commons.lang3.StringUtils; 6 | 7 | /** 8 | * Holds data for a single statistic value. 9 | */ 10 | final class StatisticValue { 11 | 12 | private final StatisticType type; 13 | private final Input input; 14 | private final String playlist; 15 | private final long value; 16 | 17 | StatisticValue(String key, long value) { 18 | // the type of statistic, ex: placetop1 19 | final var typeRaw = key.startsWith("s11") ? "s11_social_bp_level" : StringUtils.substringBetween(key, "br_", "_"); 20 | // If typeRaw == null we hit a weird ass value like 'crucible2_timezone4_keyboardmouse_m0_playlist_crucible_solo' 21 | // TODO: Once I figure out whatever those values are (there are different timezone values too) support it? 22 | type = typeRaw == null ? StatisticType.UNKNOWN.identifier(key) : StatisticType.typeOf(typeRaw); 23 | 24 | // within unknown values, all other types will be null. 25 | 26 | // the input, ex: touch 27 | final var inputRaw = StringUtils.substringBetween(key, "br_" + type.identifier() + "_", "_m0_"); 28 | input = Input.typeOf(inputRaw); 29 | 30 | // the playlist, ex: 'playlist_defaultsolo' 31 | playlist = StringUtils.substringAfter(key, inputRaw + "_m0_"); 32 | this.value = value; 33 | } 34 | 35 | /** 36 | * @return the type of statistic. 37 | */ 38 | StatisticType type() { 39 | return type; 40 | } 41 | 42 | /** 43 | * @return the input. 44 | */ 45 | Input input() { 46 | return input; 47 | } 48 | 49 | /** 50 | * @return the playlist. 51 | */ 52 | String playlist() { 53 | return playlist; 54 | } 55 | 56 | /** 57 | * @return the value. 58 | */ 59 | Long value() { 60 | return value; 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /src/main/java/athena/stats/resource/leaderboard/LeaderboardEntry.java: -------------------------------------------------------------------------------- 1 | package athena.stats.resource.leaderboard; 2 | 3 | /** 4 | * Represents a single leaderboard entry. 5 | */ 6 | public final class LeaderboardEntry { 7 | 8 | /** 9 | * The account ID. 10 | */ 11 | private String account; 12 | /** 13 | * The value. 14 | */ 15 | private int value; 16 | 17 | /** 18 | * @return the ID of the account. 19 | */ 20 | public String accountId() { 21 | return account; 22 | } 23 | 24 | /** 25 | * @return the value. 26 | */ 27 | public int value() { 28 | return value; 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /src/main/java/athena/stats/resource/leaderboard/LeaderboardResponse.java: -------------------------------------------------------------------------------- 1 | package athena.stats.resource.leaderboard; 2 | 3 | import java.util.LinkedHashMap; 4 | import java.util.LinkedList; 5 | import java.util.List; 6 | import java.util.stream.Collectors; 7 | 8 | /** 9 | * The response implementation 10 | */ 11 | public final class LeaderboardResponse { 12 | 13 | /** 14 | * List of entries. 15 | */ 16 | private LinkedList entries; 17 | 18 | /** 19 | * Collect the list of entries to a map and return. 20 | * 21 | * @return a map of entries, key is account ID and value is value. 22 | */ 23 | public LinkedHashMap mapOfEntries() { 24 | return entries.stream().collect(Collectors.toMap(LeaderboardEntry::accountId, LeaderboardEntry::value, ((integer, integer2) -> integer), LinkedHashMap::new)); 25 | } 26 | 27 | /** 28 | * @return list of entries. 29 | */ 30 | public List listOfEntries() { 31 | return entries; 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /src/main/java/athena/stats/resource/query/IndividualQueryResponse.java: -------------------------------------------------------------------------------- 1 | package athena.stats.resource.query; 2 | 3 | import java.util.Map; 4 | 5 | /** 6 | * Represents an individual query response. 7 | */ 8 | public final class IndividualQueryResponse { 9 | 10 | /** 11 | * Start and end times. 12 | */ 13 | private long startTime, endTime; 14 | 15 | /** 16 | * A map of all statistics. 17 | */ 18 | private Map stats; 19 | 20 | /** 21 | * The account ID of who these stats belong to. 22 | */ 23 | private String accountId; 24 | 25 | /** 26 | * @return the start time, usually 0. 27 | */ 28 | public long startTime() { 29 | return startTime; 30 | } 31 | 32 | /** 33 | * @return the end time usually a big ass number. 34 | */ 35 | public long endTime() { 36 | return endTime; 37 | } 38 | 39 | /** 40 | * @return a map of all statistics by type, ex: Key: br_placetop1_keyboardmouse_m0_playlist_defaultsolo, Value: 111222333 41 | */ 42 | public Map statistics() { 43 | return stats; 44 | } 45 | 46 | /** 47 | * @return the account ID of who these stats belong to. 48 | */ 49 | public String accountId() { 50 | return accountId; 51 | } 52 | 53 | /** 54 | * Get the value of the specified {@code stat} 55 | * 56 | * @param stat the type of value, eg: "br_placetop1_keyboardmouse_m0_playlist_defaultsolo" 57 | * @return the value represented as a long. 58 | */ 59 | public Long getValue(String stat) { 60 | return stats.get(stat); 61 | } 62 | 63 | } 64 | -------------------------------------------------------------------------------- /src/main/java/athena/stats/resource/type/StatisticType.java: -------------------------------------------------------------------------------- 1 | package athena.stats.resource.type; 2 | 3 | import java.util.List; 4 | 5 | public enum StatisticType { 6 | 7 | PLAYERS_OUTLIVED("playersoutlived"), 8 | KILLS("kills"), 9 | PLACED_TOP1("placetop1"), 10 | PLACED_TOP3("placetop3"), 11 | PLACED_TOP5("placetop5"), 12 | PLACED_TOP6("placetop6"), 13 | PLACED_TOP10("placetop10"), 14 | PLACED_TOP12("placetop12"), 15 | PLACED_TOP25("placetop25"), 16 | LAST_MODIFIED("lastmodified"), 17 | MINUTES_PLAYED("minutesplayed"), 18 | MATCHES_PLAYED("matchesplayed"), 19 | SCORE("score"), 20 | BP_LEVEL("s11_social_bp_level"), 21 | UNKNOWN(""); 22 | 23 | private static final List TYPES = List.of(values()); 24 | private String identifier; 25 | 26 | StatisticType(String identifier) { 27 | this.identifier = identifier; 28 | } 29 | 30 | public String identifier() { 31 | return identifier; 32 | } 33 | 34 | /** 35 | * Allow setting the identifier for unknown values. 36 | * @param identifier the identifier. 37 | */ 38 | public StatisticType identifier(String identifier) { 39 | this.identifier = identifier; 40 | return this; 41 | } 42 | 43 | /** 44 | * Gets the {@link StatisticType} from the provided {@code key} name. 45 | * 46 | * @param key the name of the statistic type. 47 | * @return a {@link StatisticType} or {@code null} if not found. 48 | */ 49 | public static StatisticType typeOf(String key) { 50 | if (key == null) return null; 51 | return TYPES.stream().filter(type -> type.identifier().equalsIgnoreCase(key)).findAny().orElse(null); 52 | } 53 | 54 | } 55 | -------------------------------------------------------------------------------- /src/main/java/athena/stats/service/StatsproxyPublicService.java: -------------------------------------------------------------------------------- 1 | package athena.stats.service; 2 | 3 | import athena.stats.resource.UnfilteredStatistic; 4 | import athena.stats.resource.leaderboard.LeaderboardResponse; 5 | import athena.stats.resource.query.IndividualQueryResponse; 6 | import athena.stats.resource.query.StatisticsQuery; 7 | import retrofit2.Call; 8 | import retrofit2.http.Body; 9 | import retrofit2.http.GET; 10 | import retrofit2.http.POST; 11 | import retrofit2.http.Path; 12 | 13 | import java.util.List; 14 | 15 | /** 16 | * Provides access to the stats service. 17 | */ 18 | public interface StatsproxyPublicService { 19 | 20 | /** 21 | * The base URL for the stats proxy service. 22 | */ 23 | String BASE_URL = "https://statsproxy-public-service-live.ol.epicgames.com/"; 24 | 25 | /** 26 | * Retrieve stats for the provided {@code accountId} 27 | * 28 | * @param accountId the ID of the account 29 | * @return a {@link UnfilteredStatistic} object that will contain the statistics. 30 | */ 31 | @GET("statsproxy/api/statsv2/account/{accountId}") 32 | Call stats(@Path("accountId") String accountId); 33 | 34 | /** 35 | * Query specific stats for some accounts. 36 | * 37 | * @param query the query body. 38 | * @return a {@link List} that contains each statistic represented as {@link IndividualQueryResponse} 39 | */ 40 | @POST("statsproxy/api/statsv2/query") 41 | Call> query(@Body StatisticsQuery query); 42 | 43 | /** 44 | * Retrieve leaderboard entries for a specific statistic. 45 | * 46 | * @param type the type of statistic, ex: 'br_placetop1_keyboardmouse_m0_playlist_defaultsolo' 47 | * @return a {@link LeaderboardResponse} that represents the response. 48 | */ 49 | @GET("statsproxy/api/statsv2/leaderboards/{type}") 50 | Call leaderboard(@Path("type") String type); 51 | 52 | } 53 | -------------------------------------------------------------------------------- /src/main/java/athena/types/Input.java: -------------------------------------------------------------------------------- 1 | package athena.types; 2 | 3 | import java.util.List; 4 | 5 | /** 6 | * Represents all the input types. 7 | */ 8 | public enum Input { 9 | 10 | KEYBOARD_AND_MOUSE("MouseAndKeyboard", "KeyboardMouse"), TOUCH("Touch"), GAMEPAD("Gamepad"); 11 | 12 | private static final List TYPES = List.of(values()); 13 | private final List names; 14 | 15 | Input(String... names) { 16 | this.names = List.of(names); 17 | } 18 | 19 | public List getNames() { 20 | return names; 21 | } 22 | 23 | /** 24 | * Gets the {@link Input} from the provided {@code key} name. 25 | * 26 | * @param key the name of the input 27 | * @return a {@link Input} or {@code null} if not found. 28 | */ 29 | public static Input typeOf(String key) { 30 | if (key == null) return null; 31 | return TYPES.stream().filter(type -> type.names.stream().anyMatch(key::equalsIgnoreCase)).findAny().orElse(null); 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /src/main/java/athena/types/Platform.java: -------------------------------------------------------------------------------- 1 | package athena.types; 2 | 3 | import java.util.List; 4 | 5 | /** 6 | * Represents all the platforms. 7 | */ 8 | public enum Platform { 9 | WIN("WIN", "Windows"), 10 | MAC("MAC", "Mac"), 11 | IOS("IOS"), 12 | AND("AND", "Android"), 13 | PSN("PS4", "PSN"), 14 | XBL("XBL", "XboxOne", "XUID", "XB1"), 15 | SWT("SWT", "Switch", "Nintendo"), 16 | NONE("NONE"); 17 | 18 | private static final List TYPES = List.of(values()); 19 | 20 | private final List names; 21 | 22 | Platform(String... names) { 23 | this.names = List.of(names); 24 | } 25 | 26 | /** 27 | * Attempt to get the platform types the {@code platform} is referencing. 28 | * 29 | * @param platform the platform 30 | * @return {@link Platform} or {@code null} if its an invalid platform. 31 | */ 32 | public static Platform typeOf(String platform) { 33 | if (platform == null) return null; 34 | return TYPES.stream().filter(type -> type.name().equalsIgnoreCase(platform) || type.names.stream().anyMatch(str -> str.equalsIgnoreCase(platform))).findAny().orElse(NONE); 35 | } 36 | 37 | /** 38 | * @return first name in the list. 39 | */ 40 | public String primaryName() { 41 | return names.get(0); 42 | } 43 | 44 | /** 45 | * @return all names. 46 | */ 47 | public List names() { 48 | return names; 49 | } 50 | 51 | } 52 | -------------------------------------------------------------------------------- /src/main/java/athena/types/Region.java: -------------------------------------------------------------------------------- 1 | package athena.types; 2 | 3 | public enum Region { 4 | 5 | NAE, NAW, ME, OCE, ASIA, EU, BR, ONSITE 6 | 7 | } 8 | -------------------------------------------------------------------------------- /src/main/java/athena/util/event/EventFactory.java: -------------------------------------------------------------------------------- 1 | package athena.util.event; 2 | 3 | import java.lang.annotation.Annotation; 4 | 5 | /** 6 | * Used to dispatch listener/annotated type events. 7 | */ 8 | public interface EventFactory { 9 | 10 | /** 11 | * Creates a new annotated factory. 12 | * 13 | * @param annotations the set of annotations that are valid. 14 | * @return a new {@link EventFactory} 15 | */ 16 | @SafeVarargs 17 | static EventFactory createAnnotatedFactory(Class... annotations) { 18 | return new EventFactoryImpl(annotations); 19 | } 20 | 21 | /** 22 | * Register an event listener. 23 | * 24 | * @param eventListener the class/type to register. 25 | */ 26 | void registerEventListener(Object eventListener); 27 | 28 | /** 29 | * Unregister an event listener. 30 | * 31 | * @param eventListener the class/type to register. 32 | */ 33 | void unregisterEventListener(Object eventListener); 34 | 35 | /** 36 | * Unregister all event listeners. 37 | */ 38 | void unregisterAll(); 39 | 40 | /** 41 | * Invoke an event type. 42 | * 43 | * @param annotation the annotation 44 | * @param arguments the arguments. 45 | */ 46 | void invoke(Class annotation, Object... arguments); 47 | 48 | /** 49 | * Dispose of this factory. 50 | */ 51 | void dispose(); 52 | 53 | } 54 | -------------------------------------------------------------------------------- /src/main/java/athena/util/json/builder/JsonArrayBuilder.java: -------------------------------------------------------------------------------- 1 | package athena.util.json.builder; 2 | 3 | import com.google.gson.JsonArray; 4 | import com.google.gson.JsonElement; 5 | 6 | /** 7 | * Utility class to build {@link com.google.gson.JsonArray}s 8 | */ 9 | public final class JsonArrayBuilder { 10 | 11 | private final JsonArray jsonArray = new JsonArray(); 12 | 13 | public JsonArrayBuilder add(String value) { 14 | jsonArray.add(value); 15 | return this; 16 | } 17 | 18 | public JsonArrayBuilder add(Number value) { 19 | jsonArray.add(value); 20 | return this; 21 | } 22 | 23 | public JsonArrayBuilder add(Boolean value) { 24 | jsonArray.add(value); 25 | return this; 26 | } 27 | 28 | public JsonArrayBuilder add(JsonElement value) { 29 | jsonArray.add(value); 30 | return this; 31 | } 32 | 33 | public JsonArray build() { 34 | return jsonArray; 35 | } 36 | 37 | } 38 | -------------------------------------------------------------------------------- /src/main/java/athena/util/json/builder/JsonObjectBuilder.java: -------------------------------------------------------------------------------- 1 | package athena.util.json.builder; 2 | 3 | import com.google.gson.JsonElement; 4 | import com.google.gson.JsonObject; 5 | 6 | /** 7 | * Utility class to build {@link com.google.gson.JsonObject}s 8 | */ 9 | public final class JsonObjectBuilder { 10 | 11 | private final JsonObject jsonObject = new JsonObject(); 12 | 13 | public JsonObjectBuilder add(String key, String value) { 14 | jsonObject.addProperty(key, value); 15 | return this; 16 | } 17 | 18 | public JsonObjectBuilder add(String key, Number value) { 19 | jsonObject.addProperty(key, value); 20 | return this; 21 | } 22 | 23 | public JsonObjectBuilder add(String key, Boolean value) { 24 | jsonObject.addProperty(key, value); 25 | return this; 26 | } 27 | 28 | public JsonObjectBuilder add(String key, JsonElement value) { 29 | jsonObject.add(key, value); 30 | return this; 31 | } 32 | 33 | public JsonObject build() { 34 | return jsonObject; 35 | } 36 | 37 | } 38 | -------------------------------------------------------------------------------- /src/main/java/athena/util/json/converters/InputConverter.java: -------------------------------------------------------------------------------- 1 | package athena.util.json.converters; 2 | 3 | import athena.types.Input; 4 | import com.google.gson.*; 5 | 6 | import java.lang.reflect.Type; 7 | 8 | /** 9 | * Used for serializing and deserializing the input type. 10 | */ 11 | public final class InputConverter implements JsonSerializer, JsonDeserializer { 12 | 13 | @Override 14 | public Input deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException { 15 | return Input.typeOf(json.getAsJsonPrimitive().getAsString()); 16 | } 17 | 18 | @Override 19 | public JsonElement serialize(Input src, Type typeOfSrc, JsonSerializationContext context) { 20 | return new JsonPrimitive(src.getNames().get(0)); 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /src/main/java/athena/util/json/converters/InstantConverter.java: -------------------------------------------------------------------------------- 1 | package athena.util.json.converters; 2 | 3 | import com.google.gson.*; 4 | 5 | import java.lang.reflect.Type; 6 | import java.time.Instant; 7 | import java.time.format.DateTimeFormatter; 8 | 9 | /** 10 | * Used to serialize and de-serialize {@link Instant} 11 | */ 12 | public final class InstantConverter implements JsonSerializer, JsonDeserializer { 13 | 14 | /** 15 | * The formatter for parsing dates. 16 | */ 17 | private static final DateTimeFormatter FORMATTER = DateTimeFormatter.ISO_INSTANT; 18 | 19 | @Override 20 | public Instant deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException { 21 | return Instant.parse(json.getAsString()); 22 | } 23 | 24 | @Override 25 | public JsonElement serialize(Instant src, Type typeOfSrc, JsonSerializationContext context) { 26 | return new JsonPrimitive(FORMATTER.format(src)); 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /src/main/java/athena/util/json/converters/JidConverter.java: -------------------------------------------------------------------------------- 1 | package athena.util.json.converters; 2 | 3 | import com.google.gson.*; 4 | import org.jxmpp.jid.Jid; 5 | import org.jxmpp.jid.impl.JidCreate; 6 | 7 | import java.lang.reflect.Type; 8 | 9 | /** 10 | * Converts the type {@link org.jxmpp.jid.Jid} 11 | */ 12 | public final class JidConverter implements JsonSerializer, JsonDeserializer { 13 | 14 | @Override 15 | public Jid deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException { 16 | return JidCreate.fromOrNull(json.getAsJsonPrimitive().getAsString()); 17 | } 18 | 19 | @Override 20 | public JsonElement serialize(Jid src, Type typeOfSrc, JsonSerializationContext context) { 21 | return new JsonPrimitive(src.asUnescapedString()); 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /src/main/java/athena/util/json/converters/LastOnlineResponseConverter.java: -------------------------------------------------------------------------------- 1 | package athena.util.json.converters; 2 | 3 | import athena.presence.resource.LastOnlineResponse; 4 | import com.google.gson.JsonDeserializationContext; 5 | import com.google.gson.JsonDeserializer; 6 | import com.google.gson.JsonElement; 7 | import com.google.gson.JsonParseException; 8 | 9 | import java.lang.reflect.Type; 10 | import java.time.Instant; 11 | import java.util.HashMap; 12 | 13 | /** 14 | * Used to deserialize {@link LastOnlineResponse} 15 | */ 16 | public final class LastOnlineResponseConverter implements JsonDeserializer { 17 | 18 | @Override 19 | public LastOnlineResponse deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException { 20 | final var object = json.getAsJsonObject(); 21 | final var map = new HashMap(); 22 | 23 | // iterate through each key and grab the array. 24 | object.keySet().forEach(key -> { 25 | final var array = object.getAsJsonArray(key); 26 | final var lastOnline = array.get(0).getAsJsonObject().get("last_online"); 27 | final var time = Instant.parse(lastOnline.getAsString()); 28 | map.put(key, time); 29 | }); 30 | return new LastOnlineResponse(map); 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /src/main/java/athena/util/json/converters/PlatformConverter.java: -------------------------------------------------------------------------------- 1 | package athena.util.json.converters; 2 | 3 | import athena.types.Platform; 4 | import com.google.gson.*; 5 | 6 | import java.lang.reflect.Type; 7 | 8 | /** 9 | * Converts the type {@link Platform} 10 | */ 11 | public final class PlatformConverter implements JsonSerializer, JsonDeserializer { 12 | 13 | @Override 14 | public Platform deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException { 15 | return Platform.typeOf(json.getAsJsonPrimitive().getAsString()); 16 | } 17 | 18 | @Override 19 | public JsonElement serialize(Platform src, Type typeOfSrc, JsonSerializationContext context) { 20 | return new JsonPrimitive(src.primaryName()); 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /src/main/java/athena/util/json/converters/RegionConverter.java: -------------------------------------------------------------------------------- 1 | package athena.util.json.converters; 2 | 3 | import athena.types.Region; 4 | import com.google.gson.*; 5 | 6 | import java.lang.reflect.Type; 7 | 8 | /** 9 | * Converts the type {@link athena.types.Region} 10 | */ 11 | public final class RegionConverter implements JsonSerializer, JsonDeserializer { 12 | 13 | @Override 14 | public Region deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException { 15 | return Region.valueOf(json.getAsJsonPrimitive().getAsString()); 16 | } 17 | 18 | @Override 19 | public JsonElement serialize(Region src, Type typeOfSrc, JsonSerializationContext context) { 20 | return new JsonPrimitive(src.name()); 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /src/main/java/athena/util/json/fortnite/annotation/FortniteArray.java: -------------------------------------------------------------------------------- 1 | package athena.util.json.fortnite.annotation; 2 | 3 | import java.lang.annotation.ElementType; 4 | import java.lang.annotation.Retention; 5 | import java.lang.annotation.RetentionPolicy; 6 | import java.lang.annotation.Target; 7 | 8 | /** 9 | * Represents a 'FortniteArray' 10 | * A JSON value that is wrapped inside a string. 11 | * For example: 12 | *

13 | * "MyValue_j" : "{\"MyValue\":[]}", 14 | */ 15 | @Retention(RetentionPolicy.RUNTIME) 16 | @Target(ElementType.FIELD) 17 | public @interface FortniteArray { 18 | /** 19 | * The wrapped name. 20 | * Using the example above this value would be "MyValue" 21 | * 22 | * @return the value 23 | */ 24 | String value(); 25 | 26 | /** 27 | * The type of object. 28 | * 29 | * @return the type 30 | */ 31 | Class type(); 32 | 33 | /** 34 | * Used for objects that are always constant values. 35 | * For example empty JSON arrays. 36 | * 37 | * @return if the value is constant. 38 | */ 39 | boolean isConstant() default false; 40 | 41 | /** 42 | * Identifies if this type is NOT a list. 43 | * 44 | * @return if this type is not a list. 45 | */ 46 | boolean isNotList() default false; 47 | 48 | } 49 | -------------------------------------------------------------------------------- /src/main/java/athena/util/json/fortnite/annotation/FortniteObject.java: -------------------------------------------------------------------------------- 1 | package athena.util.json.fortnite.annotation; 2 | 3 | import java.lang.annotation.ElementType; 4 | import java.lang.annotation.Retention; 5 | import java.lang.annotation.RetentionPolicy; 6 | import java.lang.annotation.Target; 7 | 8 | /** 9 | * * Represents a 'FortniteObject' 10 | * * A JSON value that is wrapped inside a string. 11 | * For example: 12 | *

13 | * "MyValue_j" : "{\"MyValue\":123}", 14 | */ 15 | @Retention(RetentionPolicy.RUNTIME) 16 | @Target(ElementType.FIELD) 17 | public @interface FortniteObject { 18 | /** 19 | * The wrapped name. 20 | * Using the example above this value would be "MyValue" 21 | * 22 | * @return the value 23 | */ 24 | String value(); 25 | 26 | } 27 | -------------------------------------------------------------------------------- /src/main/java/athena/util/json/hooks/Hooks.java: -------------------------------------------------------------------------------- 1 | package athena.util.json.hooks; 2 | 3 | import com.google.gson.Gson; 4 | import com.google.gson.TypeAdapter; 5 | import com.google.gson.TypeAdapterFactory; 6 | import com.google.gson.reflect.TypeToken; 7 | import com.google.gson.stream.JsonReader; 8 | import com.google.gson.stream.JsonWriter; 9 | 10 | import java.io.IOException; 11 | import java.lang.reflect.Method; 12 | import java.lang.reflect.Type; 13 | import java.util.ArrayList; 14 | import java.util.HashMap; 15 | import java.util.List; 16 | import java.util.Map; 17 | 18 | /** 19 | * Used to run actions after deserializing 20 | */ 21 | public final class Hooks implements TypeAdapterFactory { 22 | 23 | /** 24 | * Stores methods annotated with {@link PostDeserialize} 25 | */ 26 | private final Map> methodCache = new HashMap<>(); 27 | 28 | /** 29 | * Initiate with all of the class types 30 | * 31 | * @param types the classes 32 | * @return a new {@link Hooks} 33 | */ 34 | public static Hooks allOf(Class... types) { 35 | return new Hooks(types); 36 | } 37 | 38 | /** 39 | * Initialize and populate the map 40 | * 41 | * @param types the types 42 | */ 43 | private Hooks(Class... types) { 44 | for (var clazz : types) { 45 | final var list = new ArrayList(); 46 | for (var method : clazz.getDeclaredMethods()) { 47 | if (method.isAnnotationPresent(PostDeserialize.class)) { 48 | method.setAccessible(true); 49 | list.add(method); 50 | } 51 | } 52 | if (!list.isEmpty()) methodCache.put(clazz, list); 53 | } 54 | } 55 | 56 | @Override 57 | public TypeAdapter create(Gson gson, TypeToken type) { 58 | if (!methodCache.containsKey(type.getRawType())) return null; 59 | return new TypeAdapter<>() { 60 | private final List methods = methodCache.get(type.getRawType()); 61 | private final TypeAdapter original = gson.getDelegateAdapter(Hooks.this, type); 62 | 63 | @Override 64 | public void write(JsonWriter out, T value) throws IOException { 65 | original.write(out, value); 66 | } 67 | 68 | @Override 69 | public T read(JsonReader in) throws IOException { 70 | final var deserialized = original.read(in); 71 | methods.forEach(method -> { 72 | try { 73 | method.invoke(deserialized); 74 | } catch (Exception exception) { 75 | exception.printStackTrace(); 76 | } 77 | }); 78 | return deserialized; 79 | } 80 | }; 81 | } 82 | } 83 | -------------------------------------------------------------------------------- /src/main/java/athena/util/json/hooks/PostDeserialize.java: -------------------------------------------------------------------------------- 1 | package athena.util.json.hooks; 2 | 3 | import java.lang.annotation.ElementType; 4 | import java.lang.annotation.Retention; 5 | import java.lang.annotation.RetentionPolicy; 6 | import java.lang.annotation.Target; 7 | 8 | /** 9 | * Used to run actions after deserializing. 10 | */ 11 | @Retention(RetentionPolicy.RUNTIME) 12 | @Target(ElementType.METHOD) 13 | public @interface PostDeserialize { 14 | } 15 | -------------------------------------------------------------------------------- /src/main/java/athena/util/json/request/Request.java: -------------------------------------------------------------------------------- 1 | package athena.util.json.request; 2 | 3 | import java.lang.annotation.ElementType; 4 | import java.lang.annotation.Retention; 5 | import java.lang.annotation.RetentionPolicy; 6 | import java.lang.annotation.Target; 7 | 8 | /** 9 | * Used to request classes/services/resources 10 | */ 11 | @Retention(RetentionPolicy.RUNTIME) 12 | @Target(ElementType.FIELD) 13 | public @interface Request { 14 | 15 | /** 16 | * The item to request. 17 | */ 18 | Class item(); 19 | 20 | /** 21 | * Indicates if the value is the local account. 22 | * 23 | * @return {@code true} if so. 24 | */ 25 | boolean local() default false; 26 | 27 | } 28 | -------------------------------------------------------------------------------- /src/main/java/athena/util/request/Result.java: -------------------------------------------------------------------------------- 1 | package athena.util.request; 2 | 3 | import athena.exception.EpicGamesErrorException; 4 | 5 | /** 6 | * Represents an asynchronous result. 7 | * 8 | * @param TYPE. 9 | */ 10 | public interface Result { 11 | 12 | /** 13 | * Invoked when the call is completed/executed. 14 | * 15 | * @param result the result, will be {@code null} if {@code failed} == true. 16 | * @param failed {@code true} if the request failed. 17 | * @param error the error, will be {@code null} if {@code failed} == false. 18 | */ 19 | void result(T result, boolean failed, EpicGamesErrorException error); 20 | 21 | } 22 | --------------------------------------------------------------------------------