diff --git a/.gitignore b/.gitignore index 940794e..5cce309 100644 --- a/.gitignore +++ b/.gitignore @@ -286,3 +286,5 @@ __pycache__/ *.btm.cs *.odx.cs *.xsd.cs + +push.bat \ No newline at end of file diff --git a/VRChatApi/TestClient/App.config b/VRChatApi/TestClient/App.config new file mode 100644 index 0000000..731f6de --- /dev/null +++ b/VRChatApi/TestClient/App.config @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/VRChatApi/TestClient/Properties/AssemblyInfo.cs b/VRChatApi/TestClient/Properties/AssemblyInfo.cs new file mode 100644 index 0000000..d753e44 --- /dev/null +++ b/VRChatApi/TestClient/Properties/AssemblyInfo.cs @@ -0,0 +1,36 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. +[assembly: AssemblyTitle("TestClient")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("")] +[assembly: AssemblyProduct("TestClient")] +[assembly: AssemblyCopyright("Copyright © 2018")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// Setting ComVisible to false makes the types in this assembly not visible +// to COM components. If you need to access a type in this assembly from +// COM, set the ComVisible attribute to true on that type. +[assembly: ComVisible(false)] + +// The following GUID is for the ID of the typelib if this project is exposed to COM +[assembly: Guid("51e73a81-edc2-4790-90ca-38de49ff20c9")] + +// Version information for an assembly consists of the following four values: +// +// Major Version +// Minor Version +// Build Number +// Revision +// +// You can specify all the values or you can default the Build and Revision Numbers +// by using the '*' as shown below: +// [assembly: AssemblyVersion("1.0.*")] +[assembly: AssemblyVersion("1.0.0.0")] +[assembly: AssemblyFileVersion("1.0.0.0")] diff --git a/VRChatApi/VRChatApi.Tests/VRChatApi.Tests.csproj b/VRChatApi/VRChatApi.Tests/VRChatApi.Tests.csproj index 81e3ad1..153a2b4 100644 --- a/VRChatApi/VRChatApi.Tests/VRChatApi.Tests.csproj +++ b/VRChatApi/VRChatApi.Tests/VRChatApi.Tests.csproj @@ -11,11 +11,11 @@ - - - - - + + + + + all runtime; build; native; contentfiles; analyzers diff --git a/VRChatApi/VRChatApi/Classes/AvatarResponse.cs b/VRChatApi/VRChatApi/Classes/AvatarResponse.cs index 614958d..74d5f7c 100644 --- a/VRChatApi/VRChatApi/Classes/AvatarResponse.cs +++ b/VRChatApi/VRChatApi/Classes/AvatarResponse.cs @@ -1,12 +1,33 @@ -using System; +using Newtonsoft.Json; +using System; using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; + +#pragma warning disable IDE1006 namespace VRChatApi.Classes { - public class AvatarResponse + public class AssetUrlObject + { + } + + public class UnityPackage + { + public string id { get; set; } + public string assetUrl { get; set; } + public AssetUrlObject assetUrlObject { get; set; } + public string unityVersion { get; set; } + public long unitySortNumber { get; set; } + public int assetVersion { get; set; } + public string platform { get; set; } + public DateTime created_at { get; set; } + } + + public class UnityPackageUrlObject + { + public string unityPackageUrl { get; set; } + } + + public class AvatarResponse : Response { public string id { get; set; } public string name { get; set; } @@ -15,6 +36,7 @@ public class AvatarResponse public string authorName { get; set; } public List tags { get; set; } public string assetUrl { get; set; } + public AssetUrlObject assetUrlObject { get; set; } public string imageUrl { get; set; } public string thumbnailImageUrl { get; set; } public string releaseStatus { get; set; } @@ -23,6 +45,8 @@ public class AvatarResponse public List unityPackages { get; set; } public bool unityPackageUpdated { get; set; } public string unityPackageUrl { get; set; } - + public UnityPackageUrlObject unityPackageUrlObject { get; set; } + public DateTime created_at { get; set; } + public DateTime updated_at { get; set; } } } diff --git a/VRChatApi/VRChatApi/Classes/ConfigResponse.cs b/VRChatApi/VRChatApi/Classes/ConfigResponse.cs index 6442a0e..bc6c3c1 100644 --- a/VRChatApi/VRChatApi/Classes/ConfigResponse.cs +++ b/VRChatApi/VRChatApi/Classes/ConfigResponse.cs @@ -1,8 +1,28 @@ -using System.Collections.Generic; +using Newtonsoft.Json; +using System.Collections.Generic; + +#pragma warning disable IDE1006 namespace VRChatApi.Classes { - public class ConfigResponse + public class DynamicWorldRow + { + public string name { get; set; } + public string sortHeading { get; set; } + public string sortOwnership { get; set; } + public string sortOrder { get; set; } + public string platform { get; set; } + public int index { get; set; } + public string tag { get; set; } + } + + public class Announcement + { + public string name { get; set; } + public string text { get; set; } + } + + public class ConfigResponse : Response { public string messageOfTheDay { get; set; } public string timeOutWorldId { get; set; } @@ -11,6 +31,7 @@ public class ConfigResponse public string downloadLinkWindows { get; set; } public string releaseAppVersionStandalone { get; set; } public string devAppVersionStandalone { get; set; } + public string devServerVersionStandalone { get; set; } public string devDownloadLinkWindows { get; set; } public int currentTOSVersion { get; set; } public string releaseSdkUrl { get; set; } @@ -26,14 +47,36 @@ public class ConfigResponse public string tutorialWorldId { get; set; } public bool disableEventStream { get; set; } public bool disableAvatarGating { get; set; } - public List registrationShitList { get; set; } + public bool disableFeedbackGating { get; set; } + public bool disableRegistration { get; set; } + public bool disableUpgradeAccount { get; set; } + public bool disableCommunityLabs { get; set; } + public bool disableCommunityLabsPromotion { get; set; } + public bool disableTwoFactorAuth { get; set; } + public bool disableSteamNetworking { get; set; } public string plugin { get; set; } + public string sdkNotAllowedToPublishMessage { get; set; } + public string sdkDeveloperFaqUrl { get; set; } + public string sdkDiscordUrl { get; set; } + public string notAllowedToSelectAvatarInPrivateWorldMessage { get; set; } + public int userVerificationTimeout { get; set; } + public int userUpdatePeriod { get; set; } + public int userVerificationDelay { get; set; } + public int userVerificationRetry { get; set; } + public int worldUpdatePeriod { get; set; } + public int moderationQueryPeriod { get; set; } + public int clientDisconnectTimeout { get; set; } + public string defaultAvatar { get; set; } + public List dynamicWorldRows { get; set; } + public bool disableAvatarCopying { get; set; } + public List announcements { get; set; } public string address { get; set; } public string contactEmail { get; set; } public string supportEmail { get; set; } public string jobsEmail { get; set; } public string copyrightEmail { get; set; } public string moderationEmail { get; set; } + public bool disableEmail { get; set; } public string appName { get; set; } public string serverName { get; set; } public string deploymentGroup { get; set; } diff --git a/VRChatApi/VRChatApi/Classes/FavoritesResponse.cs b/VRChatApi/VRChatApi/Classes/FavoritesResponse.cs new file mode 100644 index 0000000..fc60fe5 --- /dev/null +++ b/VRChatApi/VRChatApi/Classes/FavoritesResponse.cs @@ -0,0 +1,21 @@ +using Newtonsoft.Json; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace VRChatApi.Classes +{ + public class FavoritesResponse : Response + { + public string id { get; set; } + public string type { get; set; } + public string favoriteId { get; set; } + public string[] tags { get; set; } + } + public enum FavoriteType + { + + } +} diff --git a/VRChatApi/VRChatApi/Classes/FavouriteResponse.cs b/VRChatApi/VRChatApi/Classes/FavouriteResponse.cs new file mode 100644 index 0000000..295ca37 --- /dev/null +++ b/VRChatApi/VRChatApi/Classes/FavouriteResponse.cs @@ -0,0 +1,14 @@ +using System.Collections.Generic; + +#pragma warning disable IDE1006 + +namespace VRChatApi.Classes +{ + public class FavouriteResponse : Response + { + public string id { get; set; } + public string type { get; set; } + public string favoriteId { get; set; } + public List tags { get; set; } + } +} diff --git a/VRChatApi/VRChatApi/Classes/NotificationResponse.cs b/VRChatApi/VRChatApi/Classes/NotificationResponse.cs index a4595a6..68014a4 100644 --- a/VRChatApi/VRChatApi/Classes/NotificationResponse.cs +++ b/VRChatApi/VRChatApi/Classes/NotificationResponse.cs @@ -1,23 +1,38 @@ -using System; -using System.ComponentModel; -using Newtonsoft.Json; -using Newtonsoft.Json.Linq; +using Newtonsoft.Json; +using System; + +#pragma warning disable IDE1006 namespace VRChatApi.Classes { - public class NotificationResponse + public class NotificationDetails { - public string id { get; set; } - public string type { get; set; } - public string senderUserId { get; set; } - public string receiverUserId { get; set; } - public string message { get; set; } - public JObject details { get; set; } // unknown - public string jobName { get; set; } - public string jobColor { get; set; } - - [Obsolete("Typoed property, use receiverUserId instead")] + public string WorldId { get; set; } [JsonIgnore] - public string recieverUserId { get => receiverUserId; set => receiverUserId = value; } + public bool rsvp { get; set; } + public string WorldName { get; set; } + } + + public class NotificationResponse : Response + { + public string Id { get; set; } + public string Type { get; set; } + public string SenderUserId { get; set; } + public string SenderUsername { get; set; } + public string ReceiverUserId { get; set; } + public string Message { get; set; } + [JsonProperty(PropertyName = "created_at")] + public string Created { get; set; } + public DateTime CreatedAt { get { return Convert.ToDateTime(Created); } } + public string JobName { get; set; } + public string JobColor { get; set; } + } + public class NotificationResponseWithDetails : NotificationResponse + { + public NotificationDetails Details { get; set; } + } + public class NotificationResponseWithSeen : NotificationResponse + { + public bool Seen { get; set; } } } diff --git a/VRChatApi/VRChatApi/Classes/PlayerModeratedResponse.cs b/VRChatApi/VRChatApi/Classes/PlayerModeratedResponse.cs index fce2883..e4e3201 100644 --- a/VRChatApi/VRChatApi/Classes/PlayerModeratedResponse.cs +++ b/VRChatApi/VRChatApi/Classes/PlayerModeratedResponse.cs @@ -4,9 +4,11 @@ using System.Text; using System.Threading.Tasks; +#pragma warning disable IDE1006 + namespace VRChatApi.Classes { - public class PlayerModeratedResponse + public class PlayerModeratedResponse : Response { public string id { get; set; } public string type { get; set; } @@ -14,6 +16,6 @@ public class PlayerModeratedResponse public string sourceDisplayName { get; set; } public string targetUserId { get; set; } public string targetDisplayName { get; set; } - public string created { get; set; } + public DateTime created { get; set; } } } diff --git a/VRChatApi/VRChatApi/Classes/Response.cs b/VRChatApi/VRChatApi/Classes/Response.cs new file mode 100644 index 0000000..fce3082 --- /dev/null +++ b/VRChatApi/VRChatApi/Classes/Response.cs @@ -0,0 +1,59 @@ +using Newtonsoft.Json; +using System; +using System.Collections.Generic; +using System.Net.Http; +using System.Text; +using System.Threading.Tasks; + +namespace VRChatApi.Classes +{ + public class Response + { + + [JsonIgnore] + public HttpResponseMessage Raw { get; set; } + /*public object Content { get; set; } + public object Status { get; set; } + public async Task FromResponseMessageAsync(HttpResponseMessage response) { // , object content = null + // if (content != null) Content = content; + if (response != null) { + Raw = response; + string json = await response.Content.ReadAsStringAsync(); + try { Status = JsonConvert.DeserializeObject(json); + } catch { Status = JsonConvert.DeserializeObject(json); } + } + return this; + }*/ + } + public class Message + { + [JsonProperty(PropertyName = "message")] + public string _message { get; set; } + [JsonIgnore] + public string Content { get { return _message; } } + public int status_code { get; set; } + [JsonIgnore] + public System.Net.HttpStatusCode StatusCode { get { return (System.Net.HttpStatusCode)status_code; } } + } + + public class Success + { + public Message success { get; set; } + } + public class Error + { + public Message error { get; set; } + } + public class BanResponse : Error + { + [JsonIgnore] + public bool Banned { get { return (ExpiresAt < DateTime.Now) ? true : false; } } + public string Target { get; set; } + public string Reason { get; set; } + public string Expires { get; set; } + [JsonIgnore] + public DateTime ExpiresAt { get { return Convert.ToDateTime(Expires); } } + [JsonIgnore] + public TimeSpan ExpiresIn { get { return ExpiresAt - DateTime.Now; } } + } +} diff --git a/VRChatApi/VRChatApi/Classes/UserBriefResponse.cs b/VRChatApi/VRChatApi/Classes/UserBriefResponse.cs index fc12710..4dc0498 100644 --- a/VRChatApi/VRChatApi/Classes/UserBriefResponse.cs +++ b/VRChatApi/VRChatApi/Classes/UserBriefResponse.cs @@ -1,20 +1,60 @@ using System.Collections.Generic; +using Newtonsoft.Json; + +#pragma warning disable IDE1006 namespace VRChatApi.Classes { - public class UserBriefResponse + public class UserStatus + { + public enum Status + { + Unknown, Offline, Busy, Active, JoinMe + } + public Status FromString(string status) + { + switch (status.ToLowerInvariant()) + { + case "join me": + return Status.JoinMe; + case "active": + return Status.Active; + case "busy": + return Status.Busy; + case "offline": + return Status.Offline; + default: + return Status.Unknown; + } + } + public string ToString(Status status) + { + switch (status) + { + case Status.Offline: return "offline"; + case Status.Busy: return "busy"; + case Status.Active: return "active"; + case Status.JoinMe: return "join me"; + default: return ""; + } + } + } + public class UserBriefResponse : Response { + [JsonIgnore] + public bool Offline { get; set; } public string id { get; set; } public string username { get; set; } public string displayName { get; set; } public string currentAvatarImageUrl { get; set; } public string currentAvatarThumbnailImageUrl { get; set; } - public string developerType { get; set; } + public string last_platform { get; set; } public List tags { get; set; } + public string developerType { get; set; } public string status { get; set; } public string statusDescription { get; set; } + public string friendKey { get; set; } + public bool isFriend { get; set; } public string location { get; set; } - public string worldId { get; set; } - public string instanceId { get; set; } } } diff --git a/VRChatApi/VRChatApi/Classes/UserResponse.cs b/VRChatApi/VRChatApi/Classes/UserResponse.cs index c92cb78..c16cc55 100644 --- a/VRChatApi/VRChatApi/Classes/UserResponse.cs +++ b/VRChatApi/VRChatApi/Classes/UserResponse.cs @@ -1,31 +1,52 @@ -using Newtonsoft.Json.Linq; +using System; using System.Collections.Generic; +#pragma warning disable IDE1006 + namespace VRChatApi.Classes { public class PastDisplayName { - string displayName { get; set; } - string updated_at { get; set; } + public string displayName { get; set; } + public DateTime updated_at { get; set; } + } + + public class SteamDetails + { + } + + public class Feature + { + public bool twoFactorAuth { get; set; } } public class UserResponse : UserBriefResponse { public List pastDisplayNames { get; set; } public bool hasEmail { get; set; } + public bool hasPendingEmail { get; set; } public string obfuscatedEmail { get; set; } + public string obfuscatedPendingEmail { get; set; } public bool emailVerified { get; set; } public bool hasBirthday { get; set; } public bool unsubscribe { get; set; } public List friends { get; set; } - public JObject blueprints { get; set; } - public JObject currentAvatarBlueprint { get; set; } - public List events { get; set; } + public List friendGroupNames { get; set; } public string currentAvatar { get; set; } public string currentAvatarAssetUrl { get; set; } public int acceptedTOSVersion { get; set; } - public JObject steamDetails { get; set; } + public string steamId { get; set; } + public SteamDetails steamDetails { get; set; } + public string oculusId { get; set; } public bool hasLoggedInFromClient { get; set; } - public string authToken { get; set; } + public string homeLocation { get; set; } + public bool twoFactorAuthEnabled { get; set; } + public Feature feature { get; set; } + public string state { get; set; } + public DateTime last_login { get; set; } + public bool allowAvatarCopying { get; set; } + public List onlineFriends { get; set; } + public List activeFriends { get; set; } + public List offlineFriends { get; set; } } } diff --git a/VRChatApi/VRChatApi/Classes/WorldBriefResponse.cs b/VRChatApi/VRChatApi/Classes/WorldBriefResponse.cs index 8aa9154..eed6244 100644 --- a/VRChatApi/VRChatApi/Classes/WorldBriefResponse.cs +++ b/VRChatApi/VRChatApi/Classes/WorldBriefResponse.cs @@ -1,27 +1,36 @@ using System; using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; using Newtonsoft.Json; -using Newtonsoft.Json.Linq; using Newtonsoft.Json.Converters; +#pragma warning disable IDE1006 + namespace VRChatApi.Classes { - public class WorldBriefResponse + public class WorldBriefResponse : Response { public string id { get; set; } public string name { get; set; } + public string authorId { get; set; } public string authorName { get; set; } - public int totalLikes { get; set; } - public int totalVisits { get; set; } + public int capacity { get; set; } public string imageUrl { get; set; } public string thumbnailImageUrl { get; set; } - public bool isSecure { get; set; } // Unknown + [JsonConverter(typeof(StringEnumConverter))] public ReleaseStatus releaseStatus { get; set; } - public string organization { get; set; } // Unknown + + public string organization { get; set; } + public List tags { get; set; } + public int favorites { get; set; } + public DateTime created_at { get; set; } + public DateTime updated_at { get; set; } + public DateTime publicationDate { get; set; } + public DateTime labsPublicationDate { get; set; } + public int visits { get; set; } + public List unityPackages { get; set; } + public int popularity { get; set; } + public int heat { get; set; } public int occupants { get; set; } } } diff --git a/VRChatApi/VRChatApi/Classes/WorldEnums.cs b/VRChatApi/VRChatApi/Classes/WorldEnums.cs index 52bf753..89cde54 100644 --- a/VRChatApi/VRChatApi/Classes/WorldEnums.cs +++ b/VRChatApi/VRChatApi/Classes/WorldEnums.cs @@ -1,8 +1,4 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; +using System.ComponentModel; namespace VRChatApi.Classes { @@ -22,9 +18,13 @@ public enum SortOptions public enum ReleaseStatus { + [Description("public")] Public, + [Description("private")] Private, + [Description("all")] All, + [Description("hidden")] Hidden, } diff --git a/VRChatApi/VRChatApi/Classes/WorldInstanceResponse.cs b/VRChatApi/VRChatApi/Classes/WorldInstanceResponse.cs index af9f576..346b351 100644 --- a/VRChatApi/VRChatApi/Classes/WorldInstanceResponse.cs +++ b/VRChatApi/VRChatApi/Classes/WorldInstanceResponse.cs @@ -1,14 +1,11 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; +using System.Collections.Generic; using Newtonsoft.Json; -using Newtonsoft.Json.Linq; + +#pragma warning disable IDE1006 namespace VRChatApi.Classes { - public class WorldInstanceResponse + public class WorldInstanceResponse : Response { public string id { get; set; } public string name { get; set; } diff --git a/VRChatApi/VRChatApi/Classes/WorldInstanceUserResponse.cs b/VRChatApi/VRChatApi/Classes/WorldInstanceUserResponse.cs index bf0b33b..06fa857 100644 --- a/VRChatApi/VRChatApi/Classes/WorldInstanceUserResponse.cs +++ b/VRChatApi/VRChatApi/Classes/WorldInstanceUserResponse.cs @@ -8,7 +8,7 @@ namespace VRChatApi.Classes { - public class WorldInstanceUserResponse + public class WorldInstanceUserResponse : Response { public string id { get; set; } public string username { get; set; } diff --git a/VRChatApi/VRChatApi/Classes/WorldMetadataResponse.cs b/VRChatApi/VRChatApi/Classes/WorldMetadataResponse.cs index d343781..db60303 100644 --- a/VRChatApi/VRChatApi/Classes/WorldMetadataResponse.cs +++ b/VRChatApi/VRChatApi/Classes/WorldMetadataResponse.cs @@ -1,15 +1,85 @@ using System; using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; -using Newtonsoft.Json.Linq; + +#pragma warning disable IDE1006 namespace VRChatApi.Classes { - public class WorldMetadataResponse + public class EventPortal + { + public string eventName { get; set; } + public string worldId { get; set; } + public DateTime eventStartTimeUtc { get; set; } + public string eventDuration { get; set; } + } + + public class Metadata + { + public string CENTER_TEXT { get; set; } + public string CENTER_TEXT2 { get; set; } + public List PANOS { get; set; } + public List AVATAR_CUSTOM { get; set; } + public List AVATAR_FEATURED { get; set; } + public List AVATAR_HELP { get; set; } + public List AVATAR_MORPH { get; set; } + public List AVATAR_PEDESTAL { get; set; } + public List EVENTHALL_WELCOME { get; set; } + public List EVENTHAPPENING { get; set; } + public List EVENTS { get; set; } + public List MICROPHONE { get; set; } + public List PANOSPHERE { get; set; } + public List TIPS { get; set; } + public List WELCOME { get; set; } + public List WELCOME_2 { get; set; } + public List WORLD_CREATION { get; set; } + public List WORLD_FEATURED_ONE { get; set; } + public List WORLD_FEATURED_THREE { get; set; } + public List WORLD_FEATURED_TWO { get; set; } + public List WORLD_HELP { get; set; } + public List HELP_ROOM_1 { get; set; } + public List HELP_ROOM_2 { get; set; } + public List HELP_ROOM_3 { get; set; } + public List HELP_ROOM_4 { get; set; } + public List STAFF_PORTAL_1 { get; set; } + public string STAFF_CREATOR_1 { get; set; } + public List STAFF_IMAGE_1 { get; set; } + public List STAFF_PORTAL_2 { get; set; } + public string STAFF_CREATOR_2 { get; set; } + public List STAFF_IMAGE_2 { get; set; } + public List STAFF_PORTAL_3 { get; set; } + public string STAFF_CREATOR_3 { get; set; } + public List STAFF_IMAGE_3 { get; set; } + public string AVATAR_1 { get; set; } + public string AVATAR_2 { get; set; } + public string AVATAR_3 { get; set; } + public List EVENT_CALENDAR { get; set; } + public List LOCATION_SPAWN { get; set; } + public List HELP_WELCOME { get; set; } + public List AVATAR_WELCOME { get; set; } + public List NEW_WORLDS_WELCOME { get; set; } + public List FEATURED_WORLDS_WELCOME { get; set; } + public List EVENTHALL_MARQUEE { get; set; } + public List FOUNTAIN_WELCOME { get; set; } + public List EVENT_PORTAL { get; set; } + public List HELP_PORTAL_1 { get; set; } + public List HELP_PORTAL_2 { get; set; } + public bool NameplatesVisibleByDefault { get; set; } + public List HELP_PORTALS { get; set; } + public List EVENT_PORTAL_1 { get; set; } + public List EVENT_PORTAL_2 { get; set; } + public List EVENT_PORTAL_3 { get; set; } + public List EVENT_PORTAL_4 { get; set; } + public List AVATAR_PORTAL_1 { get; set; } + public List AVATAR_PORTAL_2 { get; set; } + public List AVATAR_STATIC_PORTAL_1 { get; set; } + public List AVATAR_STATIC_PORTAL_2 { get; set; } + public List FIREPIT_PORTAL_2 { get; set; } + public List FIREPIT_PORTAL_1 { get; set; } + } + + public class WorldMetadataResponse : Response { public string id { get; set; } - public JObject metadata { get; set; } + public Metadata metadata { get; set; } } } diff --git a/VRChatApi/VRChatApi/Classes/WorldResponse.cs b/VRChatApi/VRChatApi/Classes/WorldResponse.cs index e3ae0d6..61e52a7 100644 --- a/VRChatApi/VRChatApi/Classes/WorldResponse.cs +++ b/VRChatApi/VRChatApi/Classes/WorldResponse.cs @@ -1,64 +1,36 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; +using System.Collections.Generic; using Newtonsoft.Json; using Newtonsoft.Json.Linq; using Newtonsoft.Json.Converters; +#pragma warning disable IDE1006 + namespace VRChatApi.Classes { - public class UnityPackage - { - public string id { get; set; } - public string assetUrl { get; set; } - public string pluginUrl { get; set; } - public string unityVersion { get; set; } - public int unitySortNumber { get; set; } - public int assetVersion { get; set; } - public string platform { get; set; } - [JsonProperty(PropertyName = "created_at")] - public string createdTime { get; set; } - } - public class WorldInstance { public string id { get; set; } public int occupants { get; set; } } - public class WorldResponse + public class WorldResponse : WorldBriefResponse { - public string id { get; set; } - public string name { get; set; } public string description { get; set; } public bool featured { get; set; } - public string authorId { get; set; } - public string authorName { get; set; } public int totalLikes { get; set; } public int totalVisits { get; set; } - public short capacity { get; set; } - public List tags { get; set; } - [JsonConverter(typeof(StringEnumConverter))] - public ReleaseStatus releaseStatus { get; set; } - public string imageUrl { get; set; } - public string thumbnailImageUrl { get; set; } public string assetUrl { get; set; } public string pluginUrl { get; set; } public string unityPackageUrl { get; set; } [JsonProperty(PropertyName = "namespace")] public string nameSpace { get; set; } // Unknown public bool unityPackageUpdated { get; set; } // Unknown - public List unityPackages { get; set; } public bool isSecure { get; set; } // Unknown public bool isLockdown { get; set; } // Unknown public int version { get; set; } - public string organization { get; set; } // Unknown [JsonProperty(PropertyName = "instances")] public List _instances { get; set; } [JsonIgnore] public List instances { get; set; } - public int occupants { get; set; } } } diff --git a/VRChatApi/VRChatApi/Endpoints/AvatarApi.cs b/VRChatApi/VRChatApi/Endpoints/AvatarApi.cs index 820c4fe..99f24dc 100644 --- a/VRChatApi/VRChatApi/Endpoints/AvatarApi.cs +++ b/VRChatApi/VRChatApi/Endpoints/AvatarApi.cs @@ -1,10 +1,7 @@ -using System; -using System.Collections.Generic; -using System.Linq; +using System.Collections.Generic; using System.Net.Http; using System.Text; using System.Threading.Tasks; -using Newtonsoft.Json; using VRChatApi.Classes; using VRChatApi.Logging; @@ -17,19 +14,25 @@ public class AvatarApi public async Task GetById(string id) { Logger.Debug(() => $"Getting avatar details using ID: {id}"); - HttpResponseMessage response = await Global.HttpClient.GetAsync($"avatars/{id}?apiKey={Global.ApiKey}"); - AvatarResponse res = null; + HttpResponseMessage response = await Global.HttpClient.GetAsync($"avatars/{id}?apiKey={Global.ApiKey}"); - if (response.IsSuccessStatusCode) - { - var json = await response.Content.ReadAsStringAsync(); - Logger.Debug(() => $"JSON received: {json}"); + return await Utils.ParseResponse(response); + } + public async Task> Personal(ReleaseStatus releaseStatus = ReleaseStatus.All, int amount = 100) => await List(releaseStatus: releaseStatus, amount: amount, user: "me"); - res = JsonConvert.DeserializeObject(json); - } + public async Task> List(ReleaseStatus releaseStatus = ReleaseStatus.All, int amount = 100, string user = null) + { + var sb = new StringBuilder(); + if (!string.IsNullOrEmpty(user)) sb.Append($"&user={user}"); + HttpResponseMessage response = await Global.HttpClient.GetAsync($"avatars?apiKey={Global.ApiKey}&releaseStatus={releaseStatus.GetDescription()}&n={amount}{sb.ToString()}"); + return await Utils.ParseResponse>(response); + } - return res; + public async Task> Favorites(int amount = 16) + { + HttpResponseMessage response = await Global.HttpClient.GetAsync($"avatars/favorites?apiKey={Global.ApiKey}&n={amount}"); + return await Utils.ParseResponse>(response); } } } diff --git a/VRChatApi/VRChatApi/Endpoints/FavoritesAPI.cs b/VRChatApi/VRChatApi/Endpoints/FavoritesAPI.cs new file mode 100644 index 0000000..f0a84c2 --- /dev/null +++ b/VRChatApi/VRChatApi/Endpoints/FavoritesAPI.cs @@ -0,0 +1,32 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Net.Http; +using System.Text; +using System.Threading.Tasks; +using Newtonsoft.Json; +using VRChatApi.Classes; +using VRChatApi.Logging; + +namespace VRChatApi.Endpoints +{ + public class FavoritesAPI + { + private static readonly ILog Logger = LogProvider.GetCurrentClassLogger(); + public async Task> Get(string type = null) + { + bool hasType = (type != null); + HttpResponseMessage response = await Global.HttpClient.GetAsync($"favorites?apiKey={Global.ApiKey}{(hasType ? $"&type={type}":"")}"); + List res = null; + if (response.IsSuccessStatusCode) + { + var json = await response.Content.ReadAsStringAsync(); + Logger.Debug(() => $"JSON received: {json}"); + + res = JsonConvert.DeserializeObject>(json); + } + + return res; + } + } +} diff --git a/VRChatApi/VRChatApi/Endpoints/FavouriteApi.cs b/VRChatApi/VRChatApi/Endpoints/FavouriteApi.cs new file mode 100644 index 0000000..a347ab2 --- /dev/null +++ b/VRChatApi/VRChatApi/Endpoints/FavouriteApi.cs @@ -0,0 +1,46 @@ +using Newtonsoft.Json.Linq; +using System.Collections.Generic; +using System.Net.Http; +using System.Net.Http.Headers; +using System.Text; +using System.Threading.Tasks; +using VRChatApi.Classes; + +namespace VRChatApi.Endpoints +{ + public class FavouriteApi + { + + public async Task FavouriteAvatar(string avatarId) + { + JObject json = new JObject() + { + { "type", "avatar" }, + { "favoriteId", avatarId }, + { "tags", new JArray(new[] { "avatars1" })} + }; + + StringContent content = new StringContent(json.ToString(), Encoding.UTF8); + + content.Headers.ContentType = new MediaTypeHeaderValue("application/json"); + + HttpResponseMessage response = await Global.HttpClient.PostAsync($"favorites?apiKey={Global.ApiKey}", content); + + return await Utils.ParseResponse(response); + } + + public async Task> GetFavourites(string favouriteType = "avatar") + { + HttpResponseMessage response = await Global.HttpClient.GetAsync($"favorites?type={favouriteType}&apiKey={Global.ApiKey}"); + + return await Utils.ParseResponse>(response); + } + + public async Task GetFavourite(string favouriteId) + { + HttpResponseMessage response = await Global.HttpClient.GetAsync($"favorites/{favouriteId}?apiKey={Global.ApiKey}"); + + return await Utils.ParseResponse(response); + } + } +} diff --git a/VRChatApi/VRChatApi/Endpoints/FriendsApi.cs b/VRChatApi/VRChatApi/Endpoints/FriendsApi.cs index d81eed7..2766304 100644 --- a/VRChatApi/VRChatApi/Endpoints/FriendsApi.cs +++ b/VRChatApi/VRChatApi/Endpoints/FriendsApi.cs @@ -4,7 +4,6 @@ using System.Net.Http.Headers; using System.Text; using System.Threading.Tasks; -using Newtonsoft.Json; using VRChatApi.Classes; using VRChatApi.Logging; @@ -20,24 +19,18 @@ public async Task> Get(int offset = 0, int count = 20, b HttpResponseMessage response = await Global.HttpClient.GetAsync($"auth/user/friends?apiKey={Global.ApiKey}&offset={offset}&n={count}&offline={offline.ToString().ToLowerInvariant()}"); - List res = null; - - if (response.IsSuccessStatusCode) - { - var json = await response.Content.ReadAsStringAsync(); - Logger.Debug(() => $"JSON received: {json}"); - res = JsonConvert.DeserializeObject>(json); - } - - return res; + return await Utils.ParseResponse>(response); } - public async Task SendRequest(string userId, string fromWho) + public async Task SendRequest(string userId, string fromWho = "Me") { Logger.Debug(() => $"Sending friend request to {userId} from {fromWho}"); - JObject json = new JObject(); - json["type"] = "friendrequest"; - json["message"] = $"{fromWho} wants to be your friend"; + + JObject json = new JObject() + { + { "type", "friendrequest" }, + { "message", $"{fromWho} wants to be your friend" } + }; Logger.Debug(() => $"Prepared JSON to post: {json}"); @@ -46,50 +39,48 @@ public async Task SendRequest(string userId, string fromWh content.Headers.ContentType = new MediaTypeHeaderValue("application/json"); HttpResponseMessage response = await Global.HttpClient.PostAsync($"user/{userId}/notification?apiKey={Global.ApiKey}", content); - - - NotificationResponse res = null; - if (response.IsSuccessStatusCode) - { - var receivedJson = await response.Content.ReadAsStringAsync(); - Logger.Debug(() => $"JSON received: {receivedJson}"); - res = JsonConvert.DeserializeObject(receivedJson); - } - - return res; + return await Utils.ParseResponse(response); } - // TODO: proper return type, need to document - public async Task DeleteFriend(string userId) + public async Task DeleteFriend(string userId) { HttpResponseMessage response = await Global.HttpClient.DeleteAsync($"auth/user/friends/{userId}?apiKey={Global.ApiKey}"); - string res = ""; + return Utils.ParseResponse(response) != null; + } - if (response.IsSuccessStatusCode) - { - var json = await response.Content.ReadAsStringAsync(); - Logger.Debug(() => $"JSON received: {json}"); - res = json; - } + public async Task AcceptFriend(string userId) + { + HttpResponseMessage response = await Global.HttpClient.PutAsync($"auth/user/notifications/{userId}/accept?apiKey={Global.ApiKey}", new StringContent("")); - return res; + return Utils.ParseResponse(response) != null; } - // TODO: proper return type, need to document - public async Task AcceptFriend(string userId) + public async Task SendInvite(string userId, string worldInstanceId = "", string worldName = "my world", string hiddenMessage = "") { - HttpResponseMessage response = await Global.HttpClient.PutAsync($"auth/user/notifications/{userId}/accept?apiKey={Global.ApiKey}", new StringContent("")); + JObject json = new JObject() { + { "type", "invite" }, + { "message", hiddenMessage }, + { "details", new JObject() { + { "worldId", worldInstanceId }, + { "worldName", worldName } + }}, + }; - /*string res = ""; + Logger.Debug(() => $"Prepared JSON to post: {json}"); - if (response.IsSuccessStatusCode) - { - res = await response.Content.ReadAsStringAsync(); - } + StringContent content = new StringContent(json.ToString(), Encoding.UTF8); - return res;*/ + content.Headers.ContentType = new MediaTypeHeaderValue("application/json"); + + Logger.Debug(() => $"Prepared StringContent to post: {content}"); + + HttpResponseMessage response = await Global.HttpClient.PostAsync($"user/{userId}/notification?apiKey={Global.ApiKey}", content); + + return await Utils.ParseResponse(response); } + + public async Task SendMessage(string userId, string message, string hiddenMessage = "") => await SendInvite(userId, worldName: message, hiddenMessage: hiddenMessage); } } diff --git a/VRChatApi/VRChatApi/Endpoints/ModerationsApi.cs b/VRChatApi/VRChatApi/Endpoints/ModerationsApi.cs index a18d5d7..f41f1eb 100644 --- a/VRChatApi/VRChatApi/Endpoints/ModerationsApi.cs +++ b/VRChatApi/VRChatApi/Endpoints/ModerationsApi.cs @@ -1,10 +1,9 @@ -using System; +using Newtonsoft.Json.Linq; using System.Collections.Generic; -using System.Linq; using System.Net.Http; +using System.Net.Http.Headers; using System.Text; using System.Threading.Tasks; -using Newtonsoft.Json; using VRChatApi.Classes; using VRChatApi.Logging; @@ -17,35 +16,45 @@ public class ModerationsApi public async Task> GetPlayerModerations() { Logger.Trace(() => "Get list of moderations made by current user"); - HttpResponseMessage response = await Global.HttpClient.GetAsync("auth/user/playermoderations"); - - List res = null; - if (response.IsSuccessStatusCode) - { - var json = await response.Content.ReadAsStringAsync(); - Logger.Debug(() => $"JSON received: {json}"); - res = JsonConvert.DeserializeObject>(json); - } + HttpResponseMessage response = await Global.HttpClient.GetAsync("auth/user/playermoderations"); - return res; + return await Utils.ParseResponse>(response); } public async Task> GetPlayerModerated() { Logger.Trace(() => "Get list of moderations made against current user"); + HttpResponseMessage response = await Global.HttpClient.GetAsync("auth/user/playermoderated"); - List res = null; + return await Utils.ParseResponse>(response); + } - if (response.IsSuccessStatusCode) - { - var json = await response.Content.ReadAsStringAsync(); - Logger.Debug(() => $"JSON received: {json}"); - res = JsonConvert.DeserializeObject>(json); - } - return res; + public async Task BlockUser(string userId) + { + JObject json = new JObject() { + { "blocked", userId } + }; + Logger.Debug(() => $"Prepared JSON to post: {json}"); + StringContent content = new StringContent(json.ToString(), Encoding.UTF8); + content.Headers.ContentType = new MediaTypeHeaderValue("application/json"); + HttpResponseMessage response = await Global.HttpClient.PostAsync($"auth/user/blocks?apiKey={Global.ApiKey}", content); + return await Utils.ParseResponse(response); + } + + public async Task UnblockUser(string userId) + { + JObject json = new JObject() { + { "moderated", userId }, + { "type", "block" } + }; + Logger.Debug(() => $"Prepared JSON to put: {json}"); + StringContent content = new StringContent(json.ToString(), Encoding.UTF8); + content.Headers.ContentType = new MediaTypeHeaderValue("application/json"); + HttpResponseMessage response = await Global.HttpClient.PutAsync($"auth/user/unplayermoderate?apiKey={Global.ApiKey}", content); + return await Utils.ParseResponse(response); } } } diff --git a/VRChatApi/VRChatApi/Endpoints/NotificationsAPI.cs b/VRChatApi/VRChatApi/Endpoints/NotificationsAPI.cs new file mode 100644 index 0000000..d7c72ce --- /dev/null +++ b/VRChatApi/VRChatApi/Endpoints/NotificationsAPI.cs @@ -0,0 +1,32 @@ +using Newtonsoft.Json.Linq; +using System.Collections.Generic; +using System.Net.Http; +using System.Net.Http.Headers; +using System.Text; +using System.Threading.Tasks; +using Newtonsoft.Json; +using VRChatApi.Classes; +using VRChatApi.Logging; +using System; + +namespace VRChatApi.Endpoints +{ + public class NotificationsAPI + { + private static readonly ILog Logger = LogProvider.GetCurrentClassLogger(); + public async Task> GetAll(string type = "all", bool sent = false, DateTime? after = null) + { + var url = $"auth/user/notifications?apiKey={Global.ApiKey}&type={type}&sent={sent}"; + if (after != null) url += $"&after={after}"; + HttpResponseMessage response = await Global.HttpClient.GetAsync(url); + List res = null; + if (response.IsSuccessStatusCode) + { + var receivedJson = await response.Content.ReadAsStringAsync(); + Console.WriteLine($"JSON received: {receivedJson}"); + res = JsonConvert.DeserializeObject>(receivedJson); + } + return res; + } + } +} diff --git a/VRChatApi/VRChatApi/Endpoints/RemoteConfig.cs b/VRChatApi/VRChatApi/Endpoints/RemoteConfig.cs index 252ecc7..ff7bfa7 100644 --- a/VRChatApi/VRChatApi/Endpoints/RemoteConfig.cs +++ b/VRChatApi/VRChatApi/Endpoints/RemoteConfig.cs @@ -1,7 +1,5 @@ -using System; -using System.Net.Http; +using System.Net.Http; using System.Threading.Tasks; -using Newtonsoft.Json; using VRChatApi.Classes; using VRChatApi.Logging; @@ -14,18 +12,14 @@ public class RemoteConfig public async Task Get() { Logger.Trace(() => "Getting remote config"); + HttpResponseMessage response = await Global.HttpClient.GetAsync("config"); - ConfigResponse res = null; + ConfigResponse res = await Utils.ParseResponse(response); + + Global.ApiKey = res.clientApiKey; - if (response.IsSuccessStatusCode) - { - var json = await response.Content.ReadAsStringAsync(); - Logger.Debug(() => $"JSON received: {json}"); - res = JsonConvert.DeserializeObject(json); - Global.ApiKey = res.clientApiKey; - Logger.Info(() => $"API key has been set to: {Global.ApiKey}"); - } + Logger.Info(() => $"API key has been set to: {res.clientApiKey}"); return res; } diff --git a/VRChatApi/VRChatApi/Endpoints/UserApi.cs b/VRChatApi/VRChatApi/Endpoints/UserApi.cs index 5fd15d3..11c010f 100644 --- a/VRChatApi/VRChatApi/Endpoints/UserApi.cs +++ b/VRChatApi/VRChatApi/Endpoints/UserApi.cs @@ -21,6 +21,7 @@ public class UserApi public UserApi(string username, string password) { Logger.Trace(() => $"Entering {nameof(UserApi)} constructor with username: {username}"); + Username = username; Password = password; } @@ -28,35 +29,25 @@ public UserApi(string username, string password) public async Task Login() { Logger.Trace(() => "Getting current user details"); - HttpResponseMessage response = await Global.HttpClient.GetAsync($"auth/user?apiKey={Global.ApiKey}"); - - UserResponse res = null; - if (response.IsSuccessStatusCode) - { - string json = await response.Content.ReadAsStringAsync(); - Logger.Debug(() => $"JSON received: {json}"); - res = JsonConvert.DeserializeObject(json); - } + HttpResponseMessage response = await Global.HttpClient.GetAsync($"auth/user?apiKey={Global.ApiKey}"); - return res; + return await Utils.ParseResponse(response); } public async Task Register(string username, string password, string email, string birthday = null, string acceptedTOSVersion = null) { Logger.Debug(() => $"Registering new user with {nameof(username)} = {username}, {nameof(email)} = {email}, {nameof(birthday)} = {birthday}, {nameof(acceptedTOSVersion)} = {acceptedTOSVersion}"); - JObject json = new JObject(); - json["username"] = username; - json["password"] = password; - if (email != null) - json["email"] = email; - - if (birthday != null ) - json["birthday"] = birthday; + JObject json = new JObject() + { + { "username", username }, + { "password", password } + }; - if (acceptedTOSVersion != null) - json["acceptedTOSVersion"] = acceptedTOSVersion; + json.AddIfNotNull("email", email); + json.AddIfNotNull("birthday", birthday); + json.AddIfNotNull("acceptedTOSVersion", acceptedTOSVersion); Logger.Debug(() => $"Prepared JSON to post: {json}"); @@ -66,51 +57,38 @@ public async Task Register(string username, string password, strin HttpResponseMessage response = await Global.HttpClient.PostAsync($"auth/register?apiKey={Global.ApiKey}", content); - UserResponse res = null; + return await Utils.ParseResponse(response); + } - if (response.IsSuccessStatusCode) - { - var receivedJson = await response.Content.ReadAsStringAsync(); - Logger.Debug(() => $"JSON received: {receivedJson}"); - res = JsonConvert.DeserializeObject(receivedJson); - } + public async Task> Search(string pattern, int limit = 100, int offset = 0) + { + Logger.Debug(() => $"Searching user info with pattern: {pattern}"); - return res; + HttpResponseMessage response = await Global.HttpClient.GetAsync($"users/?apiKey={Global.ApiKey}&n={limit}&offset={offset}&search={pattern}"); + + return await Utils.ParseResponse>(response); } public async Task GetById(string userId) { Logger.Debug(() => $"Getting user info with ID: {userId}"); - HttpResponseMessage response = await Global.HttpClient.GetAsync($"users/{userId}?apiKey={Global.ApiKey}"); - UserBriefResponse res = null; - - if (response.IsSuccessStatusCode) - { - string json = await response.Content.ReadAsStringAsync(); - Logger.Debug(() => $"JSON received: {json}"); - res = JsonConvert.DeserializeObject(json); - } + HttpResponseMessage response = await Global.HttpClient.GetAsync($"users/{userId}?apiKey={Global.ApiKey}"); - return res; + return await Utils.ParseResponse(response); } - public async Task UpdateInfo(string userId, string email = null, string birthday = null, string acceptedTOSVersion = null, List tags = null) + public async Task UpdateInfo(string userId, string email = null, string birthday = null, string acceptedTOSVersion = null, List tags = null, string status = null, string statusDescription = null) { - Logger.Debug(() => $"Updating user info for {nameof(userId)} = {userId} with {nameof(email)} = {email}, {nameof(birthday)} = {birthday}, {nameof(acceptedTOSVersion)} = {acceptedTOSVersion}, {nameof(tags)} = {tags}"); - JObject json = new JObject(); - - if (email != null) - json["email"] = email; - - if (birthday != null) - json["birthday"] = birthday; + Logger.Debug(() => $"Updating user info for {nameof(userId)} = {userId} with {nameof(email)} = {email}, {nameof(birthday)} = {birthday}, {nameof(acceptedTOSVersion)} = {acceptedTOSVersion}, {nameof(tags)} = {tags}, {nameof(status)} = {status}, {nameof(statusDescription)} = {statusDescription}"); - if (acceptedTOSVersion != null) - json["acceptedTOSVersion"] = acceptedTOSVersion; - - if (tags != null) - json["tags"] = JToken.FromObject(tags); + JObject json = new JObject(); + json.AddIfNotNull("email", email); + json.AddIfNotNull("birthday", birthday); + json.AddIfNotNull("acceptedTOSVersion", acceptedTOSVersion); + if (tags != null) json.Add("tags", JToken.FromObject(tags)); + json.AddIfNotNull("status", status); + json.AddIfNotNull("statusDescription", statusDescription); Logger.Debug(() => $"Prepared JSON to put: {json}"); @@ -120,16 +98,7 @@ public async Task UpdateInfo(string userId, string email = null, s HttpResponseMessage response = await Global.HttpClient.PutAsync($"users/{userId}?apiKey={Global.ApiKey}", content); - UserResponse res = null; - - if (response.IsSuccessStatusCode) - { - var receivedJson = await response.Content.ReadAsStringAsync(); - Logger.Debug(() => $"JSON received: {receivedJson}"); - res = JsonConvert.DeserializeObject(receivedJson); - } - - return res; + return await Utils.ParseResponse(response); } } } diff --git a/VRChatApi/VRChatApi/Endpoints/WorldAPI.cs b/VRChatApi/VRChatApi/Endpoints/WorldAPI.cs index 5de98cc..ccd059d 100644 --- a/VRChatApi/VRChatApi/Endpoints/WorldAPI.cs +++ b/VRChatApi/VRChatApi/Endpoints/WorldAPI.cs @@ -23,21 +23,14 @@ public async Task Get(string id) HttpResponseMessage response = await Global.HttpClient.GetAsync($"worlds/{id}?apiKey={Global.ApiKey}"); - WorldResponse res = null; + var res = await Utils.ParseResponse(response); - if (response.IsSuccessStatusCode) + // parse instances + res.instances = res._instances.Select(data => new WorldInstance() { - string json = await response.Content.ReadAsStringAsync(); - Logger.Debug(() => $"JSON received: {json}"); - res = JsonConvert.DeserializeObject(json); - - // Parse instances. - res.instances = res._instances.Select(data => new WorldInstance() - { - id = (string)data[0], - occupants = (int)data[1] - }).ToList(); - } + id = (string)data[0], + occupants = (int)data[1] + }).ToList(); return res; } @@ -48,7 +41,9 @@ public async Task> Search(WorldGroups? endpoint = null, ReleaseStatus? releaseStatus = null, int offset = 0, int count = 20) { Logger.Debug(() => "Getting world list"); + var param = new StringBuilder(); + param.Append($"&n={count}"); param.Append($"&offset={offset}"); @@ -73,19 +68,37 @@ public async Task> Search(WorldGroups? endpoint = null, } if (user.HasValue) + { param.Append($"&user={user.Value.ToString().ToLowerInvariant()}"); + } + if (!string.IsNullOrEmpty(userId)) + { param.Append($"&userId={userId}"); + } + if (!string.IsNullOrEmpty(keyword)) + { param.Append($"&search={keyword}"); + } + if (!string.IsNullOrEmpty(tags)) + { param.Append($"&tag={tags}"); + } + if (!string.IsNullOrEmpty(excludeTags)) + { param.Append($"¬ag={excludeTags}"); + } + if (releaseStatus.HasValue) + { param.Append($"&releaseStatus={releaseStatus.Value.ToString().ToLowerInvariant()}"); + } string baseUrl = "worlds"; + if (endpoint.HasValue) { switch (endpoint.Value) @@ -104,38 +117,22 @@ public async Task> Search(WorldGroups? endpoint = null, HttpResponseMessage response = await Global.HttpClient.GetAsync($"{baseUrl}?apiKey={Global.ApiKey}{param.ToString()}"); - List res = null; - - if (response.IsSuccessStatusCode) - { - string json = await response.Content.ReadAsStringAsync(); - Logger.Debug(() => $"JSON received: {json}"); - res = JsonConvert.DeserializeObject>(json); - } - - return res; + return await Utils.ParseResponse>(response); } public async Task GetMetadata(string id) { Logger.Debug(() => $"Getting world metadata with ID: {id}"); - HttpResponseMessage response = await Global.HttpClient.GetAsync($"worlds/{id}/metadata?apiKey={Global.ApiKey}"); - - WorldMetadataResponse res = null; - if (response.IsSuccessStatusCode) - { - string json = await response.Content.ReadAsStringAsync(); - Logger.Debug(() => $"JSON received: {json}"); - res = JsonConvert.DeserializeObject(json); - } + HttpResponseMessage response = await Global.HttpClient.GetAsync($"worlds/{id}/metadata?apiKey={Global.ApiKey}"); - return res; + return await Utils.ParseResponse(response); } public async Task GetInstance(string worldId, string instanceId) { Logger.Debug(() => $"Getting world instance with world ID: {worldId} and instance ID {instanceId}"); + HttpResponseMessage response = await Global.HttpClient.GetAsync($"worlds/{worldId}/{instanceId}?apiKey={Global.ApiKey}"); WorldInstanceResponse res = null; @@ -157,10 +154,12 @@ public async Task GetInstance(string worldId, string inst users = (json["users"] is JArray) ? json["users"].Select(tk => tk.ToObject()).ToList() : null, hidden = (json["hidden"] == null || json["hidden"].Type == JTokenType.Null) ? null : json["hidden"].ToString(), - nonce = (json["nonce"] == null) ? null : json["nonce"].ToString(), + nonce = json["nonce"]?.ToString(), }; } + response.Dispose(); + return res; } } diff --git a/VRChatApi/VRChatApi/Properties/AssemblyInfo.cs b/VRChatApi/VRChatApi/Properties/AssemblyInfo.cs new file mode 100644 index 0000000..5f28270 --- /dev/null +++ b/VRChatApi/VRChatApi/Properties/AssemblyInfo.cs @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/VRChatApi/VRChatApi/Utils.cs b/VRChatApi/VRChatApi/Utils.cs new file mode 100644 index 0000000..50fa39d --- /dev/null +++ b/VRChatApi/VRChatApi/Utils.cs @@ -0,0 +1,79 @@ +using Newtonsoft.Json; +using Newtonsoft.Json.Linq; +using System; +using System.Net.Http; +using System.Runtime.CompilerServices; +using System.Threading.Tasks; +using VRChatApi.Logging; +using VRChatApi.Classes; +using System.Reflection; +using System.ComponentModel; + +namespace VRChatApi +{ + static class Utils + { + public static void AddIfNotNull(this JObject jObject, string key, string value) + { + if (!string.IsNullOrEmpty(value)) + { + jObject[key] = value; + } + } + + public static void AddIfNotNull(this JObject jObject, string key, JToken value) + { + if (value.HasValues) + { + jObject[key] = value; + } + } + + private static readonly ILog Logger = LogProvider.GetCurrentClassLogger(); + + public static async Task ParseResponse(HttpResponseMessage responseMessage) where T : class + { + T res = null; + /*switch (T.GetType()) + { + case typeof(UserBriefResponse): + UserBriefResponse res = null; + break; + default: + break; + } + res.Raw = responseMessage;*/ + if (responseMessage.IsSuccessStatusCode) + { + var receivedJson = await responseMessage.Content.ReadAsStringAsync(); + + Logger.Debug(() => $"JSON received: {receivedJson}"); + + res = JsonConvert.DeserializeObject(receivedJson); + + } + + responseMessage.Dispose(); + + return res; + } + } + static class Extensions + { + public static string GetDescription(this Enum value) + { + Type type = value.GetType(); + string name = Enum.GetName(type, value); + if (name != null) { + FieldInfo field = type.GetField(name); + if (field != null) { + DescriptionAttribute attr = Attribute.GetCustomAttribute(field, typeof(DescriptionAttribute)) as DescriptionAttribute; + if (attr != null) { + return attr.Description; + } + } + } + return null; + } + } +} diff --git a/VRChatApi/VRChatApi/VRChatApi.cs b/VRChatApi/VRChatApi/VRChatApi.cs index 9819c4e..d6b8283 100644 --- a/VRChatApi/VRChatApi/VRChatApi.cs +++ b/VRChatApi/VRChatApi/VRChatApi.cs @@ -16,6 +16,8 @@ public class VRChatApi public WorldApi WorldApi { get; set; } public ModerationsApi ModerationsApi { get; set; } public AvatarApi AvatarApi { get; set; } + public FavouriteApi FavouriteApi { get; set; } + public NotificationsAPI NotificationsAPI { get; set; } public VRChatApi(string username, string password) { @@ -29,6 +31,8 @@ public VRChatApi(string username, string password) WorldApi = new WorldApi(); ModerationsApi = new ModerationsApi(); AvatarApi = new AvatarApi(); + FavouriteApi = new FavouriteApi(); + NotificationsAPI = new NotificationsAPI(); // initialize http client // TODO: use the auth cookie @@ -43,12 +47,15 @@ public VRChatApi(string username, string password) string authEncoded = Convert.ToBase64String(Encoding.UTF8.GetBytes($"{UserApi.Username}:{UserApi.Password}")); var header = Global.HttpClient.DefaultRequestHeaders; + if (header.Contains("Authorization")) { Logger.Debug(() => "Removing existing Authorization header"); header.Remove("Authorization"); } + header.Add("Authorization", $"Basic {authEncoded}"); + Logger.Trace(() => $"Added new Authorization header"); } } diff --git a/VRChatApi/VRChatApi/VRChatApi.csproj b/VRChatApi/VRChatApi/VRChatApi.csproj index bdc0864..bd2532b 100644 --- a/VRChatApi/VRChatApi/VRChatApi.csproj +++ b/VRChatApi/VRChatApi/VRChatApi.csproj @@ -1,4 +1,4 @@ - + netstandard2.0 @@ -13,8 +13,9 @@ all runtime; build; native; contentfiles; analyzers - + + diff --git a/VRChatApi/VRChatApi/packages.config b/VRChatApi/VRChatApi/packages.config new file mode 100644 index 0000000..374f45c --- /dev/null +++ b/VRChatApi/VRChatApi/packages.config @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/renovate.json b/renovate.json new file mode 100644 index 0000000..39a2b6e --- /dev/null +++ b/renovate.json @@ -0,0 +1,6 @@ +{ + "$schema": "https://docs.renovatebot.com/renovate-schema.json", + "extends": [ + "config:base" + ] +}