diff --git a/.release-please-manifest.json b/.release-please-manifest.json index 6b7b74c..da59f99 100644 --- a/.release-please-manifest.json +++ b/.release-please-manifest.json @@ -1,3 +1,3 @@ { - ".": "0.3.0" + ".": "0.4.0" } \ No newline at end of file diff --git a/.stats.yml b/.stats.yml index 2b609bf..cf3227f 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ -configured_endpoints: 117 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/xquik%2Fx-twitter-scraper-d40c57a05527faf060d21c0e013729f371d88017b10680cea7c8fd6780ffaef5.yml -openapi_spec_hash: 597ebc460cf86740b9f6f7c95478dece -config_hash: 8521caa746275ca99eb3ba7bb3d6d90f +configured_endpoints: 110 +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/xquik%2Fx-twitter-scraper-4a12c672870ee7282ad1d00f262e20fb360a8296b64a774628d1d0252e12694a.yml +openapi_spec_hash: 2e298ff704f550c80c2d07d9adadba6d +config_hash: 320a9cb2f1293d1a7b73c63ab5865af5 diff --git a/CHANGELOG.md b/CHANGELOG.md index 8e37b30..8517d88 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,27 @@ # Changelog +## 0.4.0 (2026-04-22) + +Full Changelog: [v0.3.0...v0.4.0](https://github.com/Xquik-dev/x-twitter-scraper-csharp/compare/v0.3.0...v0.4.0) + +### Features + +* **api:** api update ([739e7ff](https://github.com/Xquik-dev/x-twitter-scraper-csharp/commit/739e7ff053b9f231bd7f4a76803a2631439d3947)) +* **api:** api update ([8d82368](https://github.com/Xquik-dev/x-twitter-scraper-csharp/commit/8d823689cec9b413e618c9bfdc5a7d4b837b21b4)) +* **api:** api update ([3a5a9e7](https://github.com/Xquik-dev/x-twitter-scraper-csharp/commit/3a5a9e7d951ad61707709a91bffee20594eb58e9)) +* **api:** api update ([5000bc9](https://github.com/Xquik-dev/x-twitter-scraper-csharp/commit/5000bc965aa7184aaabaeec001679bd7b37f5b88)) + + +### Bug Fixes + +* **tests:** round-trip urls correctly ([1773360](https://github.com/Xquik-dev/x-twitter-scraper-csharp/commit/1773360afd7751305c2fbad2350919bcc2e14e5e)) + + +### Chores + +* sync OpenAPI spec ([9ad82a2](https://github.com/Xquik-dev/x-twitter-scraper-csharp/commit/9ad82a28788a0fa5853bc28666c04d8bf35220b9)) +* wire production_repo for all targets ([3eb0d89](https://github.com/Xquik-dev/x-twitter-scraper-csharp/commit/3eb0d897f16b37a69272cd99292c95243c27515b)) + ## 0.3.0 (2026-04-08) Full Changelog: [v0.2.0...v0.3.0](https://github.com/Xquik-dev/x-twitter-scraper-csharp/compare/v0.2.0...v0.3.0) diff --git a/README.md b/README.md index 7fc38bd..2f00e2a 100644 --- a/README.md +++ b/README.md @@ -56,11 +56,7 @@ Or manually: ```csharp using XTwitterScraper; -XTwitterScraperClient client = new() -{ - ApiKey = "My API Key", - BearerToken = "My Bearer Token", -}; +XTwitterScraperClient client = new() { ApiKey = "My API Key" }; ``` Or using a combination of the two approaches. @@ -321,46 +317,6 @@ var parameters = TweetSearchParams.FromRawUnchecked ); ``` -### Nested Parameters - -Undocumented properties, or undocumented values of documented properties, on nested parameters can be set similarly, using a dictionary in the constructor of the nested parameter. - -```csharp -using System.Collections.Generic; -using System.Text.Json; -using XTwitterScraper.Models.Integrations; - -IntegrationCreateParams parameters = new() -{ - Config = new - ( - new Dictionary - { - { "custom_nested_param", JsonSerializer.SerializeToElement(42) } - } - ) -}; -``` - -Required properties on the nested parameter can also be changed or omitted using the `FromRawUnchecked` method: - -```csharp -using System.Collections.Generic; -using System.Text.Json; -using XTwitterScraper.Models.Integrations; - -IntegrationCreateParams parameters = new() -{ - Config = Config.FromRawUnchecked - ( - new Dictionary - { - { "required_property", JsonSerializer.SerializeToElement("custom value") } - } - ) -}; -``` - ### Response properties To access undocumented response properties, the `RawData` property can be used: diff --git a/src/XTwitterScraper.Tests/Models/Account/AccountRetrieveResponseTest.cs b/src/XTwitterScraper.Tests/Models/Account/AccountRetrieveResponseTest.cs index 78e7fba..2ab8b3c 100644 --- a/src/XTwitterScraper.Tests/Models/Account/AccountRetrieveResponseTest.cs +++ b/src/XTwitterScraper.Tests/Models/Account/AccountRetrieveResponseTest.cs @@ -1,4 +1,3 @@ -using System; using System.Text.Json; using XTwitterScraper.Core; using XTwitterScraper.Exceptions; @@ -16,28 +15,30 @@ public void FieldRoundtrip_Works() MonitorsAllowed = 10, MonitorsUsed = 3, Plan = Plan.Active, - CurrentPeriod = new() + CreditInfo = new() { - End = DateTimeOffset.Parse("2025-02-01T00:00:00Z"), - Start = DateTimeOffset.Parse("2025-01-01T00:00:00Z"), - UsagePercent = 42.5, + AutoTopupEnabled = false, + Balance = 50000, + LifetimePurchased = 140000, + LifetimeUsed = 90000, }, }; long expectedMonitorsAllowed = 10; long expectedMonitorsUsed = 3; ApiEnum expectedPlan = Plan.Active; - CurrentPeriod expectedCurrentPeriod = new() + CreditInfo expectedCreditInfo = new() { - End = DateTimeOffset.Parse("2025-02-01T00:00:00Z"), - Start = DateTimeOffset.Parse("2025-01-01T00:00:00Z"), - UsagePercent = 42.5, + AutoTopupEnabled = false, + Balance = 50000, + LifetimePurchased = 140000, + LifetimeUsed = 90000, }; Assert.Equal(expectedMonitorsAllowed, model.MonitorsAllowed); Assert.Equal(expectedMonitorsUsed, model.MonitorsUsed); Assert.Equal(expectedPlan, model.Plan); - Assert.Equal(expectedCurrentPeriod, model.CurrentPeriod); + Assert.Equal(expectedCreditInfo, model.CreditInfo); } [Fact] @@ -48,11 +49,12 @@ public void SerializationRoundtrip_Works() MonitorsAllowed = 10, MonitorsUsed = 3, Plan = Plan.Active, - CurrentPeriod = new() + CreditInfo = new() { - End = DateTimeOffset.Parse("2025-02-01T00:00:00Z"), - Start = DateTimeOffset.Parse("2025-01-01T00:00:00Z"), - UsagePercent = 42.5, + AutoTopupEnabled = false, + Balance = 50000, + LifetimePurchased = 140000, + LifetimeUsed = 90000, }, }; @@ -73,11 +75,12 @@ public void FieldRoundtripThroughSerialization_Works() MonitorsAllowed = 10, MonitorsUsed = 3, Plan = Plan.Active, - CurrentPeriod = new() + CreditInfo = new() { - End = DateTimeOffset.Parse("2025-02-01T00:00:00Z"), - Start = DateTimeOffset.Parse("2025-01-01T00:00:00Z"), - UsagePercent = 42.5, + AutoTopupEnabled = false, + Balance = 50000, + LifetimePurchased = 140000, + LifetimeUsed = 90000, }, }; @@ -91,17 +94,18 @@ public void FieldRoundtripThroughSerialization_Works() long expectedMonitorsAllowed = 10; long expectedMonitorsUsed = 3; ApiEnum expectedPlan = Plan.Active; - CurrentPeriod expectedCurrentPeriod = new() + CreditInfo expectedCreditInfo = new() { - End = DateTimeOffset.Parse("2025-02-01T00:00:00Z"), - Start = DateTimeOffset.Parse("2025-01-01T00:00:00Z"), - UsagePercent = 42.5, + AutoTopupEnabled = false, + Balance = 50000, + LifetimePurchased = 140000, + LifetimeUsed = 90000, }; Assert.Equal(expectedMonitorsAllowed, deserialized.MonitorsAllowed); Assert.Equal(expectedMonitorsUsed, deserialized.MonitorsUsed); Assert.Equal(expectedPlan, deserialized.Plan); - Assert.Equal(expectedCurrentPeriod, deserialized.CurrentPeriod); + Assert.Equal(expectedCreditInfo, deserialized.CreditInfo); } [Fact] @@ -112,11 +116,12 @@ public void Validation_Works() MonitorsAllowed = 10, MonitorsUsed = 3, Plan = Plan.Active, - CurrentPeriod = new() + CreditInfo = new() { - End = DateTimeOffset.Parse("2025-02-01T00:00:00Z"), - Start = DateTimeOffset.Parse("2025-01-01T00:00:00Z"), - UsagePercent = 42.5, + AutoTopupEnabled = false, + Balance = 50000, + LifetimePurchased = 140000, + LifetimeUsed = 90000, }, }; @@ -133,8 +138,8 @@ public void OptionalNonNullablePropertiesUnsetAreNotSet_Works() Plan = Plan.Active, }; - Assert.Null(model.CurrentPeriod); - Assert.False(model.RawData.ContainsKey("currentPeriod")); + Assert.Null(model.CreditInfo); + Assert.False(model.RawData.ContainsKey("creditInfo")); } [Fact] @@ -160,11 +165,11 @@ public void OptionalNonNullablePropertiesSetToNullAreNotSet_Works() Plan = Plan.Active, // Null should be interpreted as omitted for these properties - CurrentPeriod = null, + CreditInfo = null, }; - Assert.Null(model.CurrentPeriod); - Assert.False(model.RawData.ContainsKey("currentPeriod")); + Assert.Null(model.CreditInfo); + Assert.False(model.RawData.ContainsKey("creditInfo")); } [Fact] @@ -177,7 +182,7 @@ public void OptionalNonNullablePropertiesSetToNullValidation_Works() Plan = Plan.Active, // Null should be interpreted as omitted for these properties - CurrentPeriod = null, + CreditInfo = null, }; model.Validate(); @@ -191,11 +196,12 @@ public void CopyConstructor_Works() MonitorsAllowed = 10, MonitorsUsed = 3, Plan = Plan.Active, - CurrentPeriod = new() + CreditInfo = new() { - End = DateTimeOffset.Parse("2025-02-01T00:00:00Z"), - Start = DateTimeOffset.Parse("2025-01-01T00:00:00Z"), - UsagePercent = 42.5, + AutoTopupEnabled = false, + Balance = 50000, + LifetimePurchased = 140000, + LifetimeUsed = 90000, }, }; @@ -263,39 +269,43 @@ public void InvalidEnumSerializationRoundtrip_Works() } } -public class CurrentPeriodTest : TestBase +public class CreditInfoTest : TestBase { [Fact] public void FieldRoundtrip_Works() { - var model = new CurrentPeriod + var model = new CreditInfo { - End = DateTimeOffset.Parse("2025-02-01T00:00:00Z"), - Start = DateTimeOffset.Parse("2025-01-01T00:00:00Z"), - UsagePercent = 42.5, + AutoTopupEnabled = false, + Balance = 50000, + LifetimePurchased = 140000, + LifetimeUsed = 90000, }; - DateTimeOffset expectedEnd = DateTimeOffset.Parse("2025-02-01T00:00:00Z"); - DateTimeOffset expectedStart = DateTimeOffset.Parse("2025-01-01T00:00:00Z"); - double expectedUsagePercent = 42.5; + bool expectedAutoTopupEnabled = false; + long expectedBalance = 50000; + long expectedLifetimePurchased = 140000; + long expectedLifetimeUsed = 90000; - Assert.Equal(expectedEnd, model.End); - Assert.Equal(expectedStart, model.Start); - Assert.Equal(expectedUsagePercent, model.UsagePercent); + Assert.Equal(expectedAutoTopupEnabled, model.AutoTopupEnabled); + Assert.Equal(expectedBalance, model.Balance); + Assert.Equal(expectedLifetimePurchased, model.LifetimePurchased); + Assert.Equal(expectedLifetimeUsed, model.LifetimeUsed); } [Fact] public void SerializationRoundtrip_Works() { - var model = new CurrentPeriod + var model = new CreditInfo { - End = DateTimeOffset.Parse("2025-02-01T00:00:00Z"), - Start = DateTimeOffset.Parse("2025-01-01T00:00:00Z"), - UsagePercent = 42.5, + AutoTopupEnabled = false, + Balance = 50000, + LifetimePurchased = 140000, + LifetimeUsed = 90000, }; string json = JsonSerializer.Serialize(model, ModelBase.SerializerOptions); - var deserialized = JsonSerializer.Deserialize( + var deserialized = JsonSerializer.Deserialize( json, ModelBase.SerializerOptions ); @@ -306,37 +316,41 @@ public void SerializationRoundtrip_Works() [Fact] public void FieldRoundtripThroughSerialization_Works() { - var model = new CurrentPeriod + var model = new CreditInfo { - End = DateTimeOffset.Parse("2025-02-01T00:00:00Z"), - Start = DateTimeOffset.Parse("2025-01-01T00:00:00Z"), - UsagePercent = 42.5, + AutoTopupEnabled = false, + Balance = 50000, + LifetimePurchased = 140000, + LifetimeUsed = 90000, }; string element = JsonSerializer.Serialize(model, ModelBase.SerializerOptions); - var deserialized = JsonSerializer.Deserialize( + var deserialized = JsonSerializer.Deserialize( element, ModelBase.SerializerOptions ); Assert.NotNull(deserialized); - DateTimeOffset expectedEnd = DateTimeOffset.Parse("2025-02-01T00:00:00Z"); - DateTimeOffset expectedStart = DateTimeOffset.Parse("2025-01-01T00:00:00Z"); - double expectedUsagePercent = 42.5; + bool expectedAutoTopupEnabled = false; + long expectedBalance = 50000; + long expectedLifetimePurchased = 140000; + long expectedLifetimeUsed = 90000; - Assert.Equal(expectedEnd, deserialized.End); - Assert.Equal(expectedStart, deserialized.Start); - Assert.Equal(expectedUsagePercent, deserialized.UsagePercent); + Assert.Equal(expectedAutoTopupEnabled, deserialized.AutoTopupEnabled); + Assert.Equal(expectedBalance, deserialized.Balance); + Assert.Equal(expectedLifetimePurchased, deserialized.LifetimePurchased); + Assert.Equal(expectedLifetimeUsed, deserialized.LifetimeUsed); } [Fact] public void Validation_Works() { - var model = new CurrentPeriod + var model = new CreditInfo { - End = DateTimeOffset.Parse("2025-02-01T00:00:00Z"), - Start = DateTimeOffset.Parse("2025-01-01T00:00:00Z"), - UsagePercent = 42.5, + AutoTopupEnabled = false, + Balance = 50000, + LifetimePurchased = 140000, + LifetimeUsed = 90000, }; model.Validate(); @@ -345,14 +359,15 @@ public void Validation_Works() [Fact] public void CopyConstructor_Works() { - var model = new CurrentPeriod + var model = new CreditInfo { - End = DateTimeOffset.Parse("2025-02-01T00:00:00Z"), - Start = DateTimeOffset.Parse("2025-01-01T00:00:00Z"), - UsagePercent = 42.5, + AutoTopupEnabled = false, + Balance = 50000, + LifetimePurchased = 140000, + LifetimeUsed = 90000, }; - CurrentPeriod copied = new(model); + CreditInfo copied = new(model); Assert.Equal(model, copied); } diff --git a/src/XTwitterScraper.Tests/Models/Account/AccountSetXUsernameParamsTest.cs b/src/XTwitterScraper.Tests/Models/Account/AccountSetXUsernameParamsTest.cs index 7fc063e..5089a34 100644 --- a/src/XTwitterScraper.Tests/Models/Account/AccountSetXUsernameParamsTest.cs +++ b/src/XTwitterScraper.Tests/Models/Account/AccountSetXUsernameParamsTest.cs @@ -20,9 +20,11 @@ public void Url_Works() { AccountSetXUsernameParams parameters = new() { Username = "elonmusk" }; - var url = parameters.Url(new() { ApiKey = "My API Key", BearerToken = "My Bearer Token" }); + var url = parameters.Url(new() { ApiKey = "My API Key" }); - Assert.Equal(new Uri("https://xquik.com/api/v1/account/x-identity"), url); + Assert.True( + TestBase.UrisEqual(new Uri("https://xquik.com/api/v1/account/x-identity"), url) + ); } [Fact] diff --git a/src/XTwitterScraper.Tests/Models/Account/AccountUpdateLocaleParamsTest.cs b/src/XTwitterScraper.Tests/Models/Account/AccountUpdateLocaleParamsTest.cs index 663d533..b3b331e 100644 --- a/src/XTwitterScraper.Tests/Models/Account/AccountUpdateLocaleParamsTest.cs +++ b/src/XTwitterScraper.Tests/Models/Account/AccountUpdateLocaleParamsTest.cs @@ -23,9 +23,9 @@ public void Url_Works() { AccountUpdateLocaleParams parameters = new() { Locale = Locale.En }; - var url = parameters.Url(new() { ApiKey = "My API Key", BearerToken = "My Bearer Token" }); + var url = parameters.Url(new() { ApiKey = "My API Key" }); - Assert.Equal(new Uri("https://xquik.com/api/v1/account"), url); + Assert.True(TestBase.UrisEqual(new Uri("https://xquik.com/api/v1/account"), url)); } [Fact] diff --git a/src/XTwitterScraper.Tests/Models/ApiKeys/ApiKeyCreateParamsTest.cs b/src/XTwitterScraper.Tests/Models/ApiKeys/ApiKeyCreateParamsTest.cs index 5709428..f445873 100644 --- a/src/XTwitterScraper.Tests/Models/ApiKeys/ApiKeyCreateParamsTest.cs +++ b/src/XTwitterScraper.Tests/Models/ApiKeys/ApiKeyCreateParamsTest.cs @@ -42,9 +42,9 @@ public void Url_Works() { ApiKeyCreateParams parameters = new(); - var url = parameters.Url(new() { ApiKey = "My API Key", BearerToken = "My Bearer Token" }); + var url = parameters.Url(new() { ApiKey = "My API Key" }); - Assert.Equal(new Uri("https://xquik.com/api/v1/api-keys"), url); + Assert.True(TestBase.UrisEqual(new Uri("https://xquik.com/api/v1/api-keys"), url)); } [Fact] diff --git a/src/XTwitterScraper.Tests/Models/ApiKeys/ApiKeyRevokeParamsTest.cs b/src/XTwitterScraper.Tests/Models/ApiKeys/ApiKeyRevokeParamsTest.cs index 998c809..d01f869 100644 --- a/src/XTwitterScraper.Tests/Models/ApiKeys/ApiKeyRevokeParamsTest.cs +++ b/src/XTwitterScraper.Tests/Models/ApiKeys/ApiKeyRevokeParamsTest.cs @@ -20,9 +20,9 @@ public void Url_Works() { ApiKeyRevokeParams parameters = new() { ID = "id" }; - var url = parameters.Url(new() { ApiKey = "My API Key", BearerToken = "My Bearer Token" }); + var url = parameters.Url(new() { ApiKey = "My API Key" }); - Assert.Equal(new Uri("https://xquik.com/api/v1/api-keys/id"), url); + Assert.True(TestBase.UrisEqual(new Uri("https://xquik.com/api/v1/api-keys/id"), url)); } [Fact] diff --git a/src/XTwitterScraper.Tests/Models/Compose/ComposeCreateParamsTest.cs b/src/XTwitterScraper.Tests/Models/Compose/ComposeCreateParamsTest.cs index 1206caa..6e3f23d 100644 --- a/src/XTwitterScraper.Tests/Models/Compose/ComposeCreateParamsTest.cs +++ b/src/XTwitterScraper.Tests/Models/Compose/ComposeCreateParamsTest.cs @@ -125,9 +125,9 @@ public void Url_Works() { ComposeCreateParams parameters = new() { Step = Step.Compose }; - var url = parameters.Url(new() { ApiKey = "My API Key", BearerToken = "My Bearer Token" }); + var url = parameters.Url(new() { ApiKey = "My API Key" }); - Assert.Equal(new Uri("https://xquik.com/api/v1/compose"), url); + Assert.True(TestBase.UrisEqual(new Uri("https://xquik.com/api/v1/compose"), url)); } [Fact] diff --git a/src/XTwitterScraper.Tests/Models/Credits/CreditTopupBalanceParamsTest.cs b/src/XTwitterScraper.Tests/Models/Credits/CreditTopupBalanceParamsTest.cs index d005298..533ff20 100644 --- a/src/XTwitterScraper.Tests/Models/Credits/CreditTopupBalanceParamsTest.cs +++ b/src/XTwitterScraper.Tests/Models/Credits/CreditTopupBalanceParamsTest.cs @@ -20,9 +20,9 @@ public void Url_Works() { CreditTopupBalanceParams parameters = new() { Amount = 10000 }; - var url = parameters.Url(new() { ApiKey = "My API Key", BearerToken = "My Bearer Token" }); + var url = parameters.Url(new() { ApiKey = "My API Key" }); - Assert.Equal(new Uri("https://xquik.com/api/v1/credits/topup"), url); + Assert.True(TestBase.UrisEqual(new Uri("https://xquik.com/api/v1/credits/topup"), url)); } [Fact] diff --git a/src/XTwitterScraper.Tests/Models/Drafts/DraftCreateParamsTest.cs b/src/XTwitterScraper.Tests/Models/Drafts/DraftCreateParamsTest.cs index 24d887b..efeab07 100644 --- a/src/XTwitterScraper.Tests/Models/Drafts/DraftCreateParamsTest.cs +++ b/src/XTwitterScraper.Tests/Models/Drafts/DraftCreateParamsTest.cs @@ -61,9 +61,9 @@ public void Url_Works() { DraftCreateParams parameters = new() { Text = "AI is the future of productivity" }; - var url = parameters.Url(new() { ApiKey = "My API Key", BearerToken = "My Bearer Token" }); + var url = parameters.Url(new() { ApiKey = "My API Key" }); - Assert.Equal(new Uri("https://xquik.com/api/v1/drafts"), url); + Assert.True(TestBase.UrisEqual(new Uri("https://xquik.com/api/v1/drafts"), url)); } [Fact] diff --git a/src/XTwitterScraper.Tests/Models/Drafts/DraftDeleteParamsTest.cs b/src/XTwitterScraper.Tests/Models/Drafts/DraftDeleteParamsTest.cs index ab28490..109dc04 100644 --- a/src/XTwitterScraper.Tests/Models/Drafts/DraftDeleteParamsTest.cs +++ b/src/XTwitterScraper.Tests/Models/Drafts/DraftDeleteParamsTest.cs @@ -20,9 +20,9 @@ public void Url_Works() { DraftDeleteParams parameters = new() { ID = "id" }; - var url = parameters.Url(new() { ApiKey = "My API Key", BearerToken = "My Bearer Token" }); + var url = parameters.Url(new() { ApiKey = "My API Key" }); - Assert.Equal(new Uri("https://xquik.com/api/v1/drafts/id"), url); + Assert.True(TestBase.UrisEqual(new Uri("https://xquik.com/api/v1/drafts/id"), url)); } [Fact] diff --git a/src/XTwitterScraper.Tests/Models/Drafts/DraftListParamsTest.cs b/src/XTwitterScraper.Tests/Models/Drafts/DraftListParamsTest.cs index 64b4203..1ab46aa 100644 --- a/src/XTwitterScraper.Tests/Models/Drafts/DraftListParamsTest.cs +++ b/src/XTwitterScraper.Tests/Models/Drafts/DraftListParamsTest.cs @@ -49,11 +49,13 @@ public void Url_Works() { DraftListParams parameters = new() { AfterCursor = "afterCursor", Limit = 1 }; - var url = parameters.Url(new() { ApiKey = "My API Key", BearerToken = "My Bearer Token" }); + var url = parameters.Url(new() { ApiKey = "My API Key" }); - Assert.Equal( - new Uri("https://xquik.com/api/v1/drafts?afterCursor=afterCursor&limit=1"), - url + Assert.True( + TestBase.UrisEqual( + new Uri("https://xquik.com/api/v1/drafts?afterCursor=afterCursor&limit=1"), + url + ) ); } diff --git a/src/XTwitterScraper.Tests/Models/Drafts/DraftRetrieveParamsTest.cs b/src/XTwitterScraper.Tests/Models/Drafts/DraftRetrieveParamsTest.cs index 8748778..cc54b1a 100644 --- a/src/XTwitterScraper.Tests/Models/Drafts/DraftRetrieveParamsTest.cs +++ b/src/XTwitterScraper.Tests/Models/Drafts/DraftRetrieveParamsTest.cs @@ -20,9 +20,9 @@ public void Url_Works() { DraftRetrieveParams parameters = new() { ID = "id" }; - var url = parameters.Url(new() { ApiKey = "My API Key", BearerToken = "My Bearer Token" }); + var url = parameters.Url(new() { ApiKey = "My API Key" }); - Assert.Equal(new Uri("https://xquik.com/api/v1/drafts/id"), url); + Assert.True(TestBase.UrisEqual(new Uri("https://xquik.com/api/v1/drafts/id"), url)); } [Fact] diff --git a/src/XTwitterScraper.Tests/Models/Draws/DrawExportParamsTest.cs b/src/XTwitterScraper.Tests/Models/Draws/DrawExportParamsTest.cs index 14ec725..5171470 100644 --- a/src/XTwitterScraper.Tests/Models/Draws/DrawExportParamsTest.cs +++ b/src/XTwitterScraper.Tests/Models/Draws/DrawExportParamsTest.cs @@ -66,11 +66,13 @@ public void Url_Works() Type = Draws::Type.Winners, }; - var url = parameters.Url(new() { ApiKey = "My API Key", BearerToken = "My Bearer Token" }); + var url = parameters.Url(new() { ApiKey = "My API Key" }); - Assert.Equal( - new Uri("https://xquik.com/api/v1/draws/id/export?format=csv&type=winners"), - url + Assert.True( + TestBase.UrisEqual( + new Uri("https://xquik.com/api/v1/draws/id/export?format=csv&type=winners"), + url + ) ); } diff --git a/src/XTwitterScraper.Tests/Models/Draws/DrawListParamsTest.cs b/src/XTwitterScraper.Tests/Models/Draws/DrawListParamsTest.cs index 7abc3e7..6ca89a3 100644 --- a/src/XTwitterScraper.Tests/Models/Draws/DrawListParamsTest.cs +++ b/src/XTwitterScraper.Tests/Models/Draws/DrawListParamsTest.cs @@ -49,9 +49,11 @@ public void Url_Works() { DrawListParams parameters = new() { After = "after", Limit = 1 }; - var url = parameters.Url(new() { ApiKey = "My API Key", BearerToken = "My Bearer Token" }); + var url = parameters.Url(new() { ApiKey = "My API Key" }); - Assert.Equal(new Uri("https://xquik.com/api/v1/draws?after=after&limit=1"), url); + Assert.True( + TestBase.UrisEqual(new Uri("https://xquik.com/api/v1/draws?after=after&limit=1"), url) + ); } [Fact] diff --git a/src/XTwitterScraper.Tests/Models/Draws/DrawRetrieveParamsTest.cs b/src/XTwitterScraper.Tests/Models/Draws/DrawRetrieveParamsTest.cs index 26e5726..aded488 100644 --- a/src/XTwitterScraper.Tests/Models/Draws/DrawRetrieveParamsTest.cs +++ b/src/XTwitterScraper.Tests/Models/Draws/DrawRetrieveParamsTest.cs @@ -20,9 +20,9 @@ public void Url_Works() { DrawRetrieveParams parameters = new() { ID = "id" }; - var url = parameters.Url(new() { ApiKey = "My API Key", BearerToken = "My Bearer Token" }); + var url = parameters.Url(new() { ApiKey = "My API Key" }); - Assert.Equal(new Uri("https://xquik.com/api/v1/draws/id"), url); + Assert.True(TestBase.UrisEqual(new Uri("https://xquik.com/api/v1/draws/id"), url)); } [Fact] diff --git a/src/XTwitterScraper.Tests/Models/Draws/DrawRunParamsTest.cs b/src/XTwitterScraper.Tests/Models/Draws/DrawRunParamsTest.cs index 62ab929..79820ca 100644 --- a/src/XTwitterScraper.Tests/Models/Draws/DrawRunParamsTest.cs +++ b/src/XTwitterScraper.Tests/Models/Draws/DrawRunParamsTest.cs @@ -149,9 +149,9 @@ public void Url_Works() { DrawRunParams parameters = new() { TweetUrl = "https://x.com/elonmusk/status/1234567890" }; - var url = parameters.Url(new() { ApiKey = "My API Key", BearerToken = "My Bearer Token" }); + var url = parameters.Url(new() { ApiKey = "My API Key" }); - Assert.Equal(new Uri("https://xquik.com/api/v1/draws"), url); + Assert.True(TestBase.UrisEqual(new Uri("https://xquik.com/api/v1/draws"), url)); } [Fact] diff --git a/src/XTwitterScraper.Tests/Models/ErrorTest.cs b/src/XTwitterScraper.Tests/Models/ErrorTest.cs index 6b410d1..d2b303f 100644 --- a/src/XTwitterScraper.Tests/Models/ErrorTest.cs +++ b/src/XTwitterScraper.Tests/Models/ErrorTest.cs @@ -73,17 +73,17 @@ public class ErrorErrorTest : TestBase [InlineData(ErrorError.InvalidTweetID)] [InlineData(ErrorError.InvalidTweetUrl)] [InlineData(ErrorError.InvalidUsername)] + [InlineData(ErrorError.InsufficientCredits)] [InlineData(ErrorError.MissingParams)] [InlineData(ErrorError.MissingQuery)] [InlineData(ErrorError.MonitorAlreadyExists)] [InlineData(ErrorError.MonitorLimitReached)] + [InlineData(ErrorError.NoCredits)] [InlineData(ErrorError.NoSubscription)] [InlineData(ErrorError.NotFound)] - [InlineData(ErrorError.StreamRegistrationFailed)] [InlineData(ErrorError.SubscriptionInactive)] [InlineData(ErrorError.TweetNotFound)] [InlineData(ErrorError.Unauthenticated)] - [InlineData(ErrorError.UsageLimitReached)] [InlineData(ErrorError.UserNotFound)] [InlineData(ErrorError.WebhookInactive)] [InlineData(ErrorError.XApiRateLimited)] @@ -118,17 +118,17 @@ public void InvalidEnumValidationThrows_Works() [InlineData(ErrorError.InvalidTweetID)] [InlineData(ErrorError.InvalidTweetUrl)] [InlineData(ErrorError.InvalidUsername)] + [InlineData(ErrorError.InsufficientCredits)] [InlineData(ErrorError.MissingParams)] [InlineData(ErrorError.MissingQuery)] [InlineData(ErrorError.MonitorAlreadyExists)] [InlineData(ErrorError.MonitorLimitReached)] + [InlineData(ErrorError.NoCredits)] [InlineData(ErrorError.NoSubscription)] [InlineData(ErrorError.NotFound)] - [InlineData(ErrorError.StreamRegistrationFailed)] [InlineData(ErrorError.SubscriptionInactive)] [InlineData(ErrorError.TweetNotFound)] [InlineData(ErrorError.Unauthenticated)] - [InlineData(ErrorError.UsageLimitReached)] [InlineData(ErrorError.UserNotFound)] [InlineData(ErrorError.WebhookInactive)] [InlineData(ErrorError.XApiRateLimited)] diff --git a/src/XTwitterScraper.Tests/Models/EventTypeTest.cs b/src/XTwitterScraper.Tests/Models/EventTypeTest.cs index b47298d..90e4dfe 100644 --- a/src/XTwitterScraper.Tests/Models/EventTypeTest.cs +++ b/src/XTwitterScraper.Tests/Models/EventTypeTest.cs @@ -12,8 +12,6 @@ public class EventTypeTest : TestBase [InlineData(EventType.TweetReply)] [InlineData(EventType.TweetRetweet)] [InlineData(EventType.TweetQuote)] - [InlineData(EventType.FollowerGained)] - [InlineData(EventType.FollowerLost)] public void Validation_Works(EventType rawValue) { // force implicit conversion because Theory can't do that for us @@ -38,8 +36,6 @@ public void InvalidEnumValidationThrows_Works() [InlineData(EventType.TweetReply)] [InlineData(EventType.TweetRetweet)] [InlineData(EventType.TweetQuote)] - [InlineData(EventType.FollowerGained)] - [InlineData(EventType.FollowerLost)] public void SerializationRoundtrip_Works(EventType rawValue) { // force implicit conversion because Theory can't do that for us diff --git a/src/XTwitterScraper.Tests/Models/Events/EventListParamsTest.cs b/src/XTwitterScraper.Tests/Models/Events/EventListParamsTest.cs index 5ee8da8..b848a10 100644 --- a/src/XTwitterScraper.Tests/Models/Events/EventListParamsTest.cs +++ b/src/XTwitterScraper.Tests/Models/Events/EventListParamsTest.cs @@ -77,13 +77,15 @@ public void Url_Works() MonitorID = "monitorId", }; - var url = parameters.Url(new() { ApiKey = "My API Key", BearerToken = "My Bearer Token" }); + var url = parameters.Url(new() { ApiKey = "My API Key" }); - Assert.Equal( - new Uri( - "https://xquik.com/api/v1/events?after=after&eventType=tweet.new&limit=1&monitorId=monitorId" - ), - url + Assert.True( + TestBase.UrisEqual( + new Uri( + "https://xquik.com/api/v1/events?after=after&eventType=tweet.new&limit=1&monitorId=monitorId" + ), + url + ) ); } diff --git a/src/XTwitterScraper.Tests/Models/Events/EventRetrieveParamsTest.cs b/src/XTwitterScraper.Tests/Models/Events/EventRetrieveParamsTest.cs index 1326fc4..bc53618 100644 --- a/src/XTwitterScraper.Tests/Models/Events/EventRetrieveParamsTest.cs +++ b/src/XTwitterScraper.Tests/Models/Events/EventRetrieveParamsTest.cs @@ -20,9 +20,9 @@ public void Url_Works() { EventRetrieveParams parameters = new() { ID = "id" }; - var url = parameters.Url(new() { ApiKey = "My API Key", BearerToken = "My Bearer Token" }); + var url = parameters.Url(new() { ApiKey = "My API Key" }); - Assert.Equal(new Uri("https://xquik.com/api/v1/events/id"), url); + Assert.True(TestBase.UrisEqual(new Uri("https://xquik.com/api/v1/events/id"), url)); } [Fact] diff --git a/src/XTwitterScraper.Tests/Models/Extractions/ExtractionEstimateCostParamsTest.cs b/src/XTwitterScraper.Tests/Models/Extractions/ExtractionEstimateCostParamsTest.cs index 8bbe929..652e2b6 100644 --- a/src/XTwitterScraper.Tests/Models/Extractions/ExtractionEstimateCostParamsTest.cs +++ b/src/XTwitterScraper.Tests/Models/Extractions/ExtractionEstimateCostParamsTest.cs @@ -124,9 +124,11 @@ public void Url_Works() ToolType = ExtractionEstimateCostParamsToolType.FollowerExplorer, }; - var url = parameters.Url(new() { ApiKey = "My API Key", BearerToken = "My Bearer Token" }); + var url = parameters.Url(new() { ApiKey = "My API Key" }); - Assert.Equal(new Uri("https://xquik.com/api/v1/extractions/estimate"), url); + Assert.True( + TestBase.UrisEqual(new Uri("https://xquik.com/api/v1/extractions/estimate"), url) + ); } [Fact] diff --git a/src/XTwitterScraper.Tests/Models/Extractions/ExtractionEstimateCostResponseTest.cs b/src/XTwitterScraper.Tests/Models/Extractions/ExtractionEstimateCostResponseTest.cs index 4936fbd..c759b4d 100644 --- a/src/XTwitterScraper.Tests/Models/Extractions/ExtractionEstimateCostResponseTest.cs +++ b/src/XTwitterScraper.Tests/Models/Extractions/ExtractionEstimateCostResponseTest.cs @@ -12,23 +12,26 @@ public void FieldRoundtrip_Works() var model = new ExtractionEstimateCostResponse { Allowed = true, + CreditsAvailable = "50000", + CreditsRequired = "500", EstimatedResults = 500, - ProjectedPercent = 30, - Source = "api_count", - UsagePercent = 25, + Source = "replyCount", + ResolvedXUserID = "123456", }; bool expectedAllowed = true; + string expectedCreditsAvailable = "50000"; + string expectedCreditsRequired = "500"; long expectedEstimatedResults = 500; - double expectedProjectedPercent = 30; - string expectedSource = "api_count"; - double expectedUsagePercent = 25; + string expectedSource = "replyCount"; + string expectedResolvedXUserID = "123456"; Assert.Equal(expectedAllowed, model.Allowed); + Assert.Equal(expectedCreditsAvailable, model.CreditsAvailable); + Assert.Equal(expectedCreditsRequired, model.CreditsRequired); Assert.Equal(expectedEstimatedResults, model.EstimatedResults); - Assert.Equal(expectedProjectedPercent, model.ProjectedPercent); Assert.Equal(expectedSource, model.Source); - Assert.Equal(expectedUsagePercent, model.UsagePercent); + Assert.Equal(expectedResolvedXUserID, model.ResolvedXUserID); } [Fact] @@ -37,10 +40,11 @@ public void SerializationRoundtrip_Works() var model = new ExtractionEstimateCostResponse { Allowed = true, + CreditsAvailable = "50000", + CreditsRequired = "500", EstimatedResults = 500, - ProjectedPercent = 30, - Source = "api_count", - UsagePercent = 25, + Source = "replyCount", + ResolvedXUserID = "123456", }; string json = JsonSerializer.Serialize(model, ModelBase.SerializerOptions); @@ -58,10 +62,11 @@ public void FieldRoundtripThroughSerialization_Works() var model = new ExtractionEstimateCostResponse { Allowed = true, + CreditsAvailable = "50000", + CreditsRequired = "500", EstimatedResults = 500, - ProjectedPercent = 30, - Source = "api_count", - UsagePercent = 25, + Source = "replyCount", + ResolvedXUserID = "123456", }; string element = JsonSerializer.Serialize(model, ModelBase.SerializerOptions); @@ -72,16 +77,18 @@ public void FieldRoundtripThroughSerialization_Works() Assert.NotNull(deserialized); bool expectedAllowed = true; + string expectedCreditsAvailable = "50000"; + string expectedCreditsRequired = "500"; long expectedEstimatedResults = 500; - double expectedProjectedPercent = 30; - string expectedSource = "api_count"; - double expectedUsagePercent = 25; + string expectedSource = "replyCount"; + string expectedResolvedXUserID = "123456"; Assert.Equal(expectedAllowed, deserialized.Allowed); + Assert.Equal(expectedCreditsAvailable, deserialized.CreditsAvailable); + Assert.Equal(expectedCreditsRequired, deserialized.CreditsRequired); Assert.Equal(expectedEstimatedResults, deserialized.EstimatedResults); - Assert.Equal(expectedProjectedPercent, deserialized.ProjectedPercent); Assert.Equal(expectedSource, deserialized.Source); - Assert.Equal(expectedUsagePercent, deserialized.UsagePercent); + Assert.Equal(expectedResolvedXUserID, deserialized.ResolvedXUserID); } [Fact] @@ -90,10 +97,79 @@ public void Validation_Works() var model = new ExtractionEstimateCostResponse { Allowed = true, + CreditsAvailable = "50000", + CreditsRequired = "500", EstimatedResults = 500, - ProjectedPercent = 30, - Source = "api_count", - UsagePercent = 25, + Source = "replyCount", + ResolvedXUserID = "123456", + }; + + model.Validate(); + } + + [Fact] + public void OptionalNonNullablePropertiesUnsetAreNotSet_Works() + { + var model = new ExtractionEstimateCostResponse + { + Allowed = true, + CreditsAvailable = "50000", + CreditsRequired = "500", + EstimatedResults = 500, + Source = "replyCount", + }; + + Assert.Null(model.ResolvedXUserID); + Assert.False(model.RawData.ContainsKey("resolvedXUserId")); + } + + [Fact] + public void OptionalNonNullablePropertiesUnsetValidation_Works() + { + var model = new ExtractionEstimateCostResponse + { + Allowed = true, + CreditsAvailable = "50000", + CreditsRequired = "500", + EstimatedResults = 500, + Source = "replyCount", + }; + + model.Validate(); + } + + [Fact] + public void OptionalNonNullablePropertiesSetToNullAreNotSet_Works() + { + var model = new ExtractionEstimateCostResponse + { + Allowed = true, + CreditsAvailable = "50000", + CreditsRequired = "500", + EstimatedResults = 500, + Source = "replyCount", + + // Null should be interpreted as omitted for these properties + ResolvedXUserID = null, + }; + + Assert.Null(model.ResolvedXUserID); + Assert.False(model.RawData.ContainsKey("resolvedXUserId")); + } + + [Fact] + public void OptionalNonNullablePropertiesSetToNullValidation_Works() + { + var model = new ExtractionEstimateCostResponse + { + Allowed = true, + CreditsAvailable = "50000", + CreditsRequired = "500", + EstimatedResults = 500, + Source = "replyCount", + + // Null should be interpreted as omitted for these properties + ResolvedXUserID = null, }; model.Validate(); @@ -105,10 +181,11 @@ public void CopyConstructor_Works() var model = new ExtractionEstimateCostResponse { Allowed = true, + CreditsAvailable = "50000", + CreditsRequired = "500", EstimatedResults = 500, - ProjectedPercent = 30, - Source = "api_count", - UsagePercent = 25, + Source = "replyCount", + ResolvedXUserID = "123456", }; ExtractionEstimateCostResponse copied = new(model); diff --git a/src/XTwitterScraper.Tests/Models/Extractions/ExtractionExportResultsParamsTest.cs b/src/XTwitterScraper.Tests/Models/Extractions/ExtractionExportResultsParamsTest.cs index fe791ff..46327d0 100644 --- a/src/XTwitterScraper.Tests/Models/Extractions/ExtractionExportResultsParamsTest.cs +++ b/src/XTwitterScraper.Tests/Models/Extractions/ExtractionExportResultsParamsTest.cs @@ -49,9 +49,14 @@ public void Url_Works() { ExtractionExportResultsParams parameters = new() { ID = "id", Format = Format.Csv }; - var url = parameters.Url(new() { ApiKey = "My API Key", BearerToken = "My Bearer Token" }); + var url = parameters.Url(new() { ApiKey = "My API Key" }); - Assert.Equal(new Uri("https://xquik.com/api/v1/extractions/id/export?format=csv"), url); + Assert.True( + TestBase.UrisEqual( + new Uri("https://xquik.com/api/v1/extractions/id/export?format=csv"), + url + ) + ); } [Fact] diff --git a/src/XTwitterScraper.Tests/Models/Extractions/ExtractionListParamsTest.cs b/src/XTwitterScraper.Tests/Models/Extractions/ExtractionListParamsTest.cs index 08e5625..cf02429 100644 --- a/src/XTwitterScraper.Tests/Models/Extractions/ExtractionListParamsTest.cs +++ b/src/XTwitterScraper.Tests/Models/Extractions/ExtractionListParamsTest.cs @@ -78,13 +78,15 @@ public void Url_Works() ToolType = ToolType.FollowerExplorer, }; - var url = parameters.Url(new() { ApiKey = "My API Key", BearerToken = "My Bearer Token" }); + var url = parameters.Url(new() { ApiKey = "My API Key" }); - Assert.Equal( - new Uri( - "https://xquik.com/api/v1/extractions?after=after&limit=1&status=running&toolType=follower_explorer" - ), - url + Assert.True( + TestBase.UrisEqual( + new Uri( + "https://xquik.com/api/v1/extractions?after=after&limit=1&status=running&toolType=follower_explorer" + ), + url + ) ); } diff --git a/src/XTwitterScraper.Tests/Models/Extractions/ExtractionRetrieveParamsTest.cs b/src/XTwitterScraper.Tests/Models/Extractions/ExtractionRetrieveParamsTest.cs index 4a4ac46..5638ed1 100644 --- a/src/XTwitterScraper.Tests/Models/Extractions/ExtractionRetrieveParamsTest.cs +++ b/src/XTwitterScraper.Tests/Models/Extractions/ExtractionRetrieveParamsTest.cs @@ -63,9 +63,14 @@ public void Url_Works() Limit = 1, }; - var url = parameters.Url(new() { ApiKey = "My API Key", BearerToken = "My Bearer Token" }); + var url = parameters.Url(new() { ApiKey = "My API Key" }); - Assert.Equal(new Uri("https://xquik.com/api/v1/extractions/id?after=after&limit=1"), url); + Assert.True( + TestBase.UrisEqual( + new Uri("https://xquik.com/api/v1/extractions/id?after=after&limit=1"), + url + ) + ); } [Fact] diff --git a/src/XTwitterScraper.Tests/Models/Extractions/ExtractionRunParamsTest.cs b/src/XTwitterScraper.Tests/Models/Extractions/ExtractionRunParamsTest.cs index cdb7c55..386f4b4 100644 --- a/src/XTwitterScraper.Tests/Models/Extractions/ExtractionRunParamsTest.cs +++ b/src/XTwitterScraper.Tests/Models/Extractions/ExtractionRunParamsTest.cs @@ -124,9 +124,9 @@ public void Url_Works() ToolType = ExtractionRunParamsToolType.FollowerExplorer, }; - var url = parameters.Url(new() { ApiKey = "My API Key", BearerToken = "My Bearer Token" }); + var url = parameters.Url(new() { ApiKey = "My API Key" }); - Assert.Equal(new Uri("https://xquik.com/api/v1/extractions"), url); + Assert.True(TestBase.UrisEqual(new Uri("https://xquik.com/api/v1/extractions"), url)); } [Fact] diff --git a/src/XTwitterScraper.Tests/Models/Integrations/IntegrationCreateParamsTest.cs b/src/XTwitterScraper.Tests/Models/Integrations/IntegrationCreateParamsTest.cs deleted file mode 100644 index 00a4214..0000000 --- a/src/XTwitterScraper.Tests/Models/Integrations/IntegrationCreateParamsTest.cs +++ /dev/null @@ -1,127 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Text.Json; -using XTwitterScraper.Core; -using XTwitterScraper.Models; -using XTwitterScraper.Models.Integrations; - -namespace XTwitterScraper.Tests.Models.Integrations; - -public class IntegrationCreateParamsTest : TestBase -{ - [Fact] - public void FieldRoundtrip_Works() - { - var parameters = new IntegrationCreateParams - { - Config = new("-1001234567890"), - EventTypes = [EventType.TweetNew, EventType.FollowerGained], - Name = "My Telegram Bot", - }; - - Config expectedConfig = new("-1001234567890"); - List> expectedEventTypes = - [ - EventType.TweetNew, - EventType.FollowerGained, - ]; - string expectedName = "My Telegram Bot"; - JsonElement expectedType = JsonSerializer.SerializeToElement("telegram"); - - Assert.Equal(expectedConfig, parameters.Config); - Assert.Equal(expectedEventTypes.Count, parameters.EventTypes.Count); - for (int i = 0; i < expectedEventTypes.Count; i++) - { - Assert.Equal(expectedEventTypes[i], parameters.EventTypes[i]); - } - Assert.Equal(expectedName, parameters.Name); - Assert.True(JsonElement.DeepEquals(expectedType, parameters.Type)); - } - - [Fact] - public void Url_Works() - { - IntegrationCreateParams parameters = new() - { - Config = new("-1001234567890"), - EventTypes = [EventType.TweetNew, EventType.FollowerGained], - Name = "My Telegram Bot", - Type = JsonSerializer.SerializeToElement("telegram"), - }; - - var url = parameters.Url(new() { ApiKey = "My API Key", BearerToken = "My Bearer Token" }); - - Assert.Equal(new Uri("https://xquik.com/api/v1/integrations"), url); - } - - [Fact] - public void CopyConstructor_Works() - { - var parameters = new IntegrationCreateParams - { - Config = new("-1001234567890"), - EventTypes = [EventType.TweetNew, EventType.FollowerGained], - Name = "My Telegram Bot", - }; - - IntegrationCreateParams copied = new(parameters); - - Assert.Equal(parameters, copied); - } -} - -public class ConfigTest : TestBase -{ - [Fact] - public void FieldRoundtrip_Works() - { - var model = new Config { ChatID = "-1001234567890" }; - - string expectedChatID = "-1001234567890"; - - Assert.Equal(expectedChatID, model.ChatID); - } - - [Fact] - public void SerializationRoundtrip_Works() - { - var model = new Config { ChatID = "-1001234567890" }; - - string json = JsonSerializer.Serialize(model, ModelBase.SerializerOptions); - var deserialized = JsonSerializer.Deserialize(json, ModelBase.SerializerOptions); - - Assert.Equal(model, deserialized); - } - - [Fact] - public void FieldRoundtripThroughSerialization_Works() - { - var model = new Config { ChatID = "-1001234567890" }; - - string element = JsonSerializer.Serialize(model, ModelBase.SerializerOptions); - var deserialized = JsonSerializer.Deserialize(element, ModelBase.SerializerOptions); - Assert.NotNull(deserialized); - - string expectedChatID = "-1001234567890"; - - Assert.Equal(expectedChatID, deserialized.ChatID); - } - - [Fact] - public void Validation_Works() - { - var model = new Config { ChatID = "-1001234567890" }; - - model.Validate(); - } - - [Fact] - public void CopyConstructor_Works() - { - var model = new Config { ChatID = "-1001234567890" }; - - Config copied = new(model); - - Assert.Equal(model, copied); - } -} diff --git a/src/XTwitterScraper.Tests/Models/Integrations/IntegrationDeleteParamsTest.cs b/src/XTwitterScraper.Tests/Models/Integrations/IntegrationDeleteParamsTest.cs deleted file mode 100644 index b9806db..0000000 --- a/src/XTwitterScraper.Tests/Models/Integrations/IntegrationDeleteParamsTest.cs +++ /dev/null @@ -1,37 +0,0 @@ -using System; -using XTwitterScraper.Models.Integrations; - -namespace XTwitterScraper.Tests.Models.Integrations; - -public class IntegrationDeleteParamsTest : TestBase -{ - [Fact] - public void FieldRoundtrip_Works() - { - var parameters = new IntegrationDeleteParams { ID = "id" }; - - string expectedID = "id"; - - Assert.Equal(expectedID, parameters.ID); - } - - [Fact] - public void Url_Works() - { - IntegrationDeleteParams parameters = new() { ID = "id" }; - - var url = parameters.Url(new() { ApiKey = "My API Key", BearerToken = "My Bearer Token" }); - - Assert.Equal(new Uri("https://xquik.com/api/v1/integrations/id"), url); - } - - [Fact] - public void CopyConstructor_Works() - { - var parameters = new IntegrationDeleteParams { ID = "id" }; - - IntegrationDeleteParams copied = new(parameters); - - Assert.Equal(parameters, copied); - } -} diff --git a/src/XTwitterScraper.Tests/Models/Integrations/IntegrationDeleteResponseTest.cs b/src/XTwitterScraper.Tests/Models/Integrations/IntegrationDeleteResponseTest.cs deleted file mode 100644 index d325594..0000000 --- a/src/XTwitterScraper.Tests/Models/Integrations/IntegrationDeleteResponseTest.cs +++ /dev/null @@ -1,67 +0,0 @@ -using System.Text.Json; -using XTwitterScraper.Core; -using XTwitterScraper.Models.Integrations; - -namespace XTwitterScraper.Tests.Models.Integrations; - -public class IntegrationDeleteResponseTest : TestBase -{ - [Fact] - public void FieldRoundtrip_Works() - { - var model = new IntegrationDeleteResponse { }; - - JsonElement expectedSuccess = JsonSerializer.SerializeToElement(true); - - Assert.True(JsonElement.DeepEquals(expectedSuccess, model.Success)); - } - - [Fact] - public void SerializationRoundtrip_Works() - { - var model = new IntegrationDeleteResponse { }; - - string json = JsonSerializer.Serialize(model, ModelBase.SerializerOptions); - var deserialized = JsonSerializer.Deserialize( - json, - ModelBase.SerializerOptions - ); - - Assert.Equal(model, deserialized); - } - - [Fact] - public void FieldRoundtripThroughSerialization_Works() - { - var model = new IntegrationDeleteResponse { }; - - string element = JsonSerializer.Serialize(model, ModelBase.SerializerOptions); - var deserialized = JsonSerializer.Deserialize( - element, - ModelBase.SerializerOptions - ); - Assert.NotNull(deserialized); - - JsonElement expectedSuccess = JsonSerializer.SerializeToElement(true); - - Assert.True(JsonElement.DeepEquals(expectedSuccess, deserialized.Success)); - } - - [Fact] - public void Validation_Works() - { - var model = new IntegrationDeleteResponse { }; - - model.Validate(); - } - - [Fact] - public void CopyConstructor_Works() - { - var model = new IntegrationDeleteResponse { }; - - IntegrationDeleteResponse copied = new(model); - - Assert.Equal(model, copied); - } -} diff --git a/src/XTwitterScraper.Tests/Models/Integrations/IntegrationDeliveryTest.cs b/src/XTwitterScraper.Tests/Models/Integrations/IntegrationDeliveryTest.cs deleted file mode 100644 index b0fa290..0000000 --- a/src/XTwitterScraper.Tests/Models/Integrations/IntegrationDeliveryTest.cs +++ /dev/null @@ -1,256 +0,0 @@ -using System; -using System.Text.Json; -using XTwitterScraper.Core; -using XTwitterScraper.Models.Integrations; - -namespace XTwitterScraper.Tests.Models.Integrations; - -public class IntegrationDeliveryTest : TestBase -{ - [Fact] - public void FieldRoundtrip_Works() - { - var model = new IntegrationDelivery - { - ID = "42", - Attempts = 1, - CreatedAt = DateTimeOffset.Parse("2025-01-15T12:00:00Z"), - EventType = "tweet.new", - Status = "delivered", - DeliveredAt = DateTimeOffset.Parse("2025-01-15T12:00:01Z"), - LastError = "", - LastStatusCode = 200, - SourceID = "100", - SourceType = "monitor", - }; - - string expectedID = "42"; - long expectedAttempts = 1; - DateTimeOffset expectedCreatedAt = DateTimeOffset.Parse("2025-01-15T12:00:00Z"); - string expectedEventType = "tweet.new"; - string expectedStatus = "delivered"; - DateTimeOffset expectedDeliveredAt = DateTimeOffset.Parse("2025-01-15T12:00:01Z"); - string expectedLastError = ""; - long expectedLastStatusCode = 200; - string expectedSourceID = "100"; - string expectedSourceType = "monitor"; - - Assert.Equal(expectedID, model.ID); - Assert.Equal(expectedAttempts, model.Attempts); - Assert.Equal(expectedCreatedAt, model.CreatedAt); - Assert.Equal(expectedEventType, model.EventType); - Assert.Equal(expectedStatus, model.Status); - Assert.Equal(expectedDeliveredAt, model.DeliveredAt); - Assert.Equal(expectedLastError, model.LastError); - Assert.Equal(expectedLastStatusCode, model.LastStatusCode); - Assert.Equal(expectedSourceID, model.SourceID); - Assert.Equal(expectedSourceType, model.SourceType); - } - - [Fact] - public void SerializationRoundtrip_Works() - { - var model = new IntegrationDelivery - { - ID = "42", - Attempts = 1, - CreatedAt = DateTimeOffset.Parse("2025-01-15T12:00:00Z"), - EventType = "tweet.new", - Status = "delivered", - DeliveredAt = DateTimeOffset.Parse("2025-01-15T12:00:01Z"), - LastError = "", - LastStatusCode = 200, - SourceID = "100", - SourceType = "monitor", - }; - - string json = JsonSerializer.Serialize(model, ModelBase.SerializerOptions); - var deserialized = JsonSerializer.Deserialize( - json, - ModelBase.SerializerOptions - ); - - Assert.Equal(model, deserialized); - } - - [Fact] - public void FieldRoundtripThroughSerialization_Works() - { - var model = new IntegrationDelivery - { - ID = "42", - Attempts = 1, - CreatedAt = DateTimeOffset.Parse("2025-01-15T12:00:00Z"), - EventType = "tweet.new", - Status = "delivered", - DeliveredAt = DateTimeOffset.Parse("2025-01-15T12:00:01Z"), - LastError = "", - LastStatusCode = 200, - SourceID = "100", - SourceType = "monitor", - }; - - string element = JsonSerializer.Serialize(model, ModelBase.SerializerOptions); - var deserialized = JsonSerializer.Deserialize( - element, - ModelBase.SerializerOptions - ); - Assert.NotNull(deserialized); - - string expectedID = "42"; - long expectedAttempts = 1; - DateTimeOffset expectedCreatedAt = DateTimeOffset.Parse("2025-01-15T12:00:00Z"); - string expectedEventType = "tweet.new"; - string expectedStatus = "delivered"; - DateTimeOffset expectedDeliveredAt = DateTimeOffset.Parse("2025-01-15T12:00:01Z"); - string expectedLastError = ""; - long expectedLastStatusCode = 200; - string expectedSourceID = "100"; - string expectedSourceType = "monitor"; - - Assert.Equal(expectedID, deserialized.ID); - Assert.Equal(expectedAttempts, deserialized.Attempts); - Assert.Equal(expectedCreatedAt, deserialized.CreatedAt); - Assert.Equal(expectedEventType, deserialized.EventType); - Assert.Equal(expectedStatus, deserialized.Status); - Assert.Equal(expectedDeliveredAt, deserialized.DeliveredAt); - Assert.Equal(expectedLastError, deserialized.LastError); - Assert.Equal(expectedLastStatusCode, deserialized.LastStatusCode); - Assert.Equal(expectedSourceID, deserialized.SourceID); - Assert.Equal(expectedSourceType, deserialized.SourceType); - } - - [Fact] - public void Validation_Works() - { - var model = new IntegrationDelivery - { - ID = "42", - Attempts = 1, - CreatedAt = DateTimeOffset.Parse("2025-01-15T12:00:00Z"), - EventType = "tweet.new", - Status = "delivered", - DeliveredAt = DateTimeOffset.Parse("2025-01-15T12:00:01Z"), - LastError = "", - LastStatusCode = 200, - SourceID = "100", - SourceType = "monitor", - }; - - model.Validate(); - } - - [Fact] - public void OptionalNonNullablePropertiesUnsetAreNotSet_Works() - { - var model = new IntegrationDelivery - { - ID = "42", - Attempts = 1, - CreatedAt = DateTimeOffset.Parse("2025-01-15T12:00:00Z"), - EventType = "tweet.new", - Status = "delivered", - }; - - Assert.Null(model.DeliveredAt); - Assert.False(model.RawData.ContainsKey("deliveredAt")); - Assert.Null(model.LastError); - Assert.False(model.RawData.ContainsKey("lastError")); - Assert.Null(model.LastStatusCode); - Assert.False(model.RawData.ContainsKey("lastStatusCode")); - Assert.Null(model.SourceID); - Assert.False(model.RawData.ContainsKey("sourceId")); - Assert.Null(model.SourceType); - Assert.False(model.RawData.ContainsKey("sourceType")); - } - - [Fact] - public void OptionalNonNullablePropertiesUnsetValidation_Works() - { - var model = new IntegrationDelivery - { - ID = "42", - Attempts = 1, - CreatedAt = DateTimeOffset.Parse("2025-01-15T12:00:00Z"), - EventType = "tweet.new", - Status = "delivered", - }; - - model.Validate(); - } - - [Fact] - public void OptionalNonNullablePropertiesSetToNullAreNotSet_Works() - { - var model = new IntegrationDelivery - { - ID = "42", - Attempts = 1, - CreatedAt = DateTimeOffset.Parse("2025-01-15T12:00:00Z"), - EventType = "tweet.new", - Status = "delivered", - - // Null should be interpreted as omitted for these properties - DeliveredAt = null, - LastError = null, - LastStatusCode = null, - SourceID = null, - SourceType = null, - }; - - Assert.Null(model.DeliveredAt); - Assert.False(model.RawData.ContainsKey("deliveredAt")); - Assert.Null(model.LastError); - Assert.False(model.RawData.ContainsKey("lastError")); - Assert.Null(model.LastStatusCode); - Assert.False(model.RawData.ContainsKey("lastStatusCode")); - Assert.Null(model.SourceID); - Assert.False(model.RawData.ContainsKey("sourceId")); - Assert.Null(model.SourceType); - Assert.False(model.RawData.ContainsKey("sourceType")); - } - - [Fact] - public void OptionalNonNullablePropertiesSetToNullValidation_Works() - { - var model = new IntegrationDelivery - { - ID = "42", - Attempts = 1, - CreatedAt = DateTimeOffset.Parse("2025-01-15T12:00:00Z"), - EventType = "tweet.new", - Status = "delivered", - - // Null should be interpreted as omitted for these properties - DeliveredAt = null, - LastError = null, - LastStatusCode = null, - SourceID = null, - SourceType = null, - }; - - model.Validate(); - } - - [Fact] - public void CopyConstructor_Works() - { - var model = new IntegrationDelivery - { - ID = "42", - Attempts = 1, - CreatedAt = DateTimeOffset.Parse("2025-01-15T12:00:00Z"), - EventType = "tweet.new", - Status = "delivered", - DeliveredAt = DateTimeOffset.Parse("2025-01-15T12:00:01Z"), - LastError = "", - LastStatusCode = 200, - SourceID = "100", - SourceType = "monitor", - }; - - IntegrationDelivery copied = new(model); - - Assert.Equal(model, copied); - } -} diff --git a/src/XTwitterScraper.Tests/Models/Integrations/IntegrationListDeliveriesParamsTest.cs b/src/XTwitterScraper.Tests/Models/Integrations/IntegrationListDeliveriesParamsTest.cs deleted file mode 100644 index 46d1dbc..0000000 --- a/src/XTwitterScraper.Tests/Models/Integrations/IntegrationListDeliveriesParamsTest.cs +++ /dev/null @@ -1,63 +0,0 @@ -using System; -using XTwitterScraper.Models.Integrations; - -namespace XTwitterScraper.Tests.Models.Integrations; - -public class IntegrationListDeliveriesParamsTest : TestBase -{ - [Fact] - public void FieldRoundtrip_Works() - { - var parameters = new IntegrationListDeliveriesParams { ID = "id", Limit = 1 }; - - string expectedID = "id"; - long expectedLimit = 1; - - Assert.Equal(expectedID, parameters.ID); - Assert.Equal(expectedLimit, parameters.Limit); - } - - [Fact] - public void OptionalNonNullableParamsUnsetAreNotSet_Works() - { - var parameters = new IntegrationListDeliveriesParams { ID = "id" }; - - Assert.Null(parameters.Limit); - Assert.False(parameters.RawQueryData.ContainsKey("limit")); - } - - [Fact] - public void OptionalNonNullableParamsSetToNullAreNotSet_Works() - { - var parameters = new IntegrationListDeliveriesParams - { - ID = "id", - - // Null should be interpreted as omitted for these properties - Limit = null, - }; - - Assert.Null(parameters.Limit); - Assert.False(parameters.RawQueryData.ContainsKey("limit")); - } - - [Fact] - public void Url_Works() - { - IntegrationListDeliveriesParams parameters = new() { ID = "id", Limit = 1 }; - - var url = parameters.Url(new() { ApiKey = "My API Key", BearerToken = "My Bearer Token" }); - - Assert.Equal(new Uri("https://xquik.com/api/v1/integrations/id/deliveries?limit=1"), url); - } - - [Fact] - public void CopyConstructor_Works() - { - var parameters = new IntegrationListDeliveriesParams { ID = "id", Limit = 1 }; - - IntegrationListDeliveriesParams copied = new(parameters); - - Assert.Equal(parameters, copied); - } -} diff --git a/src/XTwitterScraper.Tests/Models/Integrations/IntegrationListDeliveriesResponseTest.cs b/src/XTwitterScraper.Tests/Models/Integrations/IntegrationListDeliveriesResponseTest.cs deleted file mode 100644 index dcf4f90..0000000 --- a/src/XTwitterScraper.Tests/Models/Integrations/IntegrationListDeliveriesResponseTest.cs +++ /dev/null @@ -1,197 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Text.Json; -using XTwitterScraper.Core; -using XTwitterScraper.Models.Integrations; - -namespace XTwitterScraper.Tests.Models.Integrations; - -public class IntegrationListDeliveriesResponseTest : TestBase -{ - [Fact] - public void FieldRoundtrip_Works() - { - var model = new IntegrationListDeliveriesResponse - { - Deliveries = - [ - new() - { - ID = "42", - Attempts = 1, - CreatedAt = DateTimeOffset.Parse("2025-01-15T12:00:00Z"), - EventType = "tweet.new", - Status = "delivered", - DeliveredAt = DateTimeOffset.Parse("2025-01-15T12:00:01Z"), - LastError = "", - LastStatusCode = 200, - SourceID = "100", - SourceType = "monitor", - }, - ], - }; - - List expectedDeliveries = - [ - new() - { - ID = "42", - Attempts = 1, - CreatedAt = DateTimeOffset.Parse("2025-01-15T12:00:00Z"), - EventType = "tweet.new", - Status = "delivered", - DeliveredAt = DateTimeOffset.Parse("2025-01-15T12:00:01Z"), - LastError = "", - LastStatusCode = 200, - SourceID = "100", - SourceType = "monitor", - }, - ]; - - Assert.Equal(expectedDeliveries.Count, model.Deliveries.Count); - for (int i = 0; i < expectedDeliveries.Count; i++) - { - Assert.Equal(expectedDeliveries[i], model.Deliveries[i]); - } - } - - [Fact] - public void SerializationRoundtrip_Works() - { - var model = new IntegrationListDeliveriesResponse - { - Deliveries = - [ - new() - { - ID = "42", - Attempts = 1, - CreatedAt = DateTimeOffset.Parse("2025-01-15T12:00:00Z"), - EventType = "tweet.new", - Status = "delivered", - DeliveredAt = DateTimeOffset.Parse("2025-01-15T12:00:01Z"), - LastError = "", - LastStatusCode = 200, - SourceID = "100", - SourceType = "monitor", - }, - ], - }; - - string json = JsonSerializer.Serialize(model, ModelBase.SerializerOptions); - var deserialized = JsonSerializer.Deserialize( - json, - ModelBase.SerializerOptions - ); - - Assert.Equal(model, deserialized); - } - - [Fact] - public void FieldRoundtripThroughSerialization_Works() - { - var model = new IntegrationListDeliveriesResponse - { - Deliveries = - [ - new() - { - ID = "42", - Attempts = 1, - CreatedAt = DateTimeOffset.Parse("2025-01-15T12:00:00Z"), - EventType = "tweet.new", - Status = "delivered", - DeliveredAt = DateTimeOffset.Parse("2025-01-15T12:00:01Z"), - LastError = "", - LastStatusCode = 200, - SourceID = "100", - SourceType = "monitor", - }, - ], - }; - - string element = JsonSerializer.Serialize(model, ModelBase.SerializerOptions); - var deserialized = JsonSerializer.Deserialize( - element, - ModelBase.SerializerOptions - ); - Assert.NotNull(deserialized); - - List expectedDeliveries = - [ - new() - { - ID = "42", - Attempts = 1, - CreatedAt = DateTimeOffset.Parse("2025-01-15T12:00:00Z"), - EventType = "tweet.new", - Status = "delivered", - DeliveredAt = DateTimeOffset.Parse("2025-01-15T12:00:01Z"), - LastError = "", - LastStatusCode = 200, - SourceID = "100", - SourceType = "monitor", - }, - ]; - - Assert.Equal(expectedDeliveries.Count, deserialized.Deliveries.Count); - for (int i = 0; i < expectedDeliveries.Count; i++) - { - Assert.Equal(expectedDeliveries[i], deserialized.Deliveries[i]); - } - } - - [Fact] - public void Validation_Works() - { - var model = new IntegrationListDeliveriesResponse - { - Deliveries = - [ - new() - { - ID = "42", - Attempts = 1, - CreatedAt = DateTimeOffset.Parse("2025-01-15T12:00:00Z"), - EventType = "tweet.new", - Status = "delivered", - DeliveredAt = DateTimeOffset.Parse("2025-01-15T12:00:01Z"), - LastError = "", - LastStatusCode = 200, - SourceID = "100", - SourceType = "monitor", - }, - ], - }; - - model.Validate(); - } - - [Fact] - public void CopyConstructor_Works() - { - var model = new IntegrationListDeliveriesResponse - { - Deliveries = - [ - new() - { - ID = "42", - Attempts = 1, - CreatedAt = DateTimeOffset.Parse("2025-01-15T12:00:00Z"), - EventType = "tweet.new", - Status = "delivered", - DeliveredAt = DateTimeOffset.Parse("2025-01-15T12:00:01Z"), - LastError = "", - LastStatusCode = 200, - SourceID = "100", - SourceType = "monitor", - }, - ], - }; - - IntegrationListDeliveriesResponse copied = new(model); - - Assert.Equal(model, copied); - } -} diff --git a/src/XTwitterScraper.Tests/Models/Integrations/IntegrationListParamsTest.cs b/src/XTwitterScraper.Tests/Models/Integrations/IntegrationListParamsTest.cs deleted file mode 100644 index 4b6a7e2..0000000 --- a/src/XTwitterScraper.Tests/Models/Integrations/IntegrationListParamsTest.cs +++ /dev/null @@ -1 +0,0 @@ -namespace XTwitterScraper.Tests.Models.Integrations; diff --git a/src/XTwitterScraper.Tests/Models/Integrations/IntegrationListResponseTest.cs b/src/XTwitterScraper.Tests/Models/Integrations/IntegrationListResponseTest.cs deleted file mode 100644 index 4b1b733..0000000 --- a/src/XTwitterScraper.Tests/Models/Integrations/IntegrationListResponseTest.cs +++ /dev/null @@ -1,240 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Text.Json; -using XTwitterScraper.Core; -using XTwitterScraper.Models; -using XTwitterScraper.Models.Integrations; - -namespace XTwitterScraper.Tests.Models.Integrations; - -public class IntegrationListResponseTest : TestBase -{ - [Fact] - public void FieldRoundtrip_Works() - { - var model = new IntegrationListResponse - { - Integrations = - [ - new() - { - ID = "42", - Config = new Dictionary() - { - { "chatId", JsonSerializer.SerializeToElement("bar") }, - }, - CreatedAt = DateTimeOffset.Parse("2025-01-15T12:00:00Z"), - EventTypes = [EventType.TweetNew, EventType.FollowerGained], - IsActive = true, - Name = "My Telegram Bot", - Filters = new Dictionary() - { - { "minFollowers", JsonSerializer.SerializeToElement("bar") }, - }, - MessageTemplate = "New event: {{event.type}}", - ScopeAllMonitors = true, - SilentPush = false, - }, - ], - }; - - List expectedIntegrations = - [ - new() - { - ID = "42", - Config = new Dictionary() - { - { "chatId", JsonSerializer.SerializeToElement("bar") }, - }, - CreatedAt = DateTimeOffset.Parse("2025-01-15T12:00:00Z"), - EventTypes = [EventType.TweetNew, EventType.FollowerGained], - IsActive = true, - Name = "My Telegram Bot", - Filters = new Dictionary() - { - { "minFollowers", JsonSerializer.SerializeToElement("bar") }, - }, - MessageTemplate = "New event: {{event.type}}", - ScopeAllMonitors = true, - SilentPush = false, - }, - ]; - - Assert.Equal(expectedIntegrations.Count, model.Integrations.Count); - for (int i = 0; i < expectedIntegrations.Count; i++) - { - Assert.Equal(expectedIntegrations[i], model.Integrations[i]); - } - } - - [Fact] - public void SerializationRoundtrip_Works() - { - var model = new IntegrationListResponse - { - Integrations = - [ - new() - { - ID = "42", - Config = new Dictionary() - { - { "chatId", JsonSerializer.SerializeToElement("bar") }, - }, - CreatedAt = DateTimeOffset.Parse("2025-01-15T12:00:00Z"), - EventTypes = [EventType.TweetNew, EventType.FollowerGained], - IsActive = true, - Name = "My Telegram Bot", - Filters = new Dictionary() - { - { "minFollowers", JsonSerializer.SerializeToElement("bar") }, - }, - MessageTemplate = "New event: {{event.type}}", - ScopeAllMonitors = true, - SilentPush = false, - }, - ], - }; - - string json = JsonSerializer.Serialize(model, ModelBase.SerializerOptions); - var deserialized = JsonSerializer.Deserialize( - json, - ModelBase.SerializerOptions - ); - - Assert.Equal(model, deserialized); - } - - [Fact] - public void FieldRoundtripThroughSerialization_Works() - { - var model = new IntegrationListResponse - { - Integrations = - [ - new() - { - ID = "42", - Config = new Dictionary() - { - { "chatId", JsonSerializer.SerializeToElement("bar") }, - }, - CreatedAt = DateTimeOffset.Parse("2025-01-15T12:00:00Z"), - EventTypes = [EventType.TweetNew, EventType.FollowerGained], - IsActive = true, - Name = "My Telegram Bot", - Filters = new Dictionary() - { - { "minFollowers", JsonSerializer.SerializeToElement("bar") }, - }, - MessageTemplate = "New event: {{event.type}}", - ScopeAllMonitors = true, - SilentPush = false, - }, - ], - }; - - string element = JsonSerializer.Serialize(model, ModelBase.SerializerOptions); - var deserialized = JsonSerializer.Deserialize( - element, - ModelBase.SerializerOptions - ); - Assert.NotNull(deserialized); - - List expectedIntegrations = - [ - new() - { - ID = "42", - Config = new Dictionary() - { - { "chatId", JsonSerializer.SerializeToElement("bar") }, - }, - CreatedAt = DateTimeOffset.Parse("2025-01-15T12:00:00Z"), - EventTypes = [EventType.TweetNew, EventType.FollowerGained], - IsActive = true, - Name = "My Telegram Bot", - Filters = new Dictionary() - { - { "minFollowers", JsonSerializer.SerializeToElement("bar") }, - }, - MessageTemplate = "New event: {{event.type}}", - ScopeAllMonitors = true, - SilentPush = false, - }, - ]; - - Assert.Equal(expectedIntegrations.Count, deserialized.Integrations.Count); - for (int i = 0; i < expectedIntegrations.Count; i++) - { - Assert.Equal(expectedIntegrations[i], deserialized.Integrations[i]); - } - } - - [Fact] - public void Validation_Works() - { - var model = new IntegrationListResponse - { - Integrations = - [ - new() - { - ID = "42", - Config = new Dictionary() - { - { "chatId", JsonSerializer.SerializeToElement("bar") }, - }, - CreatedAt = DateTimeOffset.Parse("2025-01-15T12:00:00Z"), - EventTypes = [EventType.TweetNew, EventType.FollowerGained], - IsActive = true, - Name = "My Telegram Bot", - Filters = new Dictionary() - { - { "minFollowers", JsonSerializer.SerializeToElement("bar") }, - }, - MessageTemplate = "New event: {{event.type}}", - ScopeAllMonitors = true, - SilentPush = false, - }, - ], - }; - - model.Validate(); - } - - [Fact] - public void CopyConstructor_Works() - { - var model = new IntegrationListResponse - { - Integrations = - [ - new() - { - ID = "42", - Config = new Dictionary() - { - { "chatId", JsonSerializer.SerializeToElement("bar") }, - }, - CreatedAt = DateTimeOffset.Parse("2025-01-15T12:00:00Z"), - EventTypes = [EventType.TweetNew, EventType.FollowerGained], - IsActive = true, - Name = "My Telegram Bot", - Filters = new Dictionary() - { - { "minFollowers", JsonSerializer.SerializeToElement("bar") }, - }, - MessageTemplate = "New event: {{event.type}}", - ScopeAllMonitors = true, - SilentPush = false, - }, - ], - }; - - IntegrationListResponse copied = new(model); - - Assert.Equal(model, copied); - } -} diff --git a/src/XTwitterScraper.Tests/Models/Integrations/IntegrationRetrieveParamsTest.cs b/src/XTwitterScraper.Tests/Models/Integrations/IntegrationRetrieveParamsTest.cs deleted file mode 100644 index e787121..0000000 --- a/src/XTwitterScraper.Tests/Models/Integrations/IntegrationRetrieveParamsTest.cs +++ /dev/null @@ -1,37 +0,0 @@ -using System; -using XTwitterScraper.Models.Integrations; - -namespace XTwitterScraper.Tests.Models.Integrations; - -public class IntegrationRetrieveParamsTest : TestBase -{ - [Fact] - public void FieldRoundtrip_Works() - { - var parameters = new IntegrationRetrieveParams { ID = "id" }; - - string expectedID = "id"; - - Assert.Equal(expectedID, parameters.ID); - } - - [Fact] - public void Url_Works() - { - IntegrationRetrieveParams parameters = new() { ID = "id" }; - - var url = parameters.Url(new() { ApiKey = "My API Key", BearerToken = "My Bearer Token" }); - - Assert.Equal(new Uri("https://xquik.com/api/v1/integrations/id"), url); - } - - [Fact] - public void CopyConstructor_Works() - { - var parameters = new IntegrationRetrieveParams { ID = "id" }; - - IntegrationRetrieveParams copied = new(parameters); - - Assert.Equal(parameters, copied); - } -} diff --git a/src/XTwitterScraper.Tests/Models/Integrations/IntegrationSendTestParamsTest.cs b/src/XTwitterScraper.Tests/Models/Integrations/IntegrationSendTestParamsTest.cs deleted file mode 100644 index fb74f30..0000000 --- a/src/XTwitterScraper.Tests/Models/Integrations/IntegrationSendTestParamsTest.cs +++ /dev/null @@ -1,37 +0,0 @@ -using System; -using XTwitterScraper.Models.Integrations; - -namespace XTwitterScraper.Tests.Models.Integrations; - -public class IntegrationSendTestParamsTest : TestBase -{ - [Fact] - public void FieldRoundtrip_Works() - { - var parameters = new IntegrationSendTestParams { ID = "id" }; - - string expectedID = "id"; - - Assert.Equal(expectedID, parameters.ID); - } - - [Fact] - public void Url_Works() - { - IntegrationSendTestParams parameters = new() { ID = "id" }; - - var url = parameters.Url(new() { ApiKey = "My API Key", BearerToken = "My Bearer Token" }); - - Assert.Equal(new Uri("https://xquik.com/api/v1/integrations/id/test"), url); - } - - [Fact] - public void CopyConstructor_Works() - { - var parameters = new IntegrationSendTestParams { ID = "id" }; - - IntegrationSendTestParams copied = new(parameters); - - Assert.Equal(parameters, copied); - } -} diff --git a/src/XTwitterScraper.Tests/Models/Integrations/IntegrationSendTestResponseTest.cs b/src/XTwitterScraper.Tests/Models/Integrations/IntegrationSendTestResponseTest.cs deleted file mode 100644 index 1f3942e..0000000 --- a/src/XTwitterScraper.Tests/Models/Integrations/IntegrationSendTestResponseTest.cs +++ /dev/null @@ -1,67 +0,0 @@ -using System.Text.Json; -using XTwitterScraper.Core; -using XTwitterScraper.Models.Integrations; - -namespace XTwitterScraper.Tests.Models.Integrations; - -public class IntegrationSendTestResponseTest : TestBase -{ - [Fact] - public void FieldRoundtrip_Works() - { - var model = new IntegrationSendTestResponse { }; - - JsonElement expectedSuccess = JsonSerializer.SerializeToElement(true); - - Assert.True(JsonElement.DeepEquals(expectedSuccess, model.Success)); - } - - [Fact] - public void SerializationRoundtrip_Works() - { - var model = new IntegrationSendTestResponse { }; - - string json = JsonSerializer.Serialize(model, ModelBase.SerializerOptions); - var deserialized = JsonSerializer.Deserialize( - json, - ModelBase.SerializerOptions - ); - - Assert.Equal(model, deserialized); - } - - [Fact] - public void FieldRoundtripThroughSerialization_Works() - { - var model = new IntegrationSendTestResponse { }; - - string element = JsonSerializer.Serialize(model, ModelBase.SerializerOptions); - var deserialized = JsonSerializer.Deserialize( - element, - ModelBase.SerializerOptions - ); - Assert.NotNull(deserialized); - - JsonElement expectedSuccess = JsonSerializer.SerializeToElement(true); - - Assert.True(JsonElement.DeepEquals(expectedSuccess, deserialized.Success)); - } - - [Fact] - public void Validation_Works() - { - var model = new IntegrationSendTestResponse { }; - - model.Validate(); - } - - [Fact] - public void CopyConstructor_Works() - { - var model = new IntegrationSendTestResponse { }; - - IntegrationSendTestResponse copied = new(model); - - Assert.Equal(model, copied); - } -} diff --git a/src/XTwitterScraper.Tests/Models/Integrations/IntegrationTest.cs b/src/XTwitterScraper.Tests/Models/Integrations/IntegrationTest.cs deleted file mode 100644 index f6538c2..0000000 --- a/src/XTwitterScraper.Tests/Models/Integrations/IntegrationTest.cs +++ /dev/null @@ -1,356 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Text.Json; -using XTwitterScraper.Core; -using XTwitterScraper.Models; -using XTwitterScraper.Models.Integrations; - -namespace XTwitterScraper.Tests.Models.Integrations; - -public class IntegrationTest : TestBase -{ - [Fact] - public void FieldRoundtrip_Works() - { - var model = new Integration - { - ID = "42", - Config = new Dictionary() - { - { "chatId", JsonSerializer.SerializeToElement("bar") }, - }, - CreatedAt = DateTimeOffset.Parse("2025-01-15T12:00:00Z"), - EventTypes = [EventType.TweetNew, EventType.FollowerGained], - IsActive = true, - Name = "My Telegram Bot", - Filters = new Dictionary() - { - { "minFollowers", JsonSerializer.SerializeToElement("bar") }, - }, - MessageTemplate = "New event: {{event.type}}", - ScopeAllMonitors = true, - SilentPush = false, - }; - - string expectedID = "42"; - Dictionary expectedConfig = new() - { - { "chatId", JsonSerializer.SerializeToElement("bar") }, - }; - DateTimeOffset expectedCreatedAt = DateTimeOffset.Parse("2025-01-15T12:00:00Z"); - List> expectedEventTypes = - [ - EventType.TweetNew, - EventType.FollowerGained, - ]; - bool expectedIsActive = true; - string expectedName = "My Telegram Bot"; - JsonElement expectedType = JsonSerializer.SerializeToElement("telegram"); - Dictionary expectedFilters = new() - { - { "minFollowers", JsonSerializer.SerializeToElement("bar") }, - }; - string expectedMessageTemplate = "New event: {{event.type}}"; - bool expectedScopeAllMonitors = true; - bool expectedSilentPush = false; - - Assert.Equal(expectedID, model.ID); - Assert.Equal(expectedConfig.Count, model.Config.Count); - foreach (var item in expectedConfig) - { - Assert.True(model.Config.TryGetValue(item.Key, out var value)); - - Assert.True(JsonElement.DeepEquals(value, model.Config[item.Key])); - } - Assert.Equal(expectedCreatedAt, model.CreatedAt); - Assert.Equal(expectedEventTypes.Count, model.EventTypes.Count); - for (int i = 0; i < expectedEventTypes.Count; i++) - { - Assert.Equal(expectedEventTypes[i], model.EventTypes[i]); - } - Assert.Equal(expectedIsActive, model.IsActive); - Assert.Equal(expectedName, model.Name); - Assert.True(JsonElement.DeepEquals(expectedType, model.Type)); - Assert.NotNull(model.Filters); - Assert.Equal(expectedFilters.Count, model.Filters.Count); - foreach (var item in expectedFilters) - { - Assert.True(model.Filters.TryGetValue(item.Key, out var value)); - - Assert.True(JsonElement.DeepEquals(value, model.Filters[item.Key])); - } - Assert.Equal(expectedMessageTemplate, model.MessageTemplate); - Assert.Equal(expectedScopeAllMonitors, model.ScopeAllMonitors); - Assert.Equal(expectedSilentPush, model.SilentPush); - } - - [Fact] - public void SerializationRoundtrip_Works() - { - var model = new Integration - { - ID = "42", - Config = new Dictionary() - { - { "chatId", JsonSerializer.SerializeToElement("bar") }, - }, - CreatedAt = DateTimeOffset.Parse("2025-01-15T12:00:00Z"), - EventTypes = [EventType.TweetNew, EventType.FollowerGained], - IsActive = true, - Name = "My Telegram Bot", - Filters = new Dictionary() - { - { "minFollowers", JsonSerializer.SerializeToElement("bar") }, - }, - MessageTemplate = "New event: {{event.type}}", - ScopeAllMonitors = true, - SilentPush = false, - }; - - string json = JsonSerializer.Serialize(model, ModelBase.SerializerOptions); - var deserialized = JsonSerializer.Deserialize( - json, - ModelBase.SerializerOptions - ); - - Assert.Equal(model, deserialized); - } - - [Fact] - public void FieldRoundtripThroughSerialization_Works() - { - var model = new Integration - { - ID = "42", - Config = new Dictionary() - { - { "chatId", JsonSerializer.SerializeToElement("bar") }, - }, - CreatedAt = DateTimeOffset.Parse("2025-01-15T12:00:00Z"), - EventTypes = [EventType.TweetNew, EventType.FollowerGained], - IsActive = true, - Name = "My Telegram Bot", - Filters = new Dictionary() - { - { "minFollowers", JsonSerializer.SerializeToElement("bar") }, - }, - MessageTemplate = "New event: {{event.type}}", - ScopeAllMonitors = true, - SilentPush = false, - }; - - string element = JsonSerializer.Serialize(model, ModelBase.SerializerOptions); - var deserialized = JsonSerializer.Deserialize( - element, - ModelBase.SerializerOptions - ); - Assert.NotNull(deserialized); - - string expectedID = "42"; - Dictionary expectedConfig = new() - { - { "chatId", JsonSerializer.SerializeToElement("bar") }, - }; - DateTimeOffset expectedCreatedAt = DateTimeOffset.Parse("2025-01-15T12:00:00Z"); - List> expectedEventTypes = - [ - EventType.TweetNew, - EventType.FollowerGained, - ]; - bool expectedIsActive = true; - string expectedName = "My Telegram Bot"; - JsonElement expectedType = JsonSerializer.SerializeToElement("telegram"); - Dictionary expectedFilters = new() - { - { "minFollowers", JsonSerializer.SerializeToElement("bar") }, - }; - string expectedMessageTemplate = "New event: {{event.type}}"; - bool expectedScopeAllMonitors = true; - bool expectedSilentPush = false; - - Assert.Equal(expectedID, deserialized.ID); - Assert.Equal(expectedConfig.Count, deserialized.Config.Count); - foreach (var item in expectedConfig) - { - Assert.True(deserialized.Config.TryGetValue(item.Key, out var value)); - - Assert.True(JsonElement.DeepEquals(value, deserialized.Config[item.Key])); - } - Assert.Equal(expectedCreatedAt, deserialized.CreatedAt); - Assert.Equal(expectedEventTypes.Count, deserialized.EventTypes.Count); - for (int i = 0; i < expectedEventTypes.Count; i++) - { - Assert.Equal(expectedEventTypes[i], deserialized.EventTypes[i]); - } - Assert.Equal(expectedIsActive, deserialized.IsActive); - Assert.Equal(expectedName, deserialized.Name); - Assert.True(JsonElement.DeepEquals(expectedType, deserialized.Type)); - Assert.NotNull(deserialized.Filters); - Assert.Equal(expectedFilters.Count, deserialized.Filters.Count); - foreach (var item in expectedFilters) - { - Assert.True(deserialized.Filters.TryGetValue(item.Key, out var value)); - - Assert.True(JsonElement.DeepEquals(value, deserialized.Filters[item.Key])); - } - Assert.Equal(expectedMessageTemplate, deserialized.MessageTemplate); - Assert.Equal(expectedScopeAllMonitors, deserialized.ScopeAllMonitors); - Assert.Equal(expectedSilentPush, deserialized.SilentPush); - } - - [Fact] - public void Validation_Works() - { - var model = new Integration - { - ID = "42", - Config = new Dictionary() - { - { "chatId", JsonSerializer.SerializeToElement("bar") }, - }, - CreatedAt = DateTimeOffset.Parse("2025-01-15T12:00:00Z"), - EventTypes = [EventType.TweetNew, EventType.FollowerGained], - IsActive = true, - Name = "My Telegram Bot", - Filters = new Dictionary() - { - { "minFollowers", JsonSerializer.SerializeToElement("bar") }, - }, - MessageTemplate = "New event: {{event.type}}", - ScopeAllMonitors = true, - SilentPush = false, - }; - - model.Validate(); - } - - [Fact] - public void OptionalNonNullablePropertiesUnsetAreNotSet_Works() - { - var model = new Integration - { - ID = "42", - Config = new Dictionary() - { - { "chatId", JsonSerializer.SerializeToElement("bar") }, - }, - CreatedAt = DateTimeOffset.Parse("2025-01-15T12:00:00Z"), - EventTypes = [EventType.TweetNew, EventType.FollowerGained], - IsActive = true, - Name = "My Telegram Bot", - }; - - Assert.Null(model.Filters); - Assert.False(model.RawData.ContainsKey("filters")); - Assert.Null(model.MessageTemplate); - Assert.False(model.RawData.ContainsKey("messageTemplate")); - Assert.Null(model.ScopeAllMonitors); - Assert.False(model.RawData.ContainsKey("scopeAllMonitors")); - Assert.Null(model.SilentPush); - Assert.False(model.RawData.ContainsKey("silentPush")); - } - - [Fact] - public void OptionalNonNullablePropertiesUnsetValidation_Works() - { - var model = new Integration - { - ID = "42", - Config = new Dictionary() - { - { "chatId", JsonSerializer.SerializeToElement("bar") }, - }, - CreatedAt = DateTimeOffset.Parse("2025-01-15T12:00:00Z"), - EventTypes = [EventType.TweetNew, EventType.FollowerGained], - IsActive = true, - Name = "My Telegram Bot", - }; - - model.Validate(); - } - - [Fact] - public void OptionalNonNullablePropertiesSetToNullAreNotSet_Works() - { - var model = new Integration - { - ID = "42", - Config = new Dictionary() - { - { "chatId", JsonSerializer.SerializeToElement("bar") }, - }, - CreatedAt = DateTimeOffset.Parse("2025-01-15T12:00:00Z"), - EventTypes = [EventType.TweetNew, EventType.FollowerGained], - IsActive = true, - Name = "My Telegram Bot", - - // Null should be interpreted as omitted for these properties - Filters = null, - MessageTemplate = null, - ScopeAllMonitors = null, - SilentPush = null, - }; - - Assert.Null(model.Filters); - Assert.False(model.RawData.ContainsKey("filters")); - Assert.Null(model.MessageTemplate); - Assert.False(model.RawData.ContainsKey("messageTemplate")); - Assert.Null(model.ScopeAllMonitors); - Assert.False(model.RawData.ContainsKey("scopeAllMonitors")); - Assert.Null(model.SilentPush); - Assert.False(model.RawData.ContainsKey("silentPush")); - } - - [Fact] - public void OptionalNonNullablePropertiesSetToNullValidation_Works() - { - var model = new Integration - { - ID = "42", - Config = new Dictionary() - { - { "chatId", JsonSerializer.SerializeToElement("bar") }, - }, - CreatedAt = DateTimeOffset.Parse("2025-01-15T12:00:00Z"), - EventTypes = [EventType.TweetNew, EventType.FollowerGained], - IsActive = true, - Name = "My Telegram Bot", - - // Null should be interpreted as omitted for these properties - Filters = null, - MessageTemplate = null, - ScopeAllMonitors = null, - SilentPush = null, - }; - - model.Validate(); - } - - [Fact] - public void CopyConstructor_Works() - { - var model = new Integration - { - ID = "42", - Config = new Dictionary() - { - { "chatId", JsonSerializer.SerializeToElement("bar") }, - }, - CreatedAt = DateTimeOffset.Parse("2025-01-15T12:00:00Z"), - EventTypes = [EventType.TweetNew, EventType.FollowerGained], - IsActive = true, - Name = "My Telegram Bot", - Filters = new Dictionary() - { - { "minFollowers", JsonSerializer.SerializeToElement("bar") }, - }, - MessageTemplate = "New event: {{event.type}}", - ScopeAllMonitors = true, - SilentPush = false, - }; - - Integration copied = new(model); - - Assert.Equal(model, copied); - } -} diff --git a/src/XTwitterScraper.Tests/Models/Integrations/IntegrationUpdateParamsTest.cs b/src/XTwitterScraper.Tests/Models/Integrations/IntegrationUpdateParamsTest.cs deleted file mode 100644 index e36b86d..0000000 --- a/src/XTwitterScraper.Tests/Models/Integrations/IntegrationUpdateParamsTest.cs +++ /dev/null @@ -1,148 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Text.Json; -using XTwitterScraper.Core; -using XTwitterScraper.Models; -using XTwitterScraper.Models.Integrations; - -namespace XTwitterScraper.Tests.Models.Integrations; - -public class IntegrationUpdateParamsTest : TestBase -{ - [Fact] - public void FieldRoundtrip_Works() - { - var parameters = new IntegrationUpdateParams - { - ID = "id", - EventTypes = [EventType.TweetNew], - Filters = new Dictionary(), - IsActive = true, - MessageTemplate = new Dictionary(), - Name = "My Telegram Bot", - ScopeAllMonitors = true, - SilentPush = false, - }; - - string expectedID = "id"; - List> expectedEventTypes = [EventType.TweetNew]; - Dictionary expectedFilters = new(); - bool expectedIsActive = true; - Dictionary expectedMessageTemplate = new(); - string expectedName = "My Telegram Bot"; - bool expectedScopeAllMonitors = true; - bool expectedSilentPush = false; - - Assert.Equal(expectedID, parameters.ID); - Assert.NotNull(parameters.EventTypes); - Assert.Equal(expectedEventTypes.Count, parameters.EventTypes.Count); - for (int i = 0; i < expectedEventTypes.Count; i++) - { - Assert.Equal(expectedEventTypes[i], parameters.EventTypes[i]); - } - Assert.NotNull(parameters.Filters); - Assert.Equal(expectedFilters.Count, parameters.Filters.Count); - foreach (var item in expectedFilters) - { - Assert.True(parameters.Filters.TryGetValue(item.Key, out var value)); - - Assert.True(JsonElement.DeepEquals(value, parameters.Filters[item.Key])); - } - Assert.Equal(expectedIsActive, parameters.IsActive); - Assert.NotNull(parameters.MessageTemplate); - Assert.Equal(expectedMessageTemplate.Count, parameters.MessageTemplate.Count); - foreach (var item in expectedMessageTemplate) - { - Assert.True(parameters.MessageTemplate.TryGetValue(item.Key, out var value)); - - Assert.True(JsonElement.DeepEquals(value, parameters.MessageTemplate[item.Key])); - } - Assert.Equal(expectedName, parameters.Name); - Assert.Equal(expectedScopeAllMonitors, parameters.ScopeAllMonitors); - Assert.Equal(expectedSilentPush, parameters.SilentPush); - } - - [Fact] - public void OptionalNonNullableParamsUnsetAreNotSet_Works() - { - var parameters = new IntegrationUpdateParams { ID = "id" }; - - Assert.Null(parameters.EventTypes); - Assert.False(parameters.RawBodyData.ContainsKey("eventTypes")); - Assert.Null(parameters.Filters); - Assert.False(parameters.RawBodyData.ContainsKey("filters")); - Assert.Null(parameters.IsActive); - Assert.False(parameters.RawBodyData.ContainsKey("isActive")); - Assert.Null(parameters.MessageTemplate); - Assert.False(parameters.RawBodyData.ContainsKey("messageTemplate")); - Assert.Null(parameters.Name); - Assert.False(parameters.RawBodyData.ContainsKey("name")); - Assert.Null(parameters.ScopeAllMonitors); - Assert.False(parameters.RawBodyData.ContainsKey("scopeAllMonitors")); - Assert.Null(parameters.SilentPush); - Assert.False(parameters.RawBodyData.ContainsKey("silentPush")); - } - - [Fact] - public void OptionalNonNullableParamsSetToNullAreNotSet_Works() - { - var parameters = new IntegrationUpdateParams - { - ID = "id", - - // Null should be interpreted as omitted for these properties - EventTypes = null, - Filters = null, - IsActive = null, - MessageTemplate = null, - Name = null, - ScopeAllMonitors = null, - SilentPush = null, - }; - - Assert.Null(parameters.EventTypes); - Assert.False(parameters.RawBodyData.ContainsKey("eventTypes")); - Assert.Null(parameters.Filters); - Assert.False(parameters.RawBodyData.ContainsKey("filters")); - Assert.Null(parameters.IsActive); - Assert.False(parameters.RawBodyData.ContainsKey("isActive")); - Assert.Null(parameters.MessageTemplate); - Assert.False(parameters.RawBodyData.ContainsKey("messageTemplate")); - Assert.Null(parameters.Name); - Assert.False(parameters.RawBodyData.ContainsKey("name")); - Assert.Null(parameters.ScopeAllMonitors); - Assert.False(parameters.RawBodyData.ContainsKey("scopeAllMonitors")); - Assert.Null(parameters.SilentPush); - Assert.False(parameters.RawBodyData.ContainsKey("silentPush")); - } - - [Fact] - public void Url_Works() - { - IntegrationUpdateParams parameters = new() { ID = "id" }; - - var url = parameters.Url(new() { ApiKey = "My API Key", BearerToken = "My Bearer Token" }); - - Assert.Equal(new Uri("https://xquik.com/api/v1/integrations/id"), url); - } - - [Fact] - public void CopyConstructor_Works() - { - var parameters = new IntegrationUpdateParams - { - ID = "id", - EventTypes = [EventType.TweetNew], - Filters = new Dictionary(), - IsActive = true, - MessageTemplate = new Dictionary(), - Name = "My Telegram Bot", - ScopeAllMonitors = true, - SilentPush = false, - }; - - IntegrationUpdateParams copied = new(parameters); - - Assert.Equal(parameters, copied); - } -} diff --git a/src/XTwitterScraper.Tests/Models/Monitors/MonitorCreateParamsTest.cs b/src/XTwitterScraper.Tests/Models/Monitors/MonitorCreateParamsTest.cs index be279b7..ac54851 100644 --- a/src/XTwitterScraper.Tests/Models/Monitors/MonitorCreateParamsTest.cs +++ b/src/XTwitterScraper.Tests/Models/Monitors/MonitorCreateParamsTest.cs @@ -13,14 +13,14 @@ public void FieldRoundtrip_Works() { var parameters = new MonitorCreateParams { - EventTypes = [EventType.TweetNew, EventType.FollowerGained], + EventTypes = [EventType.TweetNew, EventType.TweetReply], Username = "elonmusk", }; List> expectedEventTypes = [ EventType.TweetNew, - EventType.FollowerGained, + EventType.TweetReply, ]; string expectedUsername = "elonmusk"; @@ -37,13 +37,13 @@ public void Url_Works() { MonitorCreateParams parameters = new() { - EventTypes = [EventType.TweetNew, EventType.FollowerGained], + EventTypes = [EventType.TweetNew, EventType.TweetReply], Username = "elonmusk", }; - var url = parameters.Url(new() { ApiKey = "My API Key", BearerToken = "My Bearer Token" }); + var url = parameters.Url(new() { ApiKey = "My API Key" }); - Assert.Equal(new Uri("https://xquik.com/api/v1/monitors"), url); + Assert.True(TestBase.UrisEqual(new Uri("https://xquik.com/api/v1/monitors"), url)); } [Fact] @@ -51,7 +51,7 @@ public void CopyConstructor_Works() { var parameters = new MonitorCreateParams { - EventTypes = [EventType.TweetNew, EventType.FollowerGained], + EventTypes = [EventType.TweetNew, EventType.TweetReply], Username = "elonmusk", }; diff --git a/src/XTwitterScraper.Tests/Models/Monitors/MonitorCreateResponseTest.cs b/src/XTwitterScraper.Tests/Models/Monitors/MonitorCreateResponseTest.cs index 52e93e6..1be0507 100644 --- a/src/XTwitterScraper.Tests/Models/Monitors/MonitorCreateResponseTest.cs +++ b/src/XTwitterScraper.Tests/Models/Monitors/MonitorCreateResponseTest.cs @@ -16,7 +16,7 @@ public void FieldRoundtrip_Works() { ID = "42", CreatedAt = DateTimeOffset.Parse("2025-01-15T12:00:00Z"), - EventTypes = [EventType.TweetNew, EventType.FollowerGained], + EventTypes = [EventType.TweetNew, EventType.TweetReply], Username = "elonmusk", XUserID = "1234567890", }; @@ -26,7 +26,7 @@ public void FieldRoundtrip_Works() List> expectedEventTypes = [ EventType.TweetNew, - EventType.FollowerGained, + EventType.TweetReply, ]; string expectedUsername = "elonmusk"; string expectedXUserID = "1234567890"; @@ -49,7 +49,7 @@ public void SerializationRoundtrip_Works() { ID = "42", CreatedAt = DateTimeOffset.Parse("2025-01-15T12:00:00Z"), - EventTypes = [EventType.TweetNew, EventType.FollowerGained], + EventTypes = [EventType.TweetNew, EventType.TweetReply], Username = "elonmusk", XUserID = "1234567890", }; @@ -70,7 +70,7 @@ public void FieldRoundtripThroughSerialization_Works() { ID = "42", CreatedAt = DateTimeOffset.Parse("2025-01-15T12:00:00Z"), - EventTypes = [EventType.TweetNew, EventType.FollowerGained], + EventTypes = [EventType.TweetNew, EventType.TweetReply], Username = "elonmusk", XUserID = "1234567890", }; @@ -87,7 +87,7 @@ public void FieldRoundtripThroughSerialization_Works() List> expectedEventTypes = [ EventType.TweetNew, - EventType.FollowerGained, + EventType.TweetReply, ]; string expectedUsername = "elonmusk"; string expectedXUserID = "1234567890"; @@ -110,7 +110,7 @@ public void Validation_Works() { ID = "42", CreatedAt = DateTimeOffset.Parse("2025-01-15T12:00:00Z"), - EventTypes = [EventType.TweetNew, EventType.FollowerGained], + EventTypes = [EventType.TweetNew, EventType.TweetReply], Username = "elonmusk", XUserID = "1234567890", }; @@ -125,7 +125,7 @@ public void CopyConstructor_Works() { ID = "42", CreatedAt = DateTimeOffset.Parse("2025-01-15T12:00:00Z"), - EventTypes = [EventType.TweetNew, EventType.FollowerGained], + EventTypes = [EventType.TweetNew, EventType.TweetReply], Username = "elonmusk", XUserID = "1234567890", }; diff --git a/src/XTwitterScraper.Tests/Models/Monitors/MonitorDeactivateParamsTest.cs b/src/XTwitterScraper.Tests/Models/Monitors/MonitorDeactivateParamsTest.cs index fe73faf..8a21707 100644 --- a/src/XTwitterScraper.Tests/Models/Monitors/MonitorDeactivateParamsTest.cs +++ b/src/XTwitterScraper.Tests/Models/Monitors/MonitorDeactivateParamsTest.cs @@ -20,9 +20,9 @@ public void Url_Works() { MonitorDeactivateParams parameters = new() { ID = "id" }; - var url = parameters.Url(new() { ApiKey = "My API Key", BearerToken = "My Bearer Token" }); + var url = parameters.Url(new() { ApiKey = "My API Key" }); - Assert.Equal(new Uri("https://xquik.com/api/v1/monitors/id"), url); + Assert.True(TestBase.UrisEqual(new Uri("https://xquik.com/api/v1/monitors/id"), url)); } [Fact] diff --git a/src/XTwitterScraper.Tests/Models/Monitors/MonitorListResponseTest.cs b/src/XTwitterScraper.Tests/Models/Monitors/MonitorListResponseTest.cs index 872ff77..2f12596 100644 --- a/src/XTwitterScraper.Tests/Models/Monitors/MonitorListResponseTest.cs +++ b/src/XTwitterScraper.Tests/Models/Monitors/MonitorListResponseTest.cs @@ -20,7 +20,7 @@ public void FieldRoundtrip_Works() { ID = "42", CreatedAt = DateTimeOffset.Parse("2025-01-15T12:00:00Z"), - EventTypes = [EventType.TweetNew, EventType.FollowerGained], + EventTypes = [EventType.TweetNew, EventType.TweetReply], IsActive = true, Username = "elonmusk", XUserID = "9876543210", @@ -35,7 +35,7 @@ public void FieldRoundtrip_Works() { ID = "42", CreatedAt = DateTimeOffset.Parse("2025-01-15T12:00:00Z"), - EventTypes = [EventType.TweetNew, EventType.FollowerGained], + EventTypes = [EventType.TweetNew, EventType.TweetReply], IsActive = true, Username = "elonmusk", XUserID = "9876543210", @@ -62,7 +62,7 @@ public void SerializationRoundtrip_Works() { ID = "42", CreatedAt = DateTimeOffset.Parse("2025-01-15T12:00:00Z"), - EventTypes = [EventType.TweetNew, EventType.FollowerGained], + EventTypes = [EventType.TweetNew, EventType.TweetReply], IsActive = true, Username = "elonmusk", XUserID = "9876543210", @@ -91,7 +91,7 @@ public void FieldRoundtripThroughSerialization_Works() { ID = "42", CreatedAt = DateTimeOffset.Parse("2025-01-15T12:00:00Z"), - EventTypes = [EventType.TweetNew, EventType.FollowerGained], + EventTypes = [EventType.TweetNew, EventType.TweetReply], IsActive = true, Username = "elonmusk", XUserID = "9876543210", @@ -113,7 +113,7 @@ public void FieldRoundtripThroughSerialization_Works() { ID = "42", CreatedAt = DateTimeOffset.Parse("2025-01-15T12:00:00Z"), - EventTypes = [EventType.TweetNew, EventType.FollowerGained], + EventTypes = [EventType.TweetNew, EventType.TweetReply], IsActive = true, Username = "elonmusk", XUserID = "9876543210", @@ -140,7 +140,7 @@ public void Validation_Works() { ID = "42", CreatedAt = DateTimeOffset.Parse("2025-01-15T12:00:00Z"), - EventTypes = [EventType.TweetNew, EventType.FollowerGained], + EventTypes = [EventType.TweetNew, EventType.TweetReply], IsActive = true, Username = "elonmusk", XUserID = "9876543210", @@ -163,7 +163,7 @@ public void CopyConstructor_Works() { ID = "42", CreatedAt = DateTimeOffset.Parse("2025-01-15T12:00:00Z"), - EventTypes = [EventType.TweetNew, EventType.FollowerGained], + EventTypes = [EventType.TweetNew, EventType.TweetReply], IsActive = true, Username = "elonmusk", XUserID = "9876543210", diff --git a/src/XTwitterScraper.Tests/Models/Monitors/MonitorRetrieveParamsTest.cs b/src/XTwitterScraper.Tests/Models/Monitors/MonitorRetrieveParamsTest.cs index e7427ad..03f5a29 100644 --- a/src/XTwitterScraper.Tests/Models/Monitors/MonitorRetrieveParamsTest.cs +++ b/src/XTwitterScraper.Tests/Models/Monitors/MonitorRetrieveParamsTest.cs @@ -20,9 +20,9 @@ public void Url_Works() { MonitorRetrieveParams parameters = new() { ID = "id" }; - var url = parameters.Url(new() { ApiKey = "My API Key", BearerToken = "My Bearer Token" }); + var url = parameters.Url(new() { ApiKey = "My API Key" }); - Assert.Equal(new Uri("https://xquik.com/api/v1/monitors/id"), url); + Assert.True(TestBase.UrisEqual(new Uri("https://xquik.com/api/v1/monitors/id"), url)); } [Fact] diff --git a/src/XTwitterScraper.Tests/Models/Monitors/MonitorTest.cs b/src/XTwitterScraper.Tests/Models/Monitors/MonitorTest.cs index 7433502..75bb171 100644 --- a/src/XTwitterScraper.Tests/Models/Monitors/MonitorTest.cs +++ b/src/XTwitterScraper.Tests/Models/Monitors/MonitorTest.cs @@ -16,7 +16,7 @@ public void FieldRoundtrip_Works() { ID = "42", CreatedAt = DateTimeOffset.Parse("2025-01-15T12:00:00Z"), - EventTypes = [EventType.TweetNew, EventType.FollowerGained], + EventTypes = [EventType.TweetNew, EventType.TweetReply], IsActive = true, Username = "elonmusk", XUserID = "9876543210", @@ -27,7 +27,7 @@ public void FieldRoundtrip_Works() List> expectedEventTypes = [ EventType.TweetNew, - EventType.FollowerGained, + EventType.TweetReply, ]; bool expectedIsActive = true; string expectedUsername = "elonmusk"; @@ -52,7 +52,7 @@ public void SerializationRoundtrip_Works() { ID = "42", CreatedAt = DateTimeOffset.Parse("2025-01-15T12:00:00Z"), - EventTypes = [EventType.TweetNew, EventType.FollowerGained], + EventTypes = [EventType.TweetNew, EventType.TweetReply], IsActive = true, Username = "elonmusk", XUserID = "9876543210", @@ -71,7 +71,7 @@ public void FieldRoundtripThroughSerialization_Works() { ID = "42", CreatedAt = DateTimeOffset.Parse("2025-01-15T12:00:00Z"), - EventTypes = [EventType.TweetNew, EventType.FollowerGained], + EventTypes = [EventType.TweetNew, EventType.TweetReply], IsActive = true, Username = "elonmusk", XUserID = "9876543210", @@ -89,7 +89,7 @@ public void FieldRoundtripThroughSerialization_Works() List> expectedEventTypes = [ EventType.TweetNew, - EventType.FollowerGained, + EventType.TweetReply, ]; bool expectedIsActive = true; string expectedUsername = "elonmusk"; @@ -114,7 +114,7 @@ public void Validation_Works() { ID = "42", CreatedAt = DateTimeOffset.Parse("2025-01-15T12:00:00Z"), - EventTypes = [EventType.TweetNew, EventType.FollowerGained], + EventTypes = [EventType.TweetNew, EventType.TweetReply], IsActive = true, Username = "elonmusk", XUserID = "9876543210", @@ -130,7 +130,7 @@ public void CopyConstructor_Works() { ID = "42", CreatedAt = DateTimeOffset.Parse("2025-01-15T12:00:00Z"), - EventTypes = [EventType.TweetNew, EventType.FollowerGained], + EventTypes = [EventType.TweetNew, EventType.TweetReply], IsActive = true, Username = "elonmusk", XUserID = "9876543210", diff --git a/src/XTwitterScraper.Tests/Models/Monitors/MonitorUpdateParamsTest.cs b/src/XTwitterScraper.Tests/Models/Monitors/MonitorUpdateParamsTest.cs index 1c5899a..a6a33e0 100644 --- a/src/XTwitterScraper.Tests/Models/Monitors/MonitorUpdateParamsTest.cs +++ b/src/XTwitterScraper.Tests/Models/Monitors/MonitorUpdateParamsTest.cs @@ -66,9 +66,9 @@ public void Url_Works() { MonitorUpdateParams parameters = new() { ID = "id" }; - var url = parameters.Url(new() { ApiKey = "My API Key", BearerToken = "My Bearer Token" }); + var url = parameters.Url(new() { ApiKey = "My API Key" }); - Assert.Equal(new Uri("https://xquik.com/api/v1/monitors/id"), url); + Assert.True(TestBase.UrisEqual(new Uri("https://xquik.com/api/v1/monitors/id"), url)); } [Fact] diff --git a/src/XTwitterScraper.Tests/Models/PaginatedTweetsTest.cs b/src/XTwitterScraper.Tests/Models/PaginatedTweetsTest.cs index 894f60a..6a2dce8 100644 --- a/src/XTwitterScraper.Tests/Models/PaginatedTweetsTest.cs +++ b/src/XTwitterScraper.Tests/Models/PaginatedTweetsTest.cs @@ -2,7 +2,6 @@ using System.Text.Json; using XTwitterScraper.Core; using XTwitterScraper.Models; -using XTwitterScraper.Models.X.Tweets; namespace XTwitterScraper.Tests.Models; diff --git a/src/XTwitterScraper.Tests/Models/PaginatedUsersTest.cs b/src/XTwitterScraper.Tests/Models/PaginatedUsersTest.cs index dc67e0c..fee4f3f 100644 --- a/src/XTwitterScraper.Tests/Models/PaginatedUsersTest.cs +++ b/src/XTwitterScraper.Tests/Models/PaginatedUsersTest.cs @@ -2,7 +2,6 @@ using System.Text.Json; using XTwitterScraper.Core; using XTwitterScraper.Models; -using XTwitterScraper.Models.X.Users; namespace XTwitterScraper.Tests.Models; diff --git a/src/XTwitterScraper.Tests/Models/Radar/RadarItemTest.cs b/src/XTwitterScraper.Tests/Models/Radar/RadarItemTest.cs index 9128702..2362d6b 100644 --- a/src/XTwitterScraper.Tests/Models/Radar/RadarItemTest.cs +++ b/src/XTwitterScraper.Tests/Models/Radar/RadarItemTest.cs @@ -1,6 +1,8 @@ using System; +using System.Collections.Generic; using System.Text.Json; using XTwitterScraper.Core; +using XTwitterScraper.Exceptions; using XTwitterScraper.Models.Radar; namespace XTwitterScraper.Tests.Models.Radar; @@ -12,32 +14,59 @@ public void FieldRoundtrip_Works() { var model = new RadarItem { - Category = "Technology", + ID = "4712", + Category = RadarItemCategory.Tech, + CreatedAt = DateTimeOffset.Parse("2025-01-15T12:01:00Z"), + Language = "en", + Metadata = new Dictionary() + { + { "foo", JsonSerializer.SerializeToElement("bar") }, + }, PublishedAt = DateTimeOffset.Parse("2025-01-15T12:00:00Z"), - Region = "US", + Region = "global", Score = 95.5, - Source = "X", + Source = RadarItemSource.Trustmrr, + SourceID = "trustmrr_acme", Title = "AI Revolution in 2025", Description = "AI is transforming every industry", ImageUrl = "https://example.com/images/ai.jpg", Url = "https://example.com/article/ai-revolution", }; - string expectedCategory = "Technology"; + string expectedID = "4712"; + ApiEnum expectedCategory = RadarItemCategory.Tech; + DateTimeOffset expectedCreatedAt = DateTimeOffset.Parse("2025-01-15T12:01:00Z"); + string expectedLanguage = "en"; + Dictionary expectedMetadata = new() + { + { "foo", JsonSerializer.SerializeToElement("bar") }, + }; DateTimeOffset expectedPublishedAt = DateTimeOffset.Parse("2025-01-15T12:00:00Z"); - string expectedRegion = "US"; + string expectedRegion = "global"; double expectedScore = 95.5; - string expectedSource = "X"; + ApiEnum expectedSource = RadarItemSource.Trustmrr; + string expectedSourceID = "trustmrr_acme"; string expectedTitle = "AI Revolution in 2025"; string expectedDescription = "AI is transforming every industry"; string expectedImageUrl = "https://example.com/images/ai.jpg"; string expectedUrl = "https://example.com/article/ai-revolution"; + Assert.Equal(expectedID, model.ID); Assert.Equal(expectedCategory, model.Category); + Assert.Equal(expectedCreatedAt, model.CreatedAt); + Assert.Equal(expectedLanguage, model.Language); + Assert.Equal(expectedMetadata.Count, model.Metadata.Count); + foreach (var item in expectedMetadata) + { + Assert.True(model.Metadata.TryGetValue(item.Key, out var value)); + + Assert.True(JsonElement.DeepEquals(value, model.Metadata[item.Key])); + } Assert.Equal(expectedPublishedAt, model.PublishedAt); Assert.Equal(expectedRegion, model.Region); Assert.Equal(expectedScore, model.Score); Assert.Equal(expectedSource, model.Source); + Assert.Equal(expectedSourceID, model.SourceID); Assert.Equal(expectedTitle, model.Title); Assert.Equal(expectedDescription, model.Description); Assert.Equal(expectedImageUrl, model.ImageUrl); @@ -49,11 +78,19 @@ public void SerializationRoundtrip_Works() { var model = new RadarItem { - Category = "Technology", + ID = "4712", + Category = RadarItemCategory.Tech, + CreatedAt = DateTimeOffset.Parse("2025-01-15T12:01:00Z"), + Language = "en", + Metadata = new Dictionary() + { + { "foo", JsonSerializer.SerializeToElement("bar") }, + }, PublishedAt = DateTimeOffset.Parse("2025-01-15T12:00:00Z"), - Region = "US", + Region = "global", Score = 95.5, - Source = "X", + Source = RadarItemSource.Trustmrr, + SourceID = "trustmrr_acme", Title = "AI Revolution in 2025", Description = "AI is transforming every industry", ImageUrl = "https://example.com/images/ai.jpg", @@ -71,11 +108,19 @@ public void FieldRoundtripThroughSerialization_Works() { var model = new RadarItem { - Category = "Technology", + ID = "4712", + Category = RadarItemCategory.Tech, + CreatedAt = DateTimeOffset.Parse("2025-01-15T12:01:00Z"), + Language = "en", + Metadata = new Dictionary() + { + { "foo", JsonSerializer.SerializeToElement("bar") }, + }, PublishedAt = DateTimeOffset.Parse("2025-01-15T12:00:00Z"), - Region = "US", + Region = "global", Score = 95.5, - Source = "X", + Source = RadarItemSource.Trustmrr, + SourceID = "trustmrr_acme", Title = "AI Revolution in 2025", Description = "AI is transforming every industry", ImageUrl = "https://example.com/images/ai.jpg", @@ -89,21 +134,40 @@ public void FieldRoundtripThroughSerialization_Works() ); Assert.NotNull(deserialized); - string expectedCategory = "Technology"; + string expectedID = "4712"; + ApiEnum expectedCategory = RadarItemCategory.Tech; + DateTimeOffset expectedCreatedAt = DateTimeOffset.Parse("2025-01-15T12:01:00Z"); + string expectedLanguage = "en"; + Dictionary expectedMetadata = new() + { + { "foo", JsonSerializer.SerializeToElement("bar") }, + }; DateTimeOffset expectedPublishedAt = DateTimeOffset.Parse("2025-01-15T12:00:00Z"); - string expectedRegion = "US"; + string expectedRegion = "global"; double expectedScore = 95.5; - string expectedSource = "X"; + ApiEnum expectedSource = RadarItemSource.Trustmrr; + string expectedSourceID = "trustmrr_acme"; string expectedTitle = "AI Revolution in 2025"; string expectedDescription = "AI is transforming every industry"; string expectedImageUrl = "https://example.com/images/ai.jpg"; string expectedUrl = "https://example.com/article/ai-revolution"; + Assert.Equal(expectedID, deserialized.ID); Assert.Equal(expectedCategory, deserialized.Category); + Assert.Equal(expectedCreatedAt, deserialized.CreatedAt); + Assert.Equal(expectedLanguage, deserialized.Language); + Assert.Equal(expectedMetadata.Count, deserialized.Metadata.Count); + foreach (var item in expectedMetadata) + { + Assert.True(deserialized.Metadata.TryGetValue(item.Key, out var value)); + + Assert.True(JsonElement.DeepEquals(value, deserialized.Metadata[item.Key])); + } Assert.Equal(expectedPublishedAt, deserialized.PublishedAt); Assert.Equal(expectedRegion, deserialized.Region); Assert.Equal(expectedScore, deserialized.Score); Assert.Equal(expectedSource, deserialized.Source); + Assert.Equal(expectedSourceID, deserialized.SourceID); Assert.Equal(expectedTitle, deserialized.Title); Assert.Equal(expectedDescription, deserialized.Description); Assert.Equal(expectedImageUrl, deserialized.ImageUrl); @@ -115,11 +179,19 @@ public void Validation_Works() { var model = new RadarItem { - Category = "Technology", + ID = "4712", + Category = RadarItemCategory.Tech, + CreatedAt = DateTimeOffset.Parse("2025-01-15T12:01:00Z"), + Language = "en", + Metadata = new Dictionary() + { + { "foo", JsonSerializer.SerializeToElement("bar") }, + }, PublishedAt = DateTimeOffset.Parse("2025-01-15T12:00:00Z"), - Region = "US", + Region = "global", Score = 95.5, - Source = "X", + Source = RadarItemSource.Trustmrr, + SourceID = "trustmrr_acme", Title = "AI Revolution in 2025", Description = "AI is transforming every industry", ImageUrl = "https://example.com/images/ai.jpg", @@ -134,11 +206,19 @@ public void OptionalNonNullablePropertiesUnsetAreNotSet_Works() { var model = new RadarItem { - Category = "Technology", + ID = "4712", + Category = RadarItemCategory.Tech, + CreatedAt = DateTimeOffset.Parse("2025-01-15T12:01:00Z"), + Language = "en", + Metadata = new Dictionary() + { + { "foo", JsonSerializer.SerializeToElement("bar") }, + }, PublishedAt = DateTimeOffset.Parse("2025-01-15T12:00:00Z"), - Region = "US", + Region = "global", Score = 95.5, - Source = "X", + Source = RadarItemSource.Trustmrr, + SourceID = "trustmrr_acme", Title = "AI Revolution in 2025", }; @@ -155,11 +235,19 @@ public void OptionalNonNullablePropertiesUnsetValidation_Works() { var model = new RadarItem { - Category = "Technology", + ID = "4712", + Category = RadarItemCategory.Tech, + CreatedAt = DateTimeOffset.Parse("2025-01-15T12:01:00Z"), + Language = "en", + Metadata = new Dictionary() + { + { "foo", JsonSerializer.SerializeToElement("bar") }, + }, PublishedAt = DateTimeOffset.Parse("2025-01-15T12:00:00Z"), - Region = "US", + Region = "global", Score = 95.5, - Source = "X", + Source = RadarItemSource.Trustmrr, + SourceID = "trustmrr_acme", Title = "AI Revolution in 2025", }; @@ -171,11 +259,19 @@ public void OptionalNonNullablePropertiesSetToNullAreNotSet_Works() { var model = new RadarItem { - Category = "Technology", + ID = "4712", + Category = RadarItemCategory.Tech, + CreatedAt = DateTimeOffset.Parse("2025-01-15T12:01:00Z"), + Language = "en", + Metadata = new Dictionary() + { + { "foo", JsonSerializer.SerializeToElement("bar") }, + }, PublishedAt = DateTimeOffset.Parse("2025-01-15T12:00:00Z"), - Region = "US", + Region = "global", Score = 95.5, - Source = "X", + Source = RadarItemSource.Trustmrr, + SourceID = "trustmrr_acme", Title = "AI Revolution in 2025", // Null should be interpreted as omitted for these properties @@ -197,11 +293,19 @@ public void OptionalNonNullablePropertiesSetToNullValidation_Works() { var model = new RadarItem { - Category = "Technology", + ID = "4712", + Category = RadarItemCategory.Tech, + CreatedAt = DateTimeOffset.Parse("2025-01-15T12:01:00Z"), + Language = "en", + Metadata = new Dictionary() + { + { "foo", JsonSerializer.SerializeToElement("bar") }, + }, PublishedAt = DateTimeOffset.Parse("2025-01-15T12:00:00Z"), - Region = "US", + Region = "global", Score = 95.5, - Source = "X", + Source = RadarItemSource.Trustmrr, + SourceID = "trustmrr_acme", Title = "AI Revolution in 2025", // Null should be interpreted as omitted for these properties @@ -218,11 +322,19 @@ public void CopyConstructor_Works() { var model = new RadarItem { - Category = "Technology", + ID = "4712", + Category = RadarItemCategory.Tech, + CreatedAt = DateTimeOffset.Parse("2025-01-15T12:01:00Z"), + Language = "en", + Metadata = new Dictionary() + { + { "foo", JsonSerializer.SerializeToElement("bar") }, + }, PublishedAt = DateTimeOffset.Parse("2025-01-15T12:00:00Z"), - Region = "US", + Region = "global", Score = 95.5, - Source = "X", + Source = RadarItemSource.Trustmrr, + SourceID = "trustmrr_acme", Title = "AI Revolution in 2025", Description = "AI is transforming every industry", ImageUrl = "https://example.com/images/ai.jpg", @@ -234,3 +346,141 @@ public void CopyConstructor_Works() Assert.Equal(model, copied); } } + +public class RadarItemCategoryTest : TestBase +{ + [Theory] + [InlineData(RadarItemCategory.General)] + [InlineData(RadarItemCategory.Tech)] + [InlineData(RadarItemCategory.Dev)] + [InlineData(RadarItemCategory.Science)] + [InlineData(RadarItemCategory.Culture)] + [InlineData(RadarItemCategory.Politics)] + [InlineData(RadarItemCategory.Business)] + [InlineData(RadarItemCategory.Entertainment)] + public void Validation_Works(RadarItemCategory rawValue) + { + // force implicit conversion because Theory can't do that for us + ApiEnum value = rawValue; + value.Validate(); + } + + [Fact] + public void InvalidEnumValidationThrows_Works() + { + var value = JsonSerializer.Deserialize>( + JsonSerializer.SerializeToElement("invalid value"), + ModelBase.SerializerOptions + ); + + Assert.NotNull(value); + Assert.Throws(() => value.Validate()); + } + + [Theory] + [InlineData(RadarItemCategory.General)] + [InlineData(RadarItemCategory.Tech)] + [InlineData(RadarItemCategory.Dev)] + [InlineData(RadarItemCategory.Science)] + [InlineData(RadarItemCategory.Culture)] + [InlineData(RadarItemCategory.Politics)] + [InlineData(RadarItemCategory.Business)] + [InlineData(RadarItemCategory.Entertainment)] + public void SerializationRoundtrip_Works(RadarItemCategory rawValue) + { + // force implicit conversion because Theory can't do that for us + ApiEnum value = rawValue; + + string json = JsonSerializer.Serialize(value, ModelBase.SerializerOptions); + var deserialized = JsonSerializer.Deserialize>( + json, + ModelBase.SerializerOptions + ); + + Assert.Equal(value, deserialized); + } + + [Fact] + public void InvalidEnumSerializationRoundtrip_Works() + { + var value = JsonSerializer.Deserialize>( + JsonSerializer.SerializeToElement("invalid value"), + ModelBase.SerializerOptions + ); + string json = JsonSerializer.Serialize(value, ModelBase.SerializerOptions); + var deserialized = JsonSerializer.Deserialize>( + json, + ModelBase.SerializerOptions + ); + + Assert.Equal(value, deserialized); + } +} + +public class RadarItemSourceTest : TestBase +{ + [Theory] + [InlineData(RadarItemSource.GitHub)] + [InlineData(RadarItemSource.GoogleTrends)] + [InlineData(RadarItemSource.HackerNews)] + [InlineData(RadarItemSource.Polymarket)] + [InlineData(RadarItemSource.Reddit)] + [InlineData(RadarItemSource.Trustmrr)] + [InlineData(RadarItemSource.Wikipedia)] + public void Validation_Works(RadarItemSource rawValue) + { + // force implicit conversion because Theory can't do that for us + ApiEnum value = rawValue; + value.Validate(); + } + + [Fact] + public void InvalidEnumValidationThrows_Works() + { + var value = JsonSerializer.Deserialize>( + JsonSerializer.SerializeToElement("invalid value"), + ModelBase.SerializerOptions + ); + + Assert.NotNull(value); + Assert.Throws(() => value.Validate()); + } + + [Theory] + [InlineData(RadarItemSource.GitHub)] + [InlineData(RadarItemSource.GoogleTrends)] + [InlineData(RadarItemSource.HackerNews)] + [InlineData(RadarItemSource.Polymarket)] + [InlineData(RadarItemSource.Reddit)] + [InlineData(RadarItemSource.Trustmrr)] + [InlineData(RadarItemSource.Wikipedia)] + public void SerializationRoundtrip_Works(RadarItemSource rawValue) + { + // force implicit conversion because Theory can't do that for us + ApiEnum value = rawValue; + + string json = JsonSerializer.Serialize(value, ModelBase.SerializerOptions); + var deserialized = JsonSerializer.Deserialize>( + json, + ModelBase.SerializerOptions + ); + + Assert.Equal(value, deserialized); + } + + [Fact] + public void InvalidEnumSerializationRoundtrip_Works() + { + var value = JsonSerializer.Deserialize>( + JsonSerializer.SerializeToElement("invalid value"), + ModelBase.SerializerOptions + ); + string json = JsonSerializer.Serialize(value, ModelBase.SerializerOptions); + var deserialized = JsonSerializer.Deserialize>( + json, + ModelBase.SerializerOptions + ); + + Assert.Equal(value, deserialized); + } +} diff --git a/src/XTwitterScraper.Tests/Models/Radar/RadarRetrieveTrendingTopicsParamsTest.cs b/src/XTwitterScraper.Tests/Models/Radar/RadarRetrieveTrendingTopicsParamsTest.cs index a95c62a..d0a4f6d 100644 --- a/src/XTwitterScraper.Tests/Models/Radar/RadarRetrieveTrendingTopicsParamsTest.cs +++ b/src/XTwitterScraper.Tests/Models/Radar/RadarRetrieveTrendingTopicsParamsTest.cs @@ -13,22 +13,25 @@ public void FieldRoundtrip_Works() { var parameters = new RadarRetrieveTrendingTopicsParams { - Category = "category", - Count = 0, - Hours = 0, + After = "after", + Category = Category.General, + Hours = 1, + Limit = 1, Region = "region", Source = Source.GitHub, }; - string expectedCategory = "category"; - long expectedCount = 0; - long expectedHours = 0; + string expectedAfter = "after"; + ApiEnum expectedCategory = Category.General; + long expectedHours = 1; + long expectedLimit = 1; string expectedRegion = "region"; ApiEnum expectedSource = Source.GitHub; + Assert.Equal(expectedAfter, parameters.After); Assert.Equal(expectedCategory, parameters.Category); - Assert.Equal(expectedCount, parameters.Count); Assert.Equal(expectedHours, parameters.Hours); + Assert.Equal(expectedLimit, parameters.Limit); Assert.Equal(expectedRegion, parameters.Region); Assert.Equal(expectedSource, parameters.Source); } @@ -38,12 +41,14 @@ public void OptionalNonNullableParamsUnsetAreNotSet_Works() { var parameters = new RadarRetrieveTrendingTopicsParams { }; + Assert.Null(parameters.After); + Assert.False(parameters.RawQueryData.ContainsKey("after")); Assert.Null(parameters.Category); Assert.False(parameters.RawQueryData.ContainsKey("category")); - Assert.Null(parameters.Count); - Assert.False(parameters.RawQueryData.ContainsKey("count")); Assert.Null(parameters.Hours); Assert.False(parameters.RawQueryData.ContainsKey("hours")); + Assert.Null(parameters.Limit); + Assert.False(parameters.RawQueryData.ContainsKey("limit")); Assert.Null(parameters.Region); Assert.False(parameters.RawQueryData.ContainsKey("region")); Assert.Null(parameters.Source); @@ -56,19 +61,22 @@ public void OptionalNonNullableParamsSetToNullAreNotSet_Works() var parameters = new RadarRetrieveTrendingTopicsParams { // Null should be interpreted as omitted for these properties + After = null, Category = null, - Count = null, Hours = null, + Limit = null, Region = null, Source = null, }; + Assert.Null(parameters.After); + Assert.False(parameters.RawQueryData.ContainsKey("after")); Assert.Null(parameters.Category); Assert.False(parameters.RawQueryData.ContainsKey("category")); - Assert.Null(parameters.Count); - Assert.False(parameters.RawQueryData.ContainsKey("count")); Assert.Null(parameters.Hours); Assert.False(parameters.RawQueryData.ContainsKey("hours")); + Assert.Null(parameters.Limit); + Assert.False(parameters.RawQueryData.ContainsKey("limit")); Assert.Null(parameters.Region); Assert.False(parameters.RawQueryData.ContainsKey("region")); Assert.Null(parameters.Source); @@ -80,20 +88,23 @@ public void Url_Works() { RadarRetrieveTrendingTopicsParams parameters = new() { - Category = "category", - Count = 0, - Hours = 0, + After = "after", + Category = Category.General, + Hours = 1, + Limit = 1, Region = "region", Source = Source.GitHub, }; - var url = parameters.Url(new() { ApiKey = "My API Key", BearerToken = "My Bearer Token" }); + var url = parameters.Url(new() { ApiKey = "My API Key" }); - Assert.Equal( - new Uri( - "https://xquik.com/api/v1/radar?category=category&count=0&hours=0®ion=region&source=github" - ), - url + Assert.True( + TestBase.UrisEqual( + new Uri( + "https://xquik.com/api/v1/radar?after=after&category=general&hours=1&limit=1®ion=region&source=github" + ), + url + ) ); } @@ -102,9 +113,10 @@ public void CopyConstructor_Works() { var parameters = new RadarRetrieveTrendingTopicsParams { - Category = "category", - Count = 0, - Hours = 0, + After = "after", + Category = Category.General, + Hours = 1, + Limit = 1, Region = "region", Source = Source.GitHub, }; @@ -115,6 +127,76 @@ public void CopyConstructor_Works() } } +public class CategoryTest : TestBase +{ + [Theory] + [InlineData(Category.General)] + [InlineData(Category.Tech)] + [InlineData(Category.Dev)] + [InlineData(Category.Science)] + [InlineData(Category.Culture)] + [InlineData(Category.Politics)] + [InlineData(Category.Business)] + [InlineData(Category.Entertainment)] + public void Validation_Works(Category rawValue) + { + // force implicit conversion because Theory can't do that for us + ApiEnum value = rawValue; + value.Validate(); + } + + [Fact] + public void InvalidEnumValidationThrows_Works() + { + var value = JsonSerializer.Deserialize>( + JsonSerializer.SerializeToElement("invalid value"), + ModelBase.SerializerOptions + ); + + Assert.NotNull(value); + Assert.Throws(() => value.Validate()); + } + + [Theory] + [InlineData(Category.General)] + [InlineData(Category.Tech)] + [InlineData(Category.Dev)] + [InlineData(Category.Science)] + [InlineData(Category.Culture)] + [InlineData(Category.Politics)] + [InlineData(Category.Business)] + [InlineData(Category.Entertainment)] + public void SerializationRoundtrip_Works(Category rawValue) + { + // force implicit conversion because Theory can't do that for us + ApiEnum value = rawValue; + + string json = JsonSerializer.Serialize(value, ModelBase.SerializerOptions); + var deserialized = JsonSerializer.Deserialize>( + json, + ModelBase.SerializerOptions + ); + + Assert.Equal(value, deserialized); + } + + [Fact] + public void InvalidEnumSerializationRoundtrip_Works() + { + var value = JsonSerializer.Deserialize>( + JsonSerializer.SerializeToElement("invalid value"), + ModelBase.SerializerOptions + ); + string json = JsonSerializer.Serialize(value, ModelBase.SerializerOptions); + var deserialized = JsonSerializer.Deserialize>( + json, + ModelBase.SerializerOptions + ); + + Assert.Equal(value, deserialized); + } +} + public class SourceTest : TestBase { [Theory] diff --git a/src/XTwitterScraper.Tests/Models/Radar/RadarRetrieveTrendingTopicsResponseTest.cs b/src/XTwitterScraper.Tests/Models/Radar/RadarRetrieveTrendingTopicsResponseTest.cs index 5b0521a..a902324 100644 --- a/src/XTwitterScraper.Tests/Models/Radar/RadarRetrieveTrendingTopicsResponseTest.cs +++ b/src/XTwitterScraper.Tests/Models/Radar/RadarRetrieveTrendingTopicsResponseTest.cs @@ -13,47 +13,66 @@ public void FieldRoundtrip_Works() { var model = new RadarRetrieveTrendingTopicsResponse { + HasMore = false, Items = [ new() { - Category = "Technology", + ID = "4712", + Category = RadarItemCategory.Tech, + CreatedAt = DateTimeOffset.Parse("2025-01-15T12:01:00Z"), + Language = "en", + Metadata = new Dictionary() + { + { "foo", JsonSerializer.SerializeToElement("bar") }, + }, PublishedAt = DateTimeOffset.Parse("2025-01-15T12:00:00Z"), - Region = "US", + Region = "global", Score = 95.5, - Source = "X", + Source = RadarItemSource.Trustmrr, + SourceID = "trustmrr_acme", Title = "AI Revolution in 2025", Description = "AI is transforming every industry", ImageUrl = "https://example.com/images/ai.jpg", Url = "https://example.com/article/ai-revolution", }, ], - Total = 0, + NextCursor = "nextCursor", }; + bool expectedHasMore = false; List expectedItems = [ new() { - Category = "Technology", + ID = "4712", + Category = RadarItemCategory.Tech, + CreatedAt = DateTimeOffset.Parse("2025-01-15T12:01:00Z"), + Language = "en", + Metadata = new Dictionary() + { + { "foo", JsonSerializer.SerializeToElement("bar") }, + }, PublishedAt = DateTimeOffset.Parse("2025-01-15T12:00:00Z"), - Region = "US", + Region = "global", Score = 95.5, - Source = "X", + Source = RadarItemSource.Trustmrr, + SourceID = "trustmrr_acme", Title = "AI Revolution in 2025", Description = "AI is transforming every industry", ImageUrl = "https://example.com/images/ai.jpg", Url = "https://example.com/article/ai-revolution", }, ]; - long expectedTotal = 0; + string expectedNextCursor = "nextCursor"; + Assert.Equal(expectedHasMore, model.HasMore); Assert.Equal(expectedItems.Count, model.Items.Count); for (int i = 0; i < expectedItems.Count; i++) { Assert.Equal(expectedItems[i], model.Items[i]); } - Assert.Equal(expectedTotal, model.Total); + Assert.Equal(expectedNextCursor, model.NextCursor); } [Fact] @@ -61,22 +80,31 @@ public void SerializationRoundtrip_Works() { var model = new RadarRetrieveTrendingTopicsResponse { + HasMore = false, Items = [ new() { - Category = "Technology", + ID = "4712", + Category = RadarItemCategory.Tech, + CreatedAt = DateTimeOffset.Parse("2025-01-15T12:01:00Z"), + Language = "en", + Metadata = new Dictionary() + { + { "foo", JsonSerializer.SerializeToElement("bar") }, + }, PublishedAt = DateTimeOffset.Parse("2025-01-15T12:00:00Z"), - Region = "US", + Region = "global", Score = 95.5, - Source = "X", + Source = RadarItemSource.Trustmrr, + SourceID = "trustmrr_acme", Title = "AI Revolution in 2025", Description = "AI is transforming every industry", ImageUrl = "https://example.com/images/ai.jpg", Url = "https://example.com/article/ai-revolution", }, ], - Total = 0, + NextCursor = "nextCursor", }; string json = JsonSerializer.Serialize(model, ModelBase.SerializerOptions); @@ -93,22 +121,31 @@ public void FieldRoundtripThroughSerialization_Works() { var model = new RadarRetrieveTrendingTopicsResponse { + HasMore = false, Items = [ new() { - Category = "Technology", + ID = "4712", + Category = RadarItemCategory.Tech, + CreatedAt = DateTimeOffset.Parse("2025-01-15T12:01:00Z"), + Language = "en", + Metadata = new Dictionary() + { + { "foo", JsonSerializer.SerializeToElement("bar") }, + }, PublishedAt = DateTimeOffset.Parse("2025-01-15T12:00:00Z"), - Region = "US", + Region = "global", Score = 95.5, - Source = "X", + Source = RadarItemSource.Trustmrr, + SourceID = "trustmrr_acme", Title = "AI Revolution in 2025", Description = "AI is transforming every industry", ImageUrl = "https://example.com/images/ai.jpg", Url = "https://example.com/article/ai-revolution", }, ], - Total = 0, + NextCursor = "nextCursor", }; string element = JsonSerializer.Serialize(model, ModelBase.SerializerOptions); @@ -118,29 +155,39 @@ public void FieldRoundtripThroughSerialization_Works() ); Assert.NotNull(deserialized); + bool expectedHasMore = false; List expectedItems = [ new() { - Category = "Technology", + ID = "4712", + Category = RadarItemCategory.Tech, + CreatedAt = DateTimeOffset.Parse("2025-01-15T12:01:00Z"), + Language = "en", + Metadata = new Dictionary() + { + { "foo", JsonSerializer.SerializeToElement("bar") }, + }, PublishedAt = DateTimeOffset.Parse("2025-01-15T12:00:00Z"), - Region = "US", + Region = "global", Score = 95.5, - Source = "X", + Source = RadarItemSource.Trustmrr, + SourceID = "trustmrr_acme", Title = "AI Revolution in 2025", Description = "AI is transforming every industry", ImageUrl = "https://example.com/images/ai.jpg", Url = "https://example.com/article/ai-revolution", }, ]; - long expectedTotal = 0; + string expectedNextCursor = "nextCursor"; + Assert.Equal(expectedHasMore, deserialized.HasMore); Assert.Equal(expectedItems.Count, deserialized.Items.Count); for (int i = 0; i < expectedItems.Count; i++) { Assert.Equal(expectedItems[i], deserialized.Items[i]); } - Assert.Equal(expectedTotal, deserialized.Total); + Assert.Equal(expectedNextCursor, deserialized.NextCursor); } [Fact] @@ -148,22 +195,175 @@ public void Validation_Works() { var model = new RadarRetrieveTrendingTopicsResponse { + HasMore = false, + Items = + [ + new() + { + ID = "4712", + Category = RadarItemCategory.Tech, + CreatedAt = DateTimeOffset.Parse("2025-01-15T12:01:00Z"), + Language = "en", + Metadata = new Dictionary() + { + { "foo", JsonSerializer.SerializeToElement("bar") }, + }, + PublishedAt = DateTimeOffset.Parse("2025-01-15T12:00:00Z"), + Region = "global", + Score = 95.5, + Source = RadarItemSource.Trustmrr, + SourceID = "trustmrr_acme", + Title = "AI Revolution in 2025", + Description = "AI is transforming every industry", + ImageUrl = "https://example.com/images/ai.jpg", + Url = "https://example.com/article/ai-revolution", + }, + ], + NextCursor = "nextCursor", + }; + + model.Validate(); + } + + [Fact] + public void OptionalNonNullablePropertiesUnsetAreNotSet_Works() + { + var model = new RadarRetrieveTrendingTopicsResponse + { + HasMore = false, + Items = + [ + new() + { + ID = "4712", + Category = RadarItemCategory.Tech, + CreatedAt = DateTimeOffset.Parse("2025-01-15T12:01:00Z"), + Language = "en", + Metadata = new Dictionary() + { + { "foo", JsonSerializer.SerializeToElement("bar") }, + }, + PublishedAt = DateTimeOffset.Parse("2025-01-15T12:00:00Z"), + Region = "global", + Score = 95.5, + Source = RadarItemSource.Trustmrr, + SourceID = "trustmrr_acme", + Title = "AI Revolution in 2025", + Description = "AI is transforming every industry", + ImageUrl = "https://example.com/images/ai.jpg", + Url = "https://example.com/article/ai-revolution", + }, + ], + }; + + Assert.Null(model.NextCursor); + Assert.False(model.RawData.ContainsKey("nextCursor")); + } + + [Fact] + public void OptionalNonNullablePropertiesUnsetValidation_Works() + { + var model = new RadarRetrieveTrendingTopicsResponse + { + HasMore = false, + Items = + [ + new() + { + ID = "4712", + Category = RadarItemCategory.Tech, + CreatedAt = DateTimeOffset.Parse("2025-01-15T12:01:00Z"), + Language = "en", + Metadata = new Dictionary() + { + { "foo", JsonSerializer.SerializeToElement("bar") }, + }, + PublishedAt = DateTimeOffset.Parse("2025-01-15T12:00:00Z"), + Region = "global", + Score = 95.5, + Source = RadarItemSource.Trustmrr, + SourceID = "trustmrr_acme", + Title = "AI Revolution in 2025", + Description = "AI is transforming every industry", + ImageUrl = "https://example.com/images/ai.jpg", + Url = "https://example.com/article/ai-revolution", + }, + ], + }; + + model.Validate(); + } + + [Fact] + public void OptionalNonNullablePropertiesSetToNullAreNotSet_Works() + { + var model = new RadarRetrieveTrendingTopicsResponse + { + HasMore = false, Items = [ new() { - Category = "Technology", + ID = "4712", + Category = RadarItemCategory.Tech, + CreatedAt = DateTimeOffset.Parse("2025-01-15T12:01:00Z"), + Language = "en", + Metadata = new Dictionary() + { + { "foo", JsonSerializer.SerializeToElement("bar") }, + }, PublishedAt = DateTimeOffset.Parse("2025-01-15T12:00:00Z"), - Region = "US", + Region = "global", Score = 95.5, - Source = "X", + Source = RadarItemSource.Trustmrr, + SourceID = "trustmrr_acme", Title = "AI Revolution in 2025", Description = "AI is transforming every industry", ImageUrl = "https://example.com/images/ai.jpg", Url = "https://example.com/article/ai-revolution", }, ], - Total = 0, + + // Null should be interpreted as omitted for these properties + NextCursor = null, + }; + + Assert.Null(model.NextCursor); + Assert.False(model.RawData.ContainsKey("nextCursor")); + } + + [Fact] + public void OptionalNonNullablePropertiesSetToNullValidation_Works() + { + var model = new RadarRetrieveTrendingTopicsResponse + { + HasMore = false, + Items = + [ + new() + { + ID = "4712", + Category = RadarItemCategory.Tech, + CreatedAt = DateTimeOffset.Parse("2025-01-15T12:01:00Z"), + Language = "en", + Metadata = new Dictionary() + { + { "foo", JsonSerializer.SerializeToElement("bar") }, + }, + PublishedAt = DateTimeOffset.Parse("2025-01-15T12:00:00Z"), + Region = "global", + Score = 95.5, + Source = RadarItemSource.Trustmrr, + SourceID = "trustmrr_acme", + Title = "AI Revolution in 2025", + Description = "AI is transforming every industry", + ImageUrl = "https://example.com/images/ai.jpg", + Url = "https://example.com/article/ai-revolution", + }, + ], + + // Null should be interpreted as omitted for these properties + NextCursor = null, }; model.Validate(); @@ -174,22 +374,31 @@ public void CopyConstructor_Works() { var model = new RadarRetrieveTrendingTopicsResponse { + HasMore = false, Items = [ new() { - Category = "Technology", + ID = "4712", + Category = RadarItemCategory.Tech, + CreatedAt = DateTimeOffset.Parse("2025-01-15T12:01:00Z"), + Language = "en", + Metadata = new Dictionary() + { + { "foo", JsonSerializer.SerializeToElement("bar") }, + }, PublishedAt = DateTimeOffset.Parse("2025-01-15T12:00:00Z"), - Region = "US", + Region = "global", Score = 95.5, - Source = "X", + Source = RadarItemSource.Trustmrr, + SourceID = "trustmrr_acme", Title = "AI Revolution in 2025", Description = "AI is transforming every industry", ImageUrl = "https://example.com/images/ai.jpg", Url = "https://example.com/article/ai-revolution", }, ], - Total = 0, + NextCursor = "nextCursor", }; RadarRetrieveTrendingTopicsResponse copied = new(model); diff --git a/src/XTwitterScraper.Tests/Models/X/Tweets/SearchTweetTest.cs b/src/XTwitterScraper.Tests/Models/SearchTweetTest.cs similarity index 96% rename from src/XTwitterScraper.Tests/Models/X/Tweets/SearchTweetTest.cs rename to src/XTwitterScraper.Tests/Models/SearchTweetTest.cs index 8564d62..fdbf535 100644 --- a/src/XTwitterScraper.Tests/Models/X/Tweets/SearchTweetTest.cs +++ b/src/XTwitterScraper.Tests/Models/SearchTweetTest.cs @@ -1,8 +1,8 @@ using System.Text.Json; using XTwitterScraper.Core; -using XTwitterScraper.Models.X.Tweets; +using XTwitterScraper.Models; -namespace XTwitterScraper.Tests.Models.X.Tweets; +namespace XTwitterScraper.Tests.Models; public class SearchTweetTest : TestBase { diff --git a/src/XTwitterScraper.Tests/Models/Styles/StyleAnalyzeParamsTest.cs b/src/XTwitterScraper.Tests/Models/Styles/StyleAnalyzeParamsTest.cs index e747ae6..74f4852 100644 --- a/src/XTwitterScraper.Tests/Models/Styles/StyleAnalyzeParamsTest.cs +++ b/src/XTwitterScraper.Tests/Models/Styles/StyleAnalyzeParamsTest.cs @@ -20,9 +20,9 @@ public void Url_Works() { StyleAnalyzeParams parameters = new() { Username = "elonmusk" }; - var url = parameters.Url(new() { ApiKey = "My API Key", BearerToken = "My Bearer Token" }); + var url = parameters.Url(new() { ApiKey = "My API Key" }); - Assert.Equal(new Uri("https://xquik.com/api/v1/styles"), url); + Assert.True(TestBase.UrisEqual(new Uri("https://xquik.com/api/v1/styles"), url)); } [Fact] diff --git a/src/XTwitterScraper.Tests/Models/Styles/StyleCompareParamsTest.cs b/src/XTwitterScraper.Tests/Models/Styles/StyleCompareParamsTest.cs index 43fd3f6..a28392d 100644 --- a/src/XTwitterScraper.Tests/Models/Styles/StyleCompareParamsTest.cs +++ b/src/XTwitterScraper.Tests/Models/Styles/StyleCompareParamsTest.cs @@ -26,13 +26,15 @@ public void Url_Works() { StyleCompareParams parameters = new() { Username1 = "username1", Username2 = "username2" }; - var url = parameters.Url(new() { ApiKey = "My API Key", BearerToken = "My Bearer Token" }); - - Assert.Equal( - new Uri( - "https://xquik.com/api/v1/styles/compare?username1=username1&username2=username2" - ), - url + var url = parameters.Url(new() { ApiKey = "My API Key" }); + + Assert.True( + TestBase.UrisEqual( + new Uri( + "https://xquik.com/api/v1/styles/compare?username1=username1&username2=username2" + ), + url + ) ); } diff --git a/src/XTwitterScraper.Tests/Models/Styles/StyleDeleteParamsTest.cs b/src/XTwitterScraper.Tests/Models/Styles/StyleDeleteParamsTest.cs index 59371a8..03b5170 100644 --- a/src/XTwitterScraper.Tests/Models/Styles/StyleDeleteParamsTest.cs +++ b/src/XTwitterScraper.Tests/Models/Styles/StyleDeleteParamsTest.cs @@ -20,9 +20,9 @@ public void Url_Works() { StyleDeleteParams parameters = new() { ID = "id" }; - var url = parameters.Url(new() { ApiKey = "My API Key", BearerToken = "My Bearer Token" }); + var url = parameters.Url(new() { ApiKey = "My API Key" }); - Assert.Equal(new Uri("https://xquik.com/api/v1/styles/id"), url); + Assert.True(TestBase.UrisEqual(new Uri("https://xquik.com/api/v1/styles/id"), url)); } [Fact] diff --git a/src/XTwitterScraper.Tests/Models/Styles/StyleGetPerformanceParamsTest.cs b/src/XTwitterScraper.Tests/Models/Styles/StyleGetPerformanceParamsTest.cs index f3dd7ef..4ca0dd3 100644 --- a/src/XTwitterScraper.Tests/Models/Styles/StyleGetPerformanceParamsTest.cs +++ b/src/XTwitterScraper.Tests/Models/Styles/StyleGetPerformanceParamsTest.cs @@ -20,9 +20,11 @@ public void Url_Works() { StyleGetPerformanceParams parameters = new() { ID = "id" }; - var url = parameters.Url(new() { ApiKey = "My API Key", BearerToken = "My Bearer Token" }); + var url = parameters.Url(new() { ApiKey = "My API Key" }); - Assert.Equal(new Uri("https://xquik.com/api/v1/styles/id/performance"), url); + Assert.True( + TestBase.UrisEqual(new Uri("https://xquik.com/api/v1/styles/id/performance"), url) + ); } [Fact] diff --git a/src/XTwitterScraper.Tests/Models/Styles/StyleRetrieveParamsTest.cs b/src/XTwitterScraper.Tests/Models/Styles/StyleRetrieveParamsTest.cs index 94f4a1e..c4275d0 100644 --- a/src/XTwitterScraper.Tests/Models/Styles/StyleRetrieveParamsTest.cs +++ b/src/XTwitterScraper.Tests/Models/Styles/StyleRetrieveParamsTest.cs @@ -20,9 +20,9 @@ public void Url_Works() { StyleRetrieveParams parameters = new() { ID = "id" }; - var url = parameters.Url(new() { ApiKey = "My API Key", BearerToken = "My Bearer Token" }); + var url = parameters.Url(new() { ApiKey = "My API Key" }); - Assert.Equal(new Uri("https://xquik.com/api/v1/styles/id"), url); + Assert.True(TestBase.UrisEqual(new Uri("https://xquik.com/api/v1/styles/id"), url)); } [Fact] diff --git a/src/XTwitterScraper.Tests/Models/Styles/StyleUpdateParamsTest.cs b/src/XTwitterScraper.Tests/Models/Styles/StyleUpdateParamsTest.cs index c5abd9b..192a514 100644 --- a/src/XTwitterScraper.Tests/Models/Styles/StyleUpdateParamsTest.cs +++ b/src/XTwitterScraper.Tests/Models/Styles/StyleUpdateParamsTest.cs @@ -41,9 +41,9 @@ public void Url_Works() Tweets = [new("Excited to share our latest research findings.")], }; - var url = parameters.Url(new() { ApiKey = "My API Key", BearerToken = "My Bearer Token" }); + var url = parameters.Url(new() { ApiKey = "My API Key" }); - Assert.Equal(new Uri("https://xquik.com/api/v1/styles/id"), url); + Assert.True(TestBase.UrisEqual(new Uri("https://xquik.com/api/v1/styles/id"), url)); } [Fact] diff --git a/src/XTwitterScraper.Tests/Models/Support/Tickets/TicketCreateParamsTest.cs b/src/XTwitterScraper.Tests/Models/Support/Tickets/TicketCreateParamsTest.cs index 79e4979..9c8239c 100644 --- a/src/XTwitterScraper.Tests/Models/Support/Tickets/TicketCreateParamsTest.cs +++ b/src/XTwitterScraper.Tests/Models/Support/Tickets/TicketCreateParamsTest.cs @@ -30,9 +30,9 @@ public void Url_Works() Subject = "Cannot connect X account", }; - var url = parameters.Url(new() { ApiKey = "My API Key", BearerToken = "My Bearer Token" }); + var url = parameters.Url(new() { ApiKey = "My API Key" }); - Assert.Equal(new Uri("https://xquik.com/api/v1/support/tickets"), url); + Assert.True(TestBase.UrisEqual(new Uri("https://xquik.com/api/v1/support/tickets"), url)); } [Fact] diff --git a/src/XTwitterScraper.Tests/Models/Support/Tickets/TicketReplyParamsTest.cs b/src/XTwitterScraper.Tests/Models/Support/Tickets/TicketReplyParamsTest.cs index 0573b69..1b1459c 100644 --- a/src/XTwitterScraper.Tests/Models/Support/Tickets/TicketReplyParamsTest.cs +++ b/src/XTwitterScraper.Tests/Models/Support/Tickets/TicketReplyParamsTest.cs @@ -22,9 +22,11 @@ public void Url_Works() { TicketReplyParams parameters = new() { ID = "id", Body = "Thank you for the update." }; - var url = parameters.Url(new() { ApiKey = "My API Key", BearerToken = "My Bearer Token" }); + var url = parameters.Url(new() { ApiKey = "My API Key" }); - Assert.Equal(new Uri("https://xquik.com/api/v1/support/tickets/id/messages"), url); + Assert.True( + TestBase.UrisEqual(new Uri("https://xquik.com/api/v1/support/tickets/id/messages"), url) + ); } [Fact] diff --git a/src/XTwitterScraper.Tests/Models/Support/Tickets/TicketRetrieveParamsTest.cs b/src/XTwitterScraper.Tests/Models/Support/Tickets/TicketRetrieveParamsTest.cs index ce8f3ec..2d2c18a 100644 --- a/src/XTwitterScraper.Tests/Models/Support/Tickets/TicketRetrieveParamsTest.cs +++ b/src/XTwitterScraper.Tests/Models/Support/Tickets/TicketRetrieveParamsTest.cs @@ -20,9 +20,14 @@ public void Url_Works() { TicketRetrieveParams parameters = new() { ID = "messages_value" }; - var url = parameters.Url(new() { ApiKey = "My API Key", BearerToken = "My Bearer Token" }); - - Assert.Equal(new Uri("https://xquik.com/api/v1/support/tickets/messages_value"), url); + var url = parameters.Url(new() { ApiKey = "My API Key" }); + + Assert.True( + TestBase.UrisEqual( + new Uri("https://xquik.com/api/v1/support/tickets/messages_value"), + url + ) + ); } [Fact] diff --git a/src/XTwitterScraper.Tests/Models/Support/Tickets/TicketUpdateParamsTest.cs b/src/XTwitterScraper.Tests/Models/Support/Tickets/TicketUpdateParamsTest.cs index 08007c8..7e7d1e3 100644 --- a/src/XTwitterScraper.Tests/Models/Support/Tickets/TicketUpdateParamsTest.cs +++ b/src/XTwitterScraper.Tests/Models/Support/Tickets/TicketUpdateParamsTest.cs @@ -25,9 +25,11 @@ public void Url_Works() { TicketUpdateParams parameters = new() { ID = "id", Status = Status.Resolved }; - var url = parameters.Url(new() { ApiKey = "My API Key", BearerToken = "My Bearer Token" }); + var url = parameters.Url(new() { ApiKey = "My API Key" }); - Assert.Equal(new Uri("https://xquik.com/api/v1/support/tickets/id"), url); + Assert.True( + TestBase.UrisEqual(new Uri("https://xquik.com/api/v1/support/tickets/id"), url) + ); } [Fact] diff --git a/src/XTwitterScraper.Tests/Models/Trends/TrendListParamsTest.cs b/src/XTwitterScraper.Tests/Models/Trends/TrendListParamsTest.cs index 9bfa9c0..4462cee 100644 --- a/src/XTwitterScraper.Tests/Models/Trends/TrendListParamsTest.cs +++ b/src/XTwitterScraper.Tests/Models/Trends/TrendListParamsTest.cs @@ -49,9 +49,11 @@ public void Url_Works() { TrendListParams parameters = new() { Count = 1, Woeid = 0 }; - var url = parameters.Url(new() { ApiKey = "My API Key", BearerToken = "My Bearer Token" }); + var url = parameters.Url(new() { ApiKey = "My API Key" }); - Assert.Equal(new Uri("https://xquik.com/api/v1/trends?count=1&woeid=0"), url); + Assert.True( + TestBase.UrisEqual(new Uri("https://xquik.com/api/v1/trends?count=1&woeid=0"), url) + ); } [Fact] diff --git a/src/XTwitterScraper.Tests/Models/X/Users/UserProfileTest.cs b/src/XTwitterScraper.Tests/Models/UserProfileTest.cs similarity index 96% rename from src/XTwitterScraper.Tests/Models/X/Users/UserProfileTest.cs rename to src/XTwitterScraper.Tests/Models/UserProfileTest.cs index 4997e8c..dfae9e5 100644 --- a/src/XTwitterScraper.Tests/Models/X/Users/UserProfileTest.cs +++ b/src/XTwitterScraper.Tests/Models/UserProfileTest.cs @@ -1,8 +1,8 @@ using System.Text.Json; using XTwitterScraper.Core; -using XTwitterScraper.Models.X.Users; +using XTwitterScraper.Models; -namespace XTwitterScraper.Tests.Models.X.Users; +namespace XTwitterScraper.Tests.Models; public class UserProfileTest : TestBase { diff --git a/src/XTwitterScraper.Tests/Models/Webhooks/WebhookCreateParamsTest.cs b/src/XTwitterScraper.Tests/Models/Webhooks/WebhookCreateParamsTest.cs index 119130a..d7552b3 100644 --- a/src/XTwitterScraper.Tests/Models/Webhooks/WebhookCreateParamsTest.cs +++ b/src/XTwitterScraper.Tests/Models/Webhooks/WebhookCreateParamsTest.cs @@ -13,14 +13,14 @@ public void FieldRoundtrip_Works() { var parameters = new WebhookCreateParams { - EventTypes = [EventType.TweetNew, EventType.FollowerGained], + EventTypes = [EventType.TweetNew, EventType.TweetReply], UrlValue = "https://example.com/webhook", }; List> expectedEventTypes = [ EventType.TweetNew, - EventType.FollowerGained, + EventType.TweetReply, ]; string expectedUrlValue = "https://example.com/webhook"; @@ -37,13 +37,13 @@ public void Url_Works() { WebhookCreateParams parameters = new() { - EventTypes = [EventType.TweetNew, EventType.FollowerGained], + EventTypes = [EventType.TweetNew, EventType.TweetReply], UrlValue = "https://example.com/webhook", }; - var url = parameters.Url(new() { ApiKey = "My API Key", BearerToken = "My Bearer Token" }); + var url = parameters.Url(new() { ApiKey = "My API Key" }); - Assert.Equal(new Uri("https://xquik.com/api/v1/webhooks"), url); + Assert.True(TestBase.UrisEqual(new Uri("https://xquik.com/api/v1/webhooks"), url)); } [Fact] @@ -51,7 +51,7 @@ public void CopyConstructor_Works() { var parameters = new WebhookCreateParams { - EventTypes = [EventType.TweetNew, EventType.FollowerGained], + EventTypes = [EventType.TweetNew, EventType.TweetReply], UrlValue = "https://example.com/webhook", }; diff --git a/src/XTwitterScraper.Tests/Models/Webhooks/WebhookCreateResponseTest.cs b/src/XTwitterScraper.Tests/Models/Webhooks/WebhookCreateResponseTest.cs index 3851f39..08f2acc 100644 --- a/src/XTwitterScraper.Tests/Models/Webhooks/WebhookCreateResponseTest.cs +++ b/src/XTwitterScraper.Tests/Models/Webhooks/WebhookCreateResponseTest.cs @@ -16,7 +16,7 @@ public void FieldRoundtrip_Works() { ID = "42", CreatedAt = DateTimeOffset.Parse("2025-01-15T12:00:00Z"), - EventTypes = [EventType.TweetNew, EventType.FollowerGained], + EventTypes = [EventType.TweetNew, EventType.TweetReply], Secret = "whsec_abc123def456", Url = "https://example.com/webhook", }; @@ -26,7 +26,7 @@ public void FieldRoundtrip_Works() List> expectedEventTypes = [ EventType.TweetNew, - EventType.FollowerGained, + EventType.TweetReply, ]; string expectedSecret = "whsec_abc123def456"; string expectedUrl = "https://example.com/webhook"; @@ -49,7 +49,7 @@ public void SerializationRoundtrip_Works() { ID = "42", CreatedAt = DateTimeOffset.Parse("2025-01-15T12:00:00Z"), - EventTypes = [EventType.TweetNew, EventType.FollowerGained], + EventTypes = [EventType.TweetNew, EventType.TweetReply], Secret = "whsec_abc123def456", Url = "https://example.com/webhook", }; @@ -70,7 +70,7 @@ public void FieldRoundtripThroughSerialization_Works() { ID = "42", CreatedAt = DateTimeOffset.Parse("2025-01-15T12:00:00Z"), - EventTypes = [EventType.TweetNew, EventType.FollowerGained], + EventTypes = [EventType.TweetNew, EventType.TweetReply], Secret = "whsec_abc123def456", Url = "https://example.com/webhook", }; @@ -87,7 +87,7 @@ public void FieldRoundtripThroughSerialization_Works() List> expectedEventTypes = [ EventType.TweetNew, - EventType.FollowerGained, + EventType.TweetReply, ]; string expectedSecret = "whsec_abc123def456"; string expectedUrl = "https://example.com/webhook"; @@ -110,7 +110,7 @@ public void Validation_Works() { ID = "42", CreatedAt = DateTimeOffset.Parse("2025-01-15T12:00:00Z"), - EventTypes = [EventType.TweetNew, EventType.FollowerGained], + EventTypes = [EventType.TweetNew, EventType.TweetReply], Secret = "whsec_abc123def456", Url = "https://example.com/webhook", }; @@ -125,7 +125,7 @@ public void CopyConstructor_Works() { ID = "42", CreatedAt = DateTimeOffset.Parse("2025-01-15T12:00:00Z"), - EventTypes = [EventType.TweetNew, EventType.FollowerGained], + EventTypes = [EventType.TweetNew, EventType.TweetReply], Secret = "whsec_abc123def456", Url = "https://example.com/webhook", }; diff --git a/src/XTwitterScraper.Tests/Models/Webhooks/WebhookDeactivateParamsTest.cs b/src/XTwitterScraper.Tests/Models/Webhooks/WebhookDeactivateParamsTest.cs index ceb6a81..791d9e8 100644 --- a/src/XTwitterScraper.Tests/Models/Webhooks/WebhookDeactivateParamsTest.cs +++ b/src/XTwitterScraper.Tests/Models/Webhooks/WebhookDeactivateParamsTest.cs @@ -20,9 +20,9 @@ public void Url_Works() { WebhookDeactivateParams parameters = new() { ID = "id" }; - var url = parameters.Url(new() { ApiKey = "My API Key", BearerToken = "My Bearer Token" }); + var url = parameters.Url(new() { ApiKey = "My API Key" }); - Assert.Equal(new Uri("https://xquik.com/api/v1/webhooks/id"), url); + Assert.True(TestBase.UrisEqual(new Uri("https://xquik.com/api/v1/webhooks/id"), url)); } [Fact] diff --git a/src/XTwitterScraper.Tests/Models/Webhooks/WebhookListDeliveriesParamsTest.cs b/src/XTwitterScraper.Tests/Models/Webhooks/WebhookListDeliveriesParamsTest.cs index f0d0ecd..4de229f 100644 --- a/src/XTwitterScraper.Tests/Models/Webhooks/WebhookListDeliveriesParamsTest.cs +++ b/src/XTwitterScraper.Tests/Models/Webhooks/WebhookListDeliveriesParamsTest.cs @@ -20,9 +20,11 @@ public void Url_Works() { WebhookListDeliveriesParams parameters = new() { ID = "id" }; - var url = parameters.Url(new() { ApiKey = "My API Key", BearerToken = "My Bearer Token" }); + var url = parameters.Url(new() { ApiKey = "My API Key" }); - Assert.Equal(new Uri("https://xquik.com/api/v1/webhooks/id/deliveries"), url); + Assert.True( + TestBase.UrisEqual(new Uri("https://xquik.com/api/v1/webhooks/id/deliveries"), url) + ); } [Fact] diff --git a/src/XTwitterScraper.Tests/Models/Webhooks/WebhookListResponseTest.cs b/src/XTwitterScraper.Tests/Models/Webhooks/WebhookListResponseTest.cs index b80f6c9..3be9476 100644 --- a/src/XTwitterScraper.Tests/Models/Webhooks/WebhookListResponseTest.cs +++ b/src/XTwitterScraper.Tests/Models/Webhooks/WebhookListResponseTest.cs @@ -20,7 +20,7 @@ public void FieldRoundtrip_Works() { ID = "42", CreatedAt = DateTimeOffset.Parse("2025-01-15T12:00:00Z"), - EventTypes = [EventType.TweetNew, EventType.FollowerGained], + EventTypes = [EventType.TweetNew, EventType.TweetReply], IsActive = true, Url = "https://example.com/webhooks/xquik", }, @@ -33,7 +33,7 @@ public void FieldRoundtrip_Works() { ID = "42", CreatedAt = DateTimeOffset.Parse("2025-01-15T12:00:00Z"), - EventTypes = [EventType.TweetNew, EventType.FollowerGained], + EventTypes = [EventType.TweetNew, EventType.TweetReply], IsActive = true, Url = "https://example.com/webhooks/xquik", }, @@ -57,7 +57,7 @@ public void SerializationRoundtrip_Works() { ID = "42", CreatedAt = DateTimeOffset.Parse("2025-01-15T12:00:00Z"), - EventTypes = [EventType.TweetNew, EventType.FollowerGained], + EventTypes = [EventType.TweetNew, EventType.TweetReply], IsActive = true, Url = "https://example.com/webhooks/xquik", }, @@ -84,7 +84,7 @@ public void FieldRoundtripThroughSerialization_Works() { ID = "42", CreatedAt = DateTimeOffset.Parse("2025-01-15T12:00:00Z"), - EventTypes = [EventType.TweetNew, EventType.FollowerGained], + EventTypes = [EventType.TweetNew, EventType.TweetReply], IsActive = true, Url = "https://example.com/webhooks/xquik", }, @@ -104,7 +104,7 @@ public void FieldRoundtripThroughSerialization_Works() { ID = "42", CreatedAt = DateTimeOffset.Parse("2025-01-15T12:00:00Z"), - EventTypes = [EventType.TweetNew, EventType.FollowerGained], + EventTypes = [EventType.TweetNew, EventType.TweetReply], IsActive = true, Url = "https://example.com/webhooks/xquik", }, @@ -128,7 +128,7 @@ public void Validation_Works() { ID = "42", CreatedAt = DateTimeOffset.Parse("2025-01-15T12:00:00Z"), - EventTypes = [EventType.TweetNew, EventType.FollowerGained], + EventTypes = [EventType.TweetNew, EventType.TweetReply], IsActive = true, Url = "https://example.com/webhooks/xquik", }, @@ -149,7 +149,7 @@ public void CopyConstructor_Works() { ID = "42", CreatedAt = DateTimeOffset.Parse("2025-01-15T12:00:00Z"), - EventTypes = [EventType.TweetNew, EventType.FollowerGained], + EventTypes = [EventType.TweetNew, EventType.TweetReply], IsActive = true, Url = "https://example.com/webhooks/xquik", }, diff --git a/src/XTwitterScraper.Tests/Models/Webhooks/WebhookTest.cs b/src/XTwitterScraper.Tests/Models/Webhooks/WebhookTest.cs index e19b348..4e1754c 100644 --- a/src/XTwitterScraper.Tests/Models/Webhooks/WebhookTest.cs +++ b/src/XTwitterScraper.Tests/Models/Webhooks/WebhookTest.cs @@ -16,7 +16,7 @@ public void FieldRoundtrip_Works() { ID = "42", CreatedAt = DateTimeOffset.Parse("2025-01-15T12:00:00Z"), - EventTypes = [EventType.TweetNew, EventType.FollowerGained], + EventTypes = [EventType.TweetNew, EventType.TweetReply], IsActive = true, Url = "https://example.com/webhooks/xquik", }; @@ -26,7 +26,7 @@ public void FieldRoundtrip_Works() List> expectedEventTypes = [ EventType.TweetNew, - EventType.FollowerGained, + EventType.TweetReply, ]; bool expectedIsActive = true; string expectedUrl = "https://example.com/webhooks/xquik"; @@ -49,7 +49,7 @@ public void SerializationRoundtrip_Works() { ID = "42", CreatedAt = DateTimeOffset.Parse("2025-01-15T12:00:00Z"), - EventTypes = [EventType.TweetNew, EventType.FollowerGained], + EventTypes = [EventType.TweetNew, EventType.TweetReply], IsActive = true, Url = "https://example.com/webhooks/xquik", }; @@ -67,7 +67,7 @@ public void FieldRoundtripThroughSerialization_Works() { ID = "42", CreatedAt = DateTimeOffset.Parse("2025-01-15T12:00:00Z"), - EventTypes = [EventType.TweetNew, EventType.FollowerGained], + EventTypes = [EventType.TweetNew, EventType.TweetReply], IsActive = true, Url = "https://example.com/webhooks/xquik", }; @@ -84,7 +84,7 @@ public void FieldRoundtripThroughSerialization_Works() List> expectedEventTypes = [ EventType.TweetNew, - EventType.FollowerGained, + EventType.TweetReply, ]; bool expectedIsActive = true; string expectedUrl = "https://example.com/webhooks/xquik"; @@ -107,7 +107,7 @@ public void Validation_Works() { ID = "42", CreatedAt = DateTimeOffset.Parse("2025-01-15T12:00:00Z"), - EventTypes = [EventType.TweetNew, EventType.FollowerGained], + EventTypes = [EventType.TweetNew, EventType.TweetReply], IsActive = true, Url = "https://example.com/webhooks/xquik", }; @@ -122,7 +122,7 @@ public void CopyConstructor_Works() { ID = "42", CreatedAt = DateTimeOffset.Parse("2025-01-15T12:00:00Z"), - EventTypes = [EventType.TweetNew, EventType.FollowerGained], + EventTypes = [EventType.TweetNew, EventType.TweetReply], IsActive = true, Url = "https://example.com/webhooks/xquik", }; diff --git a/src/XTwitterScraper.Tests/Models/Webhooks/WebhookTestParamsTest.cs b/src/XTwitterScraper.Tests/Models/Webhooks/WebhookTestParamsTest.cs index 242ec6f..af07faa 100644 --- a/src/XTwitterScraper.Tests/Models/Webhooks/WebhookTestParamsTest.cs +++ b/src/XTwitterScraper.Tests/Models/Webhooks/WebhookTestParamsTest.cs @@ -20,9 +20,9 @@ public void Url_Works() { WebhookTestParams parameters = new() { ID = "id" }; - var url = parameters.Url(new() { ApiKey = "My API Key", BearerToken = "My Bearer Token" }); + var url = parameters.Url(new() { ApiKey = "My API Key" }); - Assert.Equal(new Uri("https://xquik.com/api/v1/webhooks/id/test"), url); + Assert.True(TestBase.UrisEqual(new Uri("https://xquik.com/api/v1/webhooks/id/test"), url)); } [Fact] diff --git a/src/XTwitterScraper.Tests/Models/Webhooks/WebhookUpdateParamsTest.cs b/src/XTwitterScraper.Tests/Models/Webhooks/WebhookUpdateParamsTest.cs index 6d60546..fbf866e 100644 --- a/src/XTwitterScraper.Tests/Models/Webhooks/WebhookUpdateParamsTest.cs +++ b/src/XTwitterScraper.Tests/Models/Webhooks/WebhookUpdateParamsTest.cs @@ -74,9 +74,9 @@ public void Url_Works() { WebhookUpdateParams parameters = new() { ID = "id" }; - var url = parameters.Url(new() { ApiKey = "My API Key", BearerToken = "My Bearer Token" }); + var url = parameters.Url(new() { ApiKey = "My API Key" }); - Assert.Equal(new Uri("https://xquik.com/api/v1/webhooks/id"), url); + Assert.True(TestBase.UrisEqual(new Uri("https://xquik.com/api/v1/webhooks/id"), url)); } [Fact] diff --git a/src/XTwitterScraper.Tests/Models/X/Accounts/AccountCreateParamsTest.cs b/src/XTwitterScraper.Tests/Models/X/Accounts/AccountCreateParamsTest.cs index 0b9e48d..5d5001d 100644 --- a/src/XTwitterScraper.Tests/Models/X/Accounts/AccountCreateParamsTest.cs +++ b/src/XTwitterScraper.Tests/Models/X/Accounts/AccountCreateParamsTest.cs @@ -76,9 +76,9 @@ public void Url_Works() Username = "elonmusk", }; - var url = parameters.Url(new() { ApiKey = "My API Key", BearerToken = "My Bearer Token" }); + var url = parameters.Url(new() { ApiKey = "My API Key" }); - Assert.Equal(new Uri("https://xquik.com/api/v1/x/accounts"), url); + Assert.True(TestBase.UrisEqual(new Uri("https://xquik.com/api/v1/x/accounts"), url)); } [Fact] diff --git a/src/XTwitterScraper.Tests/Models/X/Accounts/AccountCreateResponseTest.cs b/src/XTwitterScraper.Tests/Models/X/Accounts/AccountCreateResponseTest.cs index 8fdc7ca..0bc5838 100644 --- a/src/XTwitterScraper.Tests/Models/X/Accounts/AccountCreateResponseTest.cs +++ b/src/XTwitterScraper.Tests/Models/X/Accounts/AccountCreateResponseTest.cs @@ -1,5 +1,7 @@ +using System; using System.Text.Json; using XTwitterScraper.Core; +using XTwitterScraper.Exceptions; using XTwitterScraper.Models.X.Accounts; namespace XTwitterScraper.Tests.Models.X.Accounts; @@ -12,20 +14,30 @@ public void FieldRoundtrip_Works() var model = new AccountCreateResponse { ID = "42", + CreatedAt = DateTimeOffset.Parse("2025-01-15T12:00:00Z"), + Health = AccountCreateResponseHealth.Healthy, Status = "active", XUserID = "9876543210", XUsername = "elonmusk", + LoginCountry = "US", }; string expectedID = "42"; + DateTimeOffset expectedCreatedAt = DateTimeOffset.Parse("2025-01-15T12:00:00Z"); + ApiEnum expectedHealth = + AccountCreateResponseHealth.Healthy; string expectedStatus = "active"; string expectedXUserID = "9876543210"; string expectedXUsername = "elonmusk"; + string expectedLoginCountry = "US"; Assert.Equal(expectedID, model.ID); + Assert.Equal(expectedCreatedAt, model.CreatedAt); + Assert.Equal(expectedHealth, model.Health); Assert.Equal(expectedStatus, model.Status); Assert.Equal(expectedXUserID, model.XUserID); Assert.Equal(expectedXUsername, model.XUsername); + Assert.Equal(expectedLoginCountry, model.LoginCountry); } [Fact] @@ -34,9 +46,12 @@ public void SerializationRoundtrip_Works() var model = new AccountCreateResponse { ID = "42", + CreatedAt = DateTimeOffset.Parse("2025-01-15T12:00:00Z"), + Health = AccountCreateResponseHealth.Healthy, Status = "active", XUserID = "9876543210", XUsername = "elonmusk", + LoginCountry = "US", }; string json = JsonSerializer.Serialize(model, ModelBase.SerializerOptions); @@ -54,9 +69,12 @@ public void FieldRoundtripThroughSerialization_Works() var model = new AccountCreateResponse { ID = "42", + CreatedAt = DateTimeOffset.Parse("2025-01-15T12:00:00Z"), + Health = AccountCreateResponseHealth.Healthy, Status = "active", XUserID = "9876543210", XUsername = "elonmusk", + LoginCountry = "US", }; string element = JsonSerializer.Serialize(model, ModelBase.SerializerOptions); @@ -67,14 +85,21 @@ public void FieldRoundtripThroughSerialization_Works() Assert.NotNull(deserialized); string expectedID = "42"; + DateTimeOffset expectedCreatedAt = DateTimeOffset.Parse("2025-01-15T12:00:00Z"); + ApiEnum expectedHealth = + AccountCreateResponseHealth.Healthy; string expectedStatus = "active"; string expectedXUserID = "9876543210"; string expectedXUsername = "elonmusk"; + string expectedLoginCountry = "US"; Assert.Equal(expectedID, deserialized.ID); + Assert.Equal(expectedCreatedAt, deserialized.CreatedAt); + Assert.Equal(expectedHealth, deserialized.Health); Assert.Equal(expectedStatus, deserialized.Status); Assert.Equal(expectedXUserID, deserialized.XUserID); Assert.Equal(expectedXUsername, deserialized.XUsername); + Assert.Equal(expectedLoginCountry, deserialized.LoginCountry); } [Fact] @@ -83,9 +108,84 @@ public void Validation_Works() var model = new AccountCreateResponse { ID = "42", + CreatedAt = DateTimeOffset.Parse("2025-01-15T12:00:00Z"), + Health = AccountCreateResponseHealth.Healthy, Status = "active", XUserID = "9876543210", XUsername = "elonmusk", + LoginCountry = "US", + }; + + model.Validate(); + } + + [Fact] + public void OptionalNonNullablePropertiesUnsetAreNotSet_Works() + { + var model = new AccountCreateResponse + { + ID = "42", + CreatedAt = DateTimeOffset.Parse("2025-01-15T12:00:00Z"), + Health = AccountCreateResponseHealth.Healthy, + Status = "active", + XUserID = "9876543210", + XUsername = "elonmusk", + }; + + Assert.Null(model.LoginCountry); + Assert.False(model.RawData.ContainsKey("loginCountry")); + } + + [Fact] + public void OptionalNonNullablePropertiesUnsetValidation_Works() + { + var model = new AccountCreateResponse + { + ID = "42", + CreatedAt = DateTimeOffset.Parse("2025-01-15T12:00:00Z"), + Health = AccountCreateResponseHealth.Healthy, + Status = "active", + XUserID = "9876543210", + XUsername = "elonmusk", + }; + + model.Validate(); + } + + [Fact] + public void OptionalNonNullablePropertiesSetToNullAreNotSet_Works() + { + var model = new AccountCreateResponse + { + ID = "42", + CreatedAt = DateTimeOffset.Parse("2025-01-15T12:00:00Z"), + Health = AccountCreateResponseHealth.Healthy, + Status = "active", + XUserID = "9876543210", + XUsername = "elonmusk", + + // Null should be interpreted as omitted for these properties + LoginCountry = null, + }; + + Assert.Null(model.LoginCountry); + Assert.False(model.RawData.ContainsKey("loginCountry")); + } + + [Fact] + public void OptionalNonNullablePropertiesSetToNullValidation_Works() + { + var model = new AccountCreateResponse + { + ID = "42", + CreatedAt = DateTimeOffset.Parse("2025-01-15T12:00:00Z"), + Health = AccountCreateResponseHealth.Healthy, + Status = "active", + XUserID = "9876543210", + XUsername = "elonmusk", + + // Null should be interpreted as omitted for these properties + LoginCountry = null, }; model.Validate(); @@ -97,9 +197,12 @@ public void CopyConstructor_Works() var model = new AccountCreateResponse { ID = "42", + CreatedAt = DateTimeOffset.Parse("2025-01-15T12:00:00Z"), + Health = AccountCreateResponseHealth.Healthy, Status = "active", XUserID = "9876543210", XUsername = "elonmusk", + LoginCountry = "US", }; AccountCreateResponse copied = new(model); @@ -107,3 +210,69 @@ public void CopyConstructor_Works() Assert.Equal(model, copied); } } + +public class AccountCreateResponseHealthTest : TestBase +{ + [Theory] + [InlineData(AccountCreateResponseHealth.Healthy)] + [InlineData(AccountCreateResponseHealth.Locked)] + [InlineData(AccountCreateResponseHealth.NeedsReauth)] + [InlineData(AccountCreateResponseHealth.Recovering)] + [InlineData(AccountCreateResponseHealth.Suspended)] + [InlineData(AccountCreateResponseHealth.TemporaryIssue)] + public void Validation_Works(AccountCreateResponseHealth rawValue) + { + // force implicit conversion because Theory can't do that for us + ApiEnum value = rawValue; + value.Validate(); + } + + [Fact] + public void InvalidEnumValidationThrows_Works() + { + var value = JsonSerializer.Deserialize>( + JsonSerializer.SerializeToElement("invalid value"), + ModelBase.SerializerOptions + ); + + Assert.NotNull(value); + Assert.Throws(() => value.Validate()); + } + + [Theory] + [InlineData(AccountCreateResponseHealth.Healthy)] + [InlineData(AccountCreateResponseHealth.Locked)] + [InlineData(AccountCreateResponseHealth.NeedsReauth)] + [InlineData(AccountCreateResponseHealth.Recovering)] + [InlineData(AccountCreateResponseHealth.Suspended)] + [InlineData(AccountCreateResponseHealth.TemporaryIssue)] + public void SerializationRoundtrip_Works(AccountCreateResponseHealth rawValue) + { + // force implicit conversion because Theory can't do that for us + ApiEnum value = rawValue; + + string json = JsonSerializer.Serialize(value, ModelBase.SerializerOptions); + var deserialized = JsonSerializer.Deserialize>( + json, + ModelBase.SerializerOptions + ); + + Assert.Equal(value, deserialized); + } + + [Fact] + public void InvalidEnumSerializationRoundtrip_Works() + { + var value = JsonSerializer.Deserialize>( + JsonSerializer.SerializeToElement("invalid value"), + ModelBase.SerializerOptions + ); + string json = JsonSerializer.Serialize(value, ModelBase.SerializerOptions); + var deserialized = JsonSerializer.Deserialize>( + json, + ModelBase.SerializerOptions + ); + + Assert.Equal(value, deserialized); + } +} diff --git a/src/XTwitterScraper.Tests/Models/X/Accounts/AccountDeleteParamsTest.cs b/src/XTwitterScraper.Tests/Models/X/Accounts/AccountDeleteParamsTest.cs index 1df3f2d..c18d3ce 100644 --- a/src/XTwitterScraper.Tests/Models/X/Accounts/AccountDeleteParamsTest.cs +++ b/src/XTwitterScraper.Tests/Models/X/Accounts/AccountDeleteParamsTest.cs @@ -20,9 +20,9 @@ public void Url_Works() { AccountDeleteParams parameters = new() { ID = "id" }; - var url = parameters.Url(new() { ApiKey = "My API Key", BearerToken = "My Bearer Token" }); + var url = parameters.Url(new() { ApiKey = "My API Key" }); - Assert.Equal(new Uri("https://xquik.com/api/v1/x/accounts/id"), url); + Assert.True(TestBase.UrisEqual(new Uri("https://xquik.com/api/v1/x/accounts/id"), url)); } [Fact] diff --git a/src/XTwitterScraper.Tests/Models/X/Accounts/AccountListResponseTest.cs b/src/XTwitterScraper.Tests/Models/X/Accounts/AccountListResponseTest.cs index 845aa93..d6a4874 100644 --- a/src/XTwitterScraper.Tests/Models/X/Accounts/AccountListResponseTest.cs +++ b/src/XTwitterScraper.Tests/Models/X/Accounts/AccountListResponseTest.cs @@ -19,6 +19,7 @@ public void FieldRoundtrip_Works() { ID = "42", CreatedAt = DateTimeOffset.Parse("2025-01-15T12:00:00Z"), + Health = Health.Healthy, Status = "active", XUserID = "9876543210", XUsername = "elonmusk", @@ -32,6 +33,7 @@ public void FieldRoundtrip_Works() { ID = "42", CreatedAt = DateTimeOffset.Parse("2025-01-15T12:00:00Z"), + Health = Health.Healthy, Status = "active", XUserID = "9876543210", XUsername = "elonmusk", @@ -56,6 +58,7 @@ public void SerializationRoundtrip_Works() { ID = "42", CreatedAt = DateTimeOffset.Parse("2025-01-15T12:00:00Z"), + Health = Health.Healthy, Status = "active", XUserID = "9876543210", XUsername = "elonmusk", @@ -83,6 +86,7 @@ public void FieldRoundtripThroughSerialization_Works() { ID = "42", CreatedAt = DateTimeOffset.Parse("2025-01-15T12:00:00Z"), + Health = Health.Healthy, Status = "active", XUserID = "9876543210", XUsername = "elonmusk", @@ -103,6 +107,7 @@ public void FieldRoundtripThroughSerialization_Works() { ID = "42", CreatedAt = DateTimeOffset.Parse("2025-01-15T12:00:00Z"), + Health = Health.Healthy, Status = "active", XUserID = "9876543210", XUsername = "elonmusk", @@ -127,6 +132,7 @@ public void Validation_Works() { ID = "42", CreatedAt = DateTimeOffset.Parse("2025-01-15T12:00:00Z"), + Health = Health.Healthy, Status = "active", XUserID = "9876543210", XUsername = "elonmusk", @@ -148,6 +154,7 @@ public void CopyConstructor_Works() { ID = "42", CreatedAt = DateTimeOffset.Parse("2025-01-15T12:00:00Z"), + Health = Health.Healthy, Status = "active", XUserID = "9876543210", XUsername = "elonmusk", diff --git a/src/XTwitterScraper.Tests/Models/X/Accounts/AccountReauthParamsTest.cs b/src/XTwitterScraper.Tests/Models/X/Accounts/AccountReauthParamsTest.cs index f03a8ce..4996041 100644 --- a/src/XTwitterScraper.Tests/Models/X/Accounts/AccountReauthParamsTest.cs +++ b/src/XTwitterScraper.Tests/Models/X/Accounts/AccountReauthParamsTest.cs @@ -12,15 +12,21 @@ public void FieldRoundtrip_Works() { ID = "id", Password = "password_value", + Email = "user@example.com", + ProxyCountry = "US", TotpSecret = "totp_secret_value", }; string expectedID = "id"; string expectedPassword = "password_value"; + string expectedEmail = "user@example.com"; + string expectedProxyCountry = "US"; string expectedTotpSecret = "totp_secret_value"; Assert.Equal(expectedID, parameters.ID); Assert.Equal(expectedPassword, parameters.Password); + Assert.Equal(expectedEmail, parameters.Email); + Assert.Equal(expectedProxyCountry, parameters.ProxyCountry); Assert.Equal(expectedTotpSecret, parameters.TotpSecret); } @@ -29,6 +35,10 @@ public void OptionalNonNullableParamsUnsetAreNotSet_Works() { var parameters = new AccountReauthParams { ID = "id", Password = "password_value" }; + Assert.Null(parameters.Email); + Assert.False(parameters.RawBodyData.ContainsKey("email")); + Assert.Null(parameters.ProxyCountry); + Assert.False(parameters.RawBodyData.ContainsKey("proxy_country")); Assert.Null(parameters.TotpSecret); Assert.False(parameters.RawBodyData.ContainsKey("totp_secret")); } @@ -42,9 +52,15 @@ public void OptionalNonNullableParamsSetToNullAreNotSet_Works() Password = "password_value", // Null should be interpreted as omitted for these properties + Email = null, + ProxyCountry = null, TotpSecret = null, }; + Assert.Null(parameters.Email); + Assert.False(parameters.RawBodyData.ContainsKey("email")); + Assert.Null(parameters.ProxyCountry); + Assert.False(parameters.RawBodyData.ContainsKey("proxy_country")); Assert.Null(parameters.TotpSecret); Assert.False(parameters.RawBodyData.ContainsKey("totp_secret")); } @@ -54,9 +70,11 @@ public void Url_Works() { AccountReauthParams parameters = new() { ID = "id", Password = "password_value" }; - var url = parameters.Url(new() { ApiKey = "My API Key", BearerToken = "My Bearer Token" }); + var url = parameters.Url(new() { ApiKey = "My API Key" }); - Assert.Equal(new Uri("https://xquik.com/api/v1/x/accounts/id/reauth"), url); + Assert.True( + TestBase.UrisEqual(new Uri("https://xquik.com/api/v1/x/accounts/id/reauth"), url) + ); } [Fact] @@ -66,6 +84,8 @@ public void CopyConstructor_Works() { ID = "id", Password = "password_value", + Email = "user@example.com", + ProxyCountry = "US", TotpSecret = "totp_secret_value", }; diff --git a/src/XTwitterScraper.Tests/Models/X/Accounts/AccountReauthResponseTest.cs b/src/XTwitterScraper.Tests/Models/X/Accounts/AccountReauthResponseTest.cs index b201109..00f19c0 100644 --- a/src/XTwitterScraper.Tests/Models/X/Accounts/AccountReauthResponseTest.cs +++ b/src/XTwitterScraper.Tests/Models/X/Accounts/AccountReauthResponseTest.cs @@ -1,5 +1,7 @@ +using System; using System.Text.Json; using XTwitterScraper.Core; +using XTwitterScraper.Exceptions; using XTwitterScraper.Models.X.Accounts; namespace XTwitterScraper.Tests.Models.X.Accounts; @@ -12,17 +14,30 @@ public void FieldRoundtrip_Works() var model = new AccountReauthResponse { ID = "42", + CreatedAt = DateTimeOffset.Parse("2025-01-15T12:00:00Z"), + Health = AccountReauthResponseHealth.Healthy, Status = "active", + XUserID = "9876543210", XUsername = "elonmusk", + LoginCountry = "US", }; string expectedID = "42"; + DateTimeOffset expectedCreatedAt = DateTimeOffset.Parse("2025-01-15T12:00:00Z"); + ApiEnum expectedHealth = + AccountReauthResponseHealth.Healthy; string expectedStatus = "active"; + string expectedXUserID = "9876543210"; string expectedXUsername = "elonmusk"; + string expectedLoginCountry = "US"; Assert.Equal(expectedID, model.ID); + Assert.Equal(expectedCreatedAt, model.CreatedAt); + Assert.Equal(expectedHealth, model.Health); Assert.Equal(expectedStatus, model.Status); + Assert.Equal(expectedXUserID, model.XUserID); Assert.Equal(expectedXUsername, model.XUsername); + Assert.Equal(expectedLoginCountry, model.LoginCountry); } [Fact] @@ -31,8 +46,12 @@ public void SerializationRoundtrip_Works() var model = new AccountReauthResponse { ID = "42", + CreatedAt = DateTimeOffset.Parse("2025-01-15T12:00:00Z"), + Health = AccountReauthResponseHealth.Healthy, Status = "active", + XUserID = "9876543210", XUsername = "elonmusk", + LoginCountry = "US", }; string json = JsonSerializer.Serialize(model, ModelBase.SerializerOptions); @@ -50,8 +69,12 @@ public void FieldRoundtripThroughSerialization_Works() var model = new AccountReauthResponse { ID = "42", + CreatedAt = DateTimeOffset.Parse("2025-01-15T12:00:00Z"), + Health = AccountReauthResponseHealth.Healthy, Status = "active", + XUserID = "9876543210", XUsername = "elonmusk", + LoginCountry = "US", }; string element = JsonSerializer.Serialize(model, ModelBase.SerializerOptions); @@ -62,12 +85,21 @@ public void FieldRoundtripThroughSerialization_Works() Assert.NotNull(deserialized); string expectedID = "42"; + DateTimeOffset expectedCreatedAt = DateTimeOffset.Parse("2025-01-15T12:00:00Z"); + ApiEnum expectedHealth = + AccountReauthResponseHealth.Healthy; string expectedStatus = "active"; + string expectedXUserID = "9876543210"; string expectedXUsername = "elonmusk"; + string expectedLoginCountry = "US"; Assert.Equal(expectedID, deserialized.ID); + Assert.Equal(expectedCreatedAt, deserialized.CreatedAt); + Assert.Equal(expectedHealth, deserialized.Health); Assert.Equal(expectedStatus, deserialized.Status); + Assert.Equal(expectedXUserID, deserialized.XUserID); Assert.Equal(expectedXUsername, deserialized.XUsername); + Assert.Equal(expectedLoginCountry, deserialized.LoginCountry); } [Fact] @@ -76,8 +108,84 @@ public void Validation_Works() var model = new AccountReauthResponse { ID = "42", + CreatedAt = DateTimeOffset.Parse("2025-01-15T12:00:00Z"), + Health = AccountReauthResponseHealth.Healthy, Status = "active", + XUserID = "9876543210", XUsername = "elonmusk", + LoginCountry = "US", + }; + + model.Validate(); + } + + [Fact] + public void OptionalNonNullablePropertiesUnsetAreNotSet_Works() + { + var model = new AccountReauthResponse + { + ID = "42", + CreatedAt = DateTimeOffset.Parse("2025-01-15T12:00:00Z"), + Health = AccountReauthResponseHealth.Healthy, + Status = "active", + XUserID = "9876543210", + XUsername = "elonmusk", + }; + + Assert.Null(model.LoginCountry); + Assert.False(model.RawData.ContainsKey("loginCountry")); + } + + [Fact] + public void OptionalNonNullablePropertiesUnsetValidation_Works() + { + var model = new AccountReauthResponse + { + ID = "42", + CreatedAt = DateTimeOffset.Parse("2025-01-15T12:00:00Z"), + Health = AccountReauthResponseHealth.Healthy, + Status = "active", + XUserID = "9876543210", + XUsername = "elonmusk", + }; + + model.Validate(); + } + + [Fact] + public void OptionalNonNullablePropertiesSetToNullAreNotSet_Works() + { + var model = new AccountReauthResponse + { + ID = "42", + CreatedAt = DateTimeOffset.Parse("2025-01-15T12:00:00Z"), + Health = AccountReauthResponseHealth.Healthy, + Status = "active", + XUserID = "9876543210", + XUsername = "elonmusk", + + // Null should be interpreted as omitted for these properties + LoginCountry = null, + }; + + Assert.Null(model.LoginCountry); + Assert.False(model.RawData.ContainsKey("loginCountry")); + } + + [Fact] + public void OptionalNonNullablePropertiesSetToNullValidation_Works() + { + var model = new AccountReauthResponse + { + ID = "42", + CreatedAt = DateTimeOffset.Parse("2025-01-15T12:00:00Z"), + Health = AccountReauthResponseHealth.Healthy, + Status = "active", + XUserID = "9876543210", + XUsername = "elonmusk", + + // Null should be interpreted as omitted for these properties + LoginCountry = null, }; model.Validate(); @@ -89,8 +197,12 @@ public void CopyConstructor_Works() var model = new AccountReauthResponse { ID = "42", + CreatedAt = DateTimeOffset.Parse("2025-01-15T12:00:00Z"), + Health = AccountReauthResponseHealth.Healthy, Status = "active", + XUserID = "9876543210", XUsername = "elonmusk", + LoginCountry = "US", }; AccountReauthResponse copied = new(model); @@ -98,3 +210,69 @@ public void CopyConstructor_Works() Assert.Equal(model, copied); } } + +public class AccountReauthResponseHealthTest : TestBase +{ + [Theory] + [InlineData(AccountReauthResponseHealth.Healthy)] + [InlineData(AccountReauthResponseHealth.Locked)] + [InlineData(AccountReauthResponseHealth.NeedsReauth)] + [InlineData(AccountReauthResponseHealth.Recovering)] + [InlineData(AccountReauthResponseHealth.Suspended)] + [InlineData(AccountReauthResponseHealth.TemporaryIssue)] + public void Validation_Works(AccountReauthResponseHealth rawValue) + { + // force implicit conversion because Theory can't do that for us + ApiEnum value = rawValue; + value.Validate(); + } + + [Fact] + public void InvalidEnumValidationThrows_Works() + { + var value = JsonSerializer.Deserialize>( + JsonSerializer.SerializeToElement("invalid value"), + ModelBase.SerializerOptions + ); + + Assert.NotNull(value); + Assert.Throws(() => value.Validate()); + } + + [Theory] + [InlineData(AccountReauthResponseHealth.Healthy)] + [InlineData(AccountReauthResponseHealth.Locked)] + [InlineData(AccountReauthResponseHealth.NeedsReauth)] + [InlineData(AccountReauthResponseHealth.Recovering)] + [InlineData(AccountReauthResponseHealth.Suspended)] + [InlineData(AccountReauthResponseHealth.TemporaryIssue)] + public void SerializationRoundtrip_Works(AccountReauthResponseHealth rawValue) + { + // force implicit conversion because Theory can't do that for us + ApiEnum value = rawValue; + + string json = JsonSerializer.Serialize(value, ModelBase.SerializerOptions); + var deserialized = JsonSerializer.Deserialize>( + json, + ModelBase.SerializerOptions + ); + + Assert.Equal(value, deserialized); + } + + [Fact] + public void InvalidEnumSerializationRoundtrip_Works() + { + var value = JsonSerializer.Deserialize>( + JsonSerializer.SerializeToElement("invalid value"), + ModelBase.SerializerOptions + ); + string json = JsonSerializer.Serialize(value, ModelBase.SerializerOptions); + var deserialized = JsonSerializer.Deserialize>( + json, + ModelBase.SerializerOptions + ); + + Assert.Equal(value, deserialized); + } +} diff --git a/src/XTwitterScraper.Tests/Models/X/Accounts/AccountRetrieveParamsTest.cs b/src/XTwitterScraper.Tests/Models/X/Accounts/AccountRetrieveParamsTest.cs index 81a3379..79c210e 100644 --- a/src/XTwitterScraper.Tests/Models/X/Accounts/AccountRetrieveParamsTest.cs +++ b/src/XTwitterScraper.Tests/Models/X/Accounts/AccountRetrieveParamsTest.cs @@ -20,9 +20,9 @@ public void Url_Works() { AccountRetrieveParams parameters = new() { ID = "id" }; - var url = parameters.Url(new() { ApiKey = "My API Key", BearerToken = "My Bearer Token" }); + var url = parameters.Url(new() { ApiKey = "My API Key" }); - Assert.Equal(new Uri("https://xquik.com/api/v1/x/accounts/id"), url); + Assert.True(TestBase.UrisEqual(new Uri("https://xquik.com/api/v1/x/accounts/id"), url)); } [Fact] diff --git a/src/XTwitterScraper.Tests/Models/X/Accounts/XAccountDetailTest.cs b/src/XTwitterScraper.Tests/Models/X/Accounts/XAccountDetailTest.cs index 29f0d62..86225d9 100644 --- a/src/XTwitterScraper.Tests/Models/X/Accounts/XAccountDetailTest.cs +++ b/src/XTwitterScraper.Tests/Models/X/Accounts/XAccountDetailTest.cs @@ -1,6 +1,7 @@ using System; using System.Text.Json; using XTwitterScraper.Core; +using XTwitterScraper.Exceptions; using XTwitterScraper.Models.X.Accounts; namespace XTwitterScraper.Tests.Models.X.Accounts; @@ -14,6 +15,7 @@ public void FieldRoundtrip_Works() { ID = "42", CreatedAt = DateTimeOffset.Parse("2025-01-15T12:00:00Z"), + Health = XAccountDetailHealth.Healthy, Status = "active", XUserID = "9876543210", XUsername = "elonmusk", @@ -24,6 +26,7 @@ public void FieldRoundtrip_Works() string expectedID = "42"; DateTimeOffset expectedCreatedAt = DateTimeOffset.Parse("2025-01-15T12:00:00Z"); + ApiEnum expectedHealth = XAccountDetailHealth.Healthy; string expectedStatus = "active"; string expectedXUserID = "9876543210"; string expectedXUsername = "elonmusk"; @@ -33,6 +36,7 @@ public void FieldRoundtrip_Works() Assert.Equal(expectedID, model.ID); Assert.Equal(expectedCreatedAt, model.CreatedAt); + Assert.Equal(expectedHealth, model.Health); Assert.Equal(expectedStatus, model.Status); Assert.Equal(expectedXUserID, model.XUserID); Assert.Equal(expectedXUsername, model.XUsername); @@ -48,6 +52,7 @@ public void SerializationRoundtrip_Works() { ID = "42", CreatedAt = DateTimeOffset.Parse("2025-01-15T12:00:00Z"), + Health = XAccountDetailHealth.Healthy, Status = "active", XUserID = "9876543210", XUsername = "elonmusk", @@ -72,6 +77,7 @@ public void FieldRoundtripThroughSerialization_Works() { ID = "42", CreatedAt = DateTimeOffset.Parse("2025-01-15T12:00:00Z"), + Health = XAccountDetailHealth.Healthy, Status = "active", XUserID = "9876543210", XUsername = "elonmusk", @@ -89,6 +95,7 @@ public void FieldRoundtripThroughSerialization_Works() string expectedID = "42"; DateTimeOffset expectedCreatedAt = DateTimeOffset.Parse("2025-01-15T12:00:00Z"); + ApiEnum expectedHealth = XAccountDetailHealth.Healthy; string expectedStatus = "active"; string expectedXUserID = "9876543210"; string expectedXUsername = "elonmusk"; @@ -98,6 +105,7 @@ public void FieldRoundtripThroughSerialization_Works() Assert.Equal(expectedID, deserialized.ID); Assert.Equal(expectedCreatedAt, deserialized.CreatedAt); + Assert.Equal(expectedHealth, deserialized.Health); Assert.Equal(expectedStatus, deserialized.Status); Assert.Equal(expectedXUserID, deserialized.XUserID); Assert.Equal(expectedXUsername, deserialized.XUsername); @@ -113,6 +121,7 @@ public void Validation_Works() { ID = "42", CreatedAt = DateTimeOffset.Parse("2025-01-15T12:00:00Z"), + Health = XAccountDetailHealth.Healthy, Status = "active", XUserID = "9876543210", XUsername = "elonmusk", @@ -131,6 +140,7 @@ public void OptionalNonNullablePropertiesUnsetAreNotSet_Works() { ID = "42", CreatedAt = DateTimeOffset.Parse("2025-01-15T12:00:00Z"), + Health = XAccountDetailHealth.Healthy, Status = "active", XUserID = "9876543210", XUsername = "elonmusk", @@ -151,6 +161,7 @@ public void OptionalNonNullablePropertiesUnsetValidation_Works() { ID = "42", CreatedAt = DateTimeOffset.Parse("2025-01-15T12:00:00Z"), + Health = XAccountDetailHealth.Healthy, Status = "active", XUserID = "9876543210", XUsername = "elonmusk", @@ -166,6 +177,7 @@ public void OptionalNonNullablePropertiesSetToNullAreNotSet_Works() { ID = "42", CreatedAt = DateTimeOffset.Parse("2025-01-15T12:00:00Z"), + Health = XAccountDetailHealth.Healthy, Status = "active", XUserID = "9876543210", XUsername = "elonmusk", @@ -191,6 +203,7 @@ public void OptionalNonNullablePropertiesSetToNullValidation_Works() { ID = "42", CreatedAt = DateTimeOffset.Parse("2025-01-15T12:00:00Z"), + Health = XAccountDetailHealth.Healthy, Status = "active", XUserID = "9876543210", XUsername = "elonmusk", @@ -211,6 +224,7 @@ public void CopyConstructor_Works() { ID = "42", CreatedAt = DateTimeOffset.Parse("2025-01-15T12:00:00Z"), + Health = XAccountDetailHealth.Healthy, Status = "active", XUserID = "9876543210", XUsername = "elonmusk", @@ -224,3 +238,69 @@ public void CopyConstructor_Works() Assert.Equal(model, copied); } } + +public class XAccountDetailHealthTest : TestBase +{ + [Theory] + [InlineData(XAccountDetailHealth.Healthy)] + [InlineData(XAccountDetailHealth.Locked)] + [InlineData(XAccountDetailHealth.NeedsReauth)] + [InlineData(XAccountDetailHealth.Recovering)] + [InlineData(XAccountDetailHealth.Suspended)] + [InlineData(XAccountDetailHealth.TemporaryIssue)] + public void Validation_Works(XAccountDetailHealth rawValue) + { + // force implicit conversion because Theory can't do that for us + ApiEnum value = rawValue; + value.Validate(); + } + + [Fact] + public void InvalidEnumValidationThrows_Works() + { + var value = JsonSerializer.Deserialize>( + JsonSerializer.SerializeToElement("invalid value"), + ModelBase.SerializerOptions + ); + + Assert.NotNull(value); + Assert.Throws(() => value.Validate()); + } + + [Theory] + [InlineData(XAccountDetailHealth.Healthy)] + [InlineData(XAccountDetailHealth.Locked)] + [InlineData(XAccountDetailHealth.NeedsReauth)] + [InlineData(XAccountDetailHealth.Recovering)] + [InlineData(XAccountDetailHealth.Suspended)] + [InlineData(XAccountDetailHealth.TemporaryIssue)] + public void SerializationRoundtrip_Works(XAccountDetailHealth rawValue) + { + // force implicit conversion because Theory can't do that for us + ApiEnum value = rawValue; + + string json = JsonSerializer.Serialize(value, ModelBase.SerializerOptions); + var deserialized = JsonSerializer.Deserialize>( + json, + ModelBase.SerializerOptions + ); + + Assert.Equal(value, deserialized); + } + + [Fact] + public void InvalidEnumSerializationRoundtrip_Works() + { + var value = JsonSerializer.Deserialize>( + JsonSerializer.SerializeToElement("invalid value"), + ModelBase.SerializerOptions + ); + string json = JsonSerializer.Serialize(value, ModelBase.SerializerOptions); + var deserialized = JsonSerializer.Deserialize>( + json, + ModelBase.SerializerOptions + ); + + Assert.Equal(value, deserialized); + } +} diff --git a/src/XTwitterScraper.Tests/Models/X/Accounts/XAccountTest.cs b/src/XTwitterScraper.Tests/Models/X/Accounts/XAccountTest.cs index e10286f..96d1ebf 100644 --- a/src/XTwitterScraper.Tests/Models/X/Accounts/XAccountTest.cs +++ b/src/XTwitterScraper.Tests/Models/X/Accounts/XAccountTest.cs @@ -1,6 +1,7 @@ using System; using System.Text.Json; using XTwitterScraper.Core; +using XTwitterScraper.Exceptions; using XTwitterScraper.Models.X.Accounts; namespace XTwitterScraper.Tests.Models.X.Accounts; @@ -14,6 +15,7 @@ public void FieldRoundtrip_Works() { ID = "42", CreatedAt = DateTimeOffset.Parse("2025-01-15T12:00:00Z"), + Health = Health.Healthy, Status = "active", XUserID = "9876543210", XUsername = "elonmusk", @@ -21,12 +23,14 @@ public void FieldRoundtrip_Works() string expectedID = "42"; DateTimeOffset expectedCreatedAt = DateTimeOffset.Parse("2025-01-15T12:00:00Z"); + ApiEnum expectedHealth = Health.Healthy; string expectedStatus = "active"; string expectedXUserID = "9876543210"; string expectedXUsername = "elonmusk"; Assert.Equal(expectedID, model.ID); Assert.Equal(expectedCreatedAt, model.CreatedAt); + Assert.Equal(expectedHealth, model.Health); Assert.Equal(expectedStatus, model.Status); Assert.Equal(expectedXUserID, model.XUserID); Assert.Equal(expectedXUsername, model.XUsername); @@ -39,6 +43,7 @@ public void SerializationRoundtrip_Works() { ID = "42", CreatedAt = DateTimeOffset.Parse("2025-01-15T12:00:00Z"), + Health = Health.Healthy, Status = "active", XUserID = "9876543210", XUsername = "elonmusk", @@ -57,6 +62,7 @@ public void FieldRoundtripThroughSerialization_Works() { ID = "42", CreatedAt = DateTimeOffset.Parse("2025-01-15T12:00:00Z"), + Health = Health.Healthy, Status = "active", XUserID = "9876543210", XUsername = "elonmusk", @@ -71,12 +77,14 @@ public void FieldRoundtripThroughSerialization_Works() string expectedID = "42"; DateTimeOffset expectedCreatedAt = DateTimeOffset.Parse("2025-01-15T12:00:00Z"); + ApiEnum expectedHealth = Health.Healthy; string expectedStatus = "active"; string expectedXUserID = "9876543210"; string expectedXUsername = "elonmusk"; Assert.Equal(expectedID, deserialized.ID); Assert.Equal(expectedCreatedAt, deserialized.CreatedAt); + Assert.Equal(expectedHealth, deserialized.Health); Assert.Equal(expectedStatus, deserialized.Status); Assert.Equal(expectedXUserID, deserialized.XUserID); Assert.Equal(expectedXUsername, deserialized.XUsername); @@ -89,6 +97,7 @@ public void Validation_Works() { ID = "42", CreatedAt = DateTimeOffset.Parse("2025-01-15T12:00:00Z"), + Health = Health.Healthy, Status = "active", XUserID = "9876543210", XUsername = "elonmusk", @@ -104,6 +113,7 @@ public void CopyConstructor_Works() { ID = "42", CreatedAt = DateTimeOffset.Parse("2025-01-15T12:00:00Z"), + Health = Health.Healthy, Status = "active", XUserID = "9876543210", XUsername = "elonmusk", @@ -114,3 +124,69 @@ public void CopyConstructor_Works() Assert.Equal(model, copied); } } + +public class HealthTest : TestBase +{ + [Theory] + [InlineData(Health.Healthy)] + [InlineData(Health.Locked)] + [InlineData(Health.NeedsReauth)] + [InlineData(Health.Recovering)] + [InlineData(Health.Suspended)] + [InlineData(Health.TemporaryIssue)] + public void Validation_Works(Health rawValue) + { + // force implicit conversion because Theory can't do that for us + ApiEnum value = rawValue; + value.Validate(); + } + + [Fact] + public void InvalidEnumValidationThrows_Works() + { + var value = JsonSerializer.Deserialize>( + JsonSerializer.SerializeToElement("invalid value"), + ModelBase.SerializerOptions + ); + + Assert.NotNull(value); + Assert.Throws(() => value.Validate()); + } + + [Theory] + [InlineData(Health.Healthy)] + [InlineData(Health.Locked)] + [InlineData(Health.NeedsReauth)] + [InlineData(Health.Recovering)] + [InlineData(Health.Suspended)] + [InlineData(Health.TemporaryIssue)] + public void SerializationRoundtrip_Works(Health rawValue) + { + // force implicit conversion because Theory can't do that for us + ApiEnum value = rawValue; + + string json = JsonSerializer.Serialize(value, ModelBase.SerializerOptions); + var deserialized = JsonSerializer.Deserialize>( + json, + ModelBase.SerializerOptions + ); + + Assert.Equal(value, deserialized); + } + + [Fact] + public void InvalidEnumSerializationRoundtrip_Works() + { + var value = JsonSerializer.Deserialize>( + JsonSerializer.SerializeToElement("invalid value"), + ModelBase.SerializerOptions + ); + string json = JsonSerializer.Serialize(value, ModelBase.SerializerOptions); + var deserialized = JsonSerializer.Deserialize>( + json, + ModelBase.SerializerOptions + ); + + Assert.Equal(value, deserialized); + } +} diff --git a/src/XTwitterScraper.Tests/Models/X/Bookmarks/BookmarkListParamsTest.cs b/src/XTwitterScraper.Tests/Models/X/Bookmarks/BookmarkListParamsTest.cs index 2e4cbbe..f24584f 100644 --- a/src/XTwitterScraper.Tests/Models/X/Bookmarks/BookmarkListParamsTest.cs +++ b/src/XTwitterScraper.Tests/Models/X/Bookmarks/BookmarkListParamsTest.cs @@ -49,11 +49,15 @@ public void Url_Works() { BookmarkListParams parameters = new() { Cursor = "folders_value", FolderID = "folderId" }; - var url = parameters.Url(new() { ApiKey = "My API Key", BearerToken = "My Bearer Token" }); + var url = parameters.Url(new() { ApiKey = "My API Key" }); - Assert.Equal( - new Uri("https://xquik.com/api/v1/x/bookmarks?cursor=folders_value&folderId=folderId"), - url + Assert.True( + TestBase.UrisEqual( + new Uri( + "https://xquik.com/api/v1/x/bookmarks?cursor=folders_value&folderId=folderId" + ), + url + ) ); } diff --git a/src/XTwitterScraper.Tests/Models/X/Communities/CommunityCreateParamsTest.cs b/src/XTwitterScraper.Tests/Models/X/Communities/CommunityCreateParamsTest.cs index fc66a84..198eac5 100644 --- a/src/XTwitterScraper.Tests/Models/X/Communities/CommunityCreateParamsTest.cs +++ b/src/XTwitterScraper.Tests/Models/X/Communities/CommunityCreateParamsTest.cs @@ -54,9 +54,9 @@ public void Url_Works() { CommunityCreateParams parameters = new() { Account = "@elonmusk", Name = "Example Name" }; - var url = parameters.Url(new() { ApiKey = "My API Key", BearerToken = "My Bearer Token" }); + var url = parameters.Url(new() { ApiKey = "My API Key" }); - Assert.Equal(new Uri("https://xquik.com/api/v1/x/communities"), url); + Assert.True(TestBase.UrisEqual(new Uri("https://xquik.com/api/v1/x/communities"), url)); } [Fact] diff --git a/src/XTwitterScraper.Tests/Models/X/Communities/CommunityDeleteParamsTest.cs b/src/XTwitterScraper.Tests/Models/X/Communities/CommunityDeleteParamsTest.cs index 1e2b861..963d8a2 100644 --- a/src/XTwitterScraper.Tests/Models/X/Communities/CommunityDeleteParamsTest.cs +++ b/src/XTwitterScraper.Tests/Models/X/Communities/CommunityDeleteParamsTest.cs @@ -34,9 +34,9 @@ public void Url_Works() CommunityName = "Tesla Fans", }; - var url = parameters.Url(new() { ApiKey = "My API Key", BearerToken = "My Bearer Token" }); + var url = parameters.Url(new() { ApiKey = "My API Key" }); - Assert.Equal(new Uri("https://xquik.com/api/v1/x/communities/id"), url); + Assert.True(TestBase.UrisEqual(new Uri("https://xquik.com/api/v1/x/communities/id"), url)); } [Fact] diff --git a/src/XTwitterScraper.Tests/Models/X/Communities/CommunityRetrieveInfoParamsTest.cs b/src/XTwitterScraper.Tests/Models/X/Communities/CommunityRetrieveInfoParamsTest.cs index 7137578..3677ff3 100644 --- a/src/XTwitterScraper.Tests/Models/X/Communities/CommunityRetrieveInfoParamsTest.cs +++ b/src/XTwitterScraper.Tests/Models/X/Communities/CommunityRetrieveInfoParamsTest.cs @@ -20,9 +20,11 @@ public void Url_Works() { CommunityRetrieveInfoParams parameters = new() { ID = "id" }; - var url = parameters.Url(new() { ApiKey = "My API Key", BearerToken = "My Bearer Token" }); + var url = parameters.Url(new() { ApiKey = "My API Key" }); - Assert.Equal(new Uri("https://xquik.com/api/v1/x/communities/id/info"), url); + Assert.True( + TestBase.UrisEqual(new Uri("https://xquik.com/api/v1/x/communities/id/info"), url) + ); } [Fact] diff --git a/src/XTwitterScraper.Tests/Models/X/Communities/CommunityRetrieveMembersParamsTest.cs b/src/XTwitterScraper.Tests/Models/X/Communities/CommunityRetrieveMembersParamsTest.cs index 898d777..14f43bb 100644 --- a/src/XTwitterScraper.Tests/Models/X/Communities/CommunityRetrieveMembersParamsTest.cs +++ b/src/XTwitterScraper.Tests/Models/X/Communities/CommunityRetrieveMembersParamsTest.cs @@ -46,11 +46,13 @@ public void Url_Works() { CommunityRetrieveMembersParams parameters = new() { ID = "id", Cursor = "cursor" }; - var url = parameters.Url(new() { ApiKey = "My API Key", BearerToken = "My Bearer Token" }); + var url = parameters.Url(new() { ApiKey = "My API Key" }); - Assert.Equal( - new Uri("https://xquik.com/api/v1/x/communities/id/members?cursor=cursor"), - url + Assert.True( + TestBase.UrisEqual( + new Uri("https://xquik.com/api/v1/x/communities/id/members?cursor=cursor"), + url + ) ); } diff --git a/src/XTwitterScraper.Tests/Models/X/Communities/CommunityRetrieveModeratorsParamsTest.cs b/src/XTwitterScraper.Tests/Models/X/Communities/CommunityRetrieveModeratorsParamsTest.cs index 09b6fdb..0f01003 100644 --- a/src/XTwitterScraper.Tests/Models/X/Communities/CommunityRetrieveModeratorsParamsTest.cs +++ b/src/XTwitterScraper.Tests/Models/X/Communities/CommunityRetrieveModeratorsParamsTest.cs @@ -46,11 +46,13 @@ public void Url_Works() { CommunityRetrieveModeratorsParams parameters = new() { ID = "id", Cursor = "cursor" }; - var url = parameters.Url(new() { ApiKey = "My API Key", BearerToken = "My Bearer Token" }); + var url = parameters.Url(new() { ApiKey = "My API Key" }); - Assert.Equal( - new Uri("https://xquik.com/api/v1/x/communities/id/moderators?cursor=cursor"), - url + Assert.True( + TestBase.UrisEqual( + new Uri("https://xquik.com/api/v1/x/communities/id/moderators?cursor=cursor"), + url + ) ); } diff --git a/src/XTwitterScraper.Tests/Models/X/Communities/CommunityRetrieveSearchParamsTest.cs b/src/XTwitterScraper.Tests/Models/X/Communities/CommunityRetrieveSearchParamsTest.cs index f93afd7..4752a96 100644 --- a/src/XTwitterScraper.Tests/Models/X/Communities/CommunityRetrieveSearchParamsTest.cs +++ b/src/XTwitterScraper.Tests/Models/X/Communities/CommunityRetrieveSearchParamsTest.cs @@ -63,13 +63,15 @@ public void Url_Works() QueryType = "queryType", }; - var url = parameters.Url(new() { ApiKey = "My API Key", BearerToken = "My Bearer Token" }); + var url = parameters.Url(new() { ApiKey = "My API Key" }); - Assert.Equal( - new Uri( - "https://xquik.com/api/v1/x/communities/search?q=q&cursor=cursor&queryType=queryType" - ), - url + Assert.True( + TestBase.UrisEqual( + new Uri( + "https://xquik.com/api/v1/x/communities/search?q=q&cursor=cursor&queryType=queryType" + ), + url + ) ); } diff --git a/src/XTwitterScraper.Tests/Models/X/Communities/Join/JoinCreateParamsTest.cs b/src/XTwitterScraper.Tests/Models/X/Communities/Join/JoinCreateParamsTest.cs index ac9981e..e747a34 100644 --- a/src/XTwitterScraper.Tests/Models/X/Communities/Join/JoinCreateParamsTest.cs +++ b/src/XTwitterScraper.Tests/Models/X/Communities/Join/JoinCreateParamsTest.cs @@ -22,9 +22,11 @@ public void Url_Works() { JoinCreateParams parameters = new() { ID = "id", Account = "@elonmusk" }; - var url = parameters.Url(new() { ApiKey = "My API Key", BearerToken = "My Bearer Token" }); + var url = parameters.Url(new() { ApiKey = "My API Key" }); - Assert.Equal(new Uri("https://xquik.com/api/v1/x/communities/id/join"), url); + Assert.True( + TestBase.UrisEqual(new Uri("https://xquik.com/api/v1/x/communities/id/join"), url) + ); } [Fact] diff --git a/src/XTwitterScraper.Tests/Models/X/Communities/Join/JoinDeleteAllParamsTest.cs b/src/XTwitterScraper.Tests/Models/X/Communities/Join/JoinDeleteAllParamsTest.cs index a4eb82e..ca4bace 100644 --- a/src/XTwitterScraper.Tests/Models/X/Communities/Join/JoinDeleteAllParamsTest.cs +++ b/src/XTwitterScraper.Tests/Models/X/Communities/Join/JoinDeleteAllParamsTest.cs @@ -22,9 +22,11 @@ public void Url_Works() { JoinDeleteAllParams parameters = new() { ID = "id", Account = "@elonmusk" }; - var url = parameters.Url(new() { ApiKey = "My API Key", BearerToken = "My Bearer Token" }); + var url = parameters.Url(new() { ApiKey = "My API Key" }); - Assert.Equal(new Uri("https://xquik.com/api/v1/x/communities/id/join"), url); + Assert.True( + TestBase.UrisEqual(new Uri("https://xquik.com/api/v1/x/communities/id/join"), url) + ); } [Fact] diff --git a/src/XTwitterScraper.Tests/Models/X/Communities/Tweets/TweetListByCommunityParamsTest.cs b/src/XTwitterScraper.Tests/Models/X/Communities/Tweets/TweetListByCommunityParamsTest.cs index 4a7c4c6..32fba7a 100644 --- a/src/XTwitterScraper.Tests/Models/X/Communities/Tweets/TweetListByCommunityParamsTest.cs +++ b/src/XTwitterScraper.Tests/Models/X/Communities/Tweets/TweetListByCommunityParamsTest.cs @@ -46,11 +46,13 @@ public void Url_Works() { TweetListByCommunityParams parameters = new() { ID = "id", Cursor = "cursor" }; - var url = parameters.Url(new() { ApiKey = "My API Key", BearerToken = "My Bearer Token" }); + var url = parameters.Url(new() { ApiKey = "My API Key" }); - Assert.Equal( - new Uri("https://xquik.com/api/v1/x/communities/id/tweets?cursor=cursor"), - url + Assert.True( + TestBase.UrisEqual( + new Uri("https://xquik.com/api/v1/x/communities/id/tweets?cursor=cursor"), + url + ) ); } diff --git a/src/XTwitterScraper.Tests/Models/X/Communities/Tweets/TweetListParamsTest.cs b/src/XTwitterScraper.Tests/Models/X/Communities/Tweets/TweetListParamsTest.cs index b220145..8d6a8be 100644 --- a/src/XTwitterScraper.Tests/Models/X/Communities/Tweets/TweetListParamsTest.cs +++ b/src/XTwitterScraper.Tests/Models/X/Communities/Tweets/TweetListParamsTest.cs @@ -63,13 +63,15 @@ public void Url_Works() QueryType = "queryType", }; - var url = parameters.Url(new() { ApiKey = "My API Key", BearerToken = "My Bearer Token" }); + var url = parameters.Url(new() { ApiKey = "My API Key" }); - Assert.Equal( - new Uri( - "https://xquik.com/api/v1/x/communities/tweets?q=q&cursor=cursor&queryType=queryType" - ), - url + Assert.True( + TestBase.UrisEqual( + new Uri( + "https://xquik.com/api/v1/x/communities/tweets?q=q&cursor=cursor&queryType=queryType" + ), + url + ) ); } diff --git a/src/XTwitterScraper.Tests/Models/X/Dm/DmRetrieveHistoryParamsTest.cs b/src/XTwitterScraper.Tests/Models/X/Dm/DmRetrieveHistoryParamsTest.cs index 7972665..76c0814 100644 --- a/src/XTwitterScraper.Tests/Models/X/Dm/DmRetrieveHistoryParamsTest.cs +++ b/src/XTwitterScraper.Tests/Models/X/Dm/DmRetrieveHistoryParamsTest.cs @@ -63,11 +63,13 @@ public void Url_Works() MaxID = "maxId", }; - var url = parameters.Url(new() { ApiKey = "My API Key", BearerToken = "My Bearer Token" }); + var url = parameters.Url(new() { ApiKey = "My API Key" }); - Assert.Equal( - new Uri("https://xquik.com/api/v1/x/dm/userId/history?cursor=cursor&maxId=maxId"), - url + Assert.True( + TestBase.UrisEqual( + new Uri("https://xquik.com/api/v1/x/dm/userId/history?cursor=cursor&maxId=maxId"), + url + ) ); } diff --git a/src/XTwitterScraper.Tests/Models/X/Dm/DmSendParamsTest.cs b/src/XTwitterScraper.Tests/Models/X/Dm/DmSendParamsTest.cs index 37910f2..977d471 100644 --- a/src/XTwitterScraper.Tests/Models/X/Dm/DmSendParamsTest.cs +++ b/src/XTwitterScraper.Tests/Models/X/Dm/DmSendParamsTest.cs @@ -82,9 +82,9 @@ public void Url_Works() Text = "Example text content", }; - var url = parameters.Url(new() { ApiKey = "My API Key", BearerToken = "My Bearer Token" }); + var url = parameters.Url(new() { ApiKey = "My API Key" }); - Assert.Equal(new Uri("https://xquik.com/api/v1/x/dm/userId"), url); + Assert.True(TestBase.UrisEqual(new Uri("https://xquik.com/api/v1/x/dm/userId"), url)); } [Fact] diff --git a/src/XTwitterScraper.Tests/Models/X/Followers/FollowerCheckParamsTest.cs b/src/XTwitterScraper.Tests/Models/X/Followers/FollowerCheckParamsTest.cs index 569526b..85c8d50 100644 --- a/src/XTwitterScraper.Tests/Models/X/Followers/FollowerCheckParamsTest.cs +++ b/src/XTwitterScraper.Tests/Models/X/Followers/FollowerCheckParamsTest.cs @@ -22,11 +22,13 @@ public void Url_Works() { FollowerCheckParams parameters = new() { Source = "source", Target = "target" }; - var url = parameters.Url(new() { ApiKey = "My API Key", BearerToken = "My Bearer Token" }); + var url = parameters.Url(new() { ApiKey = "My API Key" }); - Assert.Equal( - new Uri("https://xquik.com/api/v1/x/followers/check?source=source&target=target"), - url + Assert.True( + TestBase.UrisEqual( + new Uri("https://xquik.com/api/v1/x/followers/check?source=source&target=target"), + url + ) ); } diff --git a/src/XTwitterScraper.Tests/Models/X/Lists/ListRetrieveFollowersParamsTest.cs b/src/XTwitterScraper.Tests/Models/X/Lists/ListRetrieveFollowersParamsTest.cs index 65b1ba6..1b22437 100644 --- a/src/XTwitterScraper.Tests/Models/X/Lists/ListRetrieveFollowersParamsTest.cs +++ b/src/XTwitterScraper.Tests/Models/X/Lists/ListRetrieveFollowersParamsTest.cs @@ -46,9 +46,14 @@ public void Url_Works() { ListRetrieveFollowersParams parameters = new() { ID = "id", Cursor = "cursor" }; - var url = parameters.Url(new() { ApiKey = "My API Key", BearerToken = "My Bearer Token" }); + var url = parameters.Url(new() { ApiKey = "My API Key" }); - Assert.Equal(new Uri("https://xquik.com/api/v1/x/lists/id/followers?cursor=cursor"), url); + Assert.True( + TestBase.UrisEqual( + new Uri("https://xquik.com/api/v1/x/lists/id/followers?cursor=cursor"), + url + ) + ); } [Fact] diff --git a/src/XTwitterScraper.Tests/Models/X/Lists/ListRetrieveMembersParamsTest.cs b/src/XTwitterScraper.Tests/Models/X/Lists/ListRetrieveMembersParamsTest.cs index 1b6b802..d57b1a2 100644 --- a/src/XTwitterScraper.Tests/Models/X/Lists/ListRetrieveMembersParamsTest.cs +++ b/src/XTwitterScraper.Tests/Models/X/Lists/ListRetrieveMembersParamsTest.cs @@ -46,9 +46,14 @@ public void Url_Works() { ListRetrieveMembersParams parameters = new() { ID = "id", Cursor = "cursor" }; - var url = parameters.Url(new() { ApiKey = "My API Key", BearerToken = "My Bearer Token" }); + var url = parameters.Url(new() { ApiKey = "My API Key" }); - Assert.Equal(new Uri("https://xquik.com/api/v1/x/lists/id/members?cursor=cursor"), url); + Assert.True( + TestBase.UrisEqual( + new Uri("https://xquik.com/api/v1/x/lists/id/members?cursor=cursor"), + url + ) + ); } [Fact] diff --git a/src/XTwitterScraper.Tests/Models/X/Lists/ListRetrieveTweetsParamsTest.cs b/src/XTwitterScraper.Tests/Models/X/Lists/ListRetrieveTweetsParamsTest.cs index bd8aa19..d63a1cc 100644 --- a/src/XTwitterScraper.Tests/Models/X/Lists/ListRetrieveTweetsParamsTest.cs +++ b/src/XTwitterScraper.Tests/Models/X/Lists/ListRetrieveTweetsParamsTest.cs @@ -81,13 +81,15 @@ public void Url_Works() UntilTime = "untilTime", }; - var url = parameters.Url(new() { ApiKey = "My API Key", BearerToken = "My Bearer Token" }); + var url = parameters.Url(new() { ApiKey = "My API Key" }); - Assert.Equal( - new Uri( - "https://xquik.com/api/v1/x/lists/id/tweets?cursor=cursor&includeReplies=true&sinceTime=sinceTime&untilTime=untilTime" - ), - url + Assert.True( + TestBase.UrisEqual( + new Uri( + "https://xquik.com/api/v1/x/lists/id/tweets?cursor=cursor&includeReplies=true&sinceTime=sinceTime&untilTime=untilTime" + ), + url + ) ); } diff --git a/src/XTwitterScraper.Tests/Models/X/Media/MediaDownloadParamsTest.cs b/src/XTwitterScraper.Tests/Models/X/Media/MediaDownloadParamsTest.cs index 6c2e097..22f2e94 100644 --- a/src/XTwitterScraper.Tests/Models/X/Media/MediaDownloadParamsTest.cs +++ b/src/XTwitterScraper.Tests/Models/X/Media/MediaDownloadParamsTest.cs @@ -59,9 +59,9 @@ public void Url_Works() { MediaDownloadParams parameters = new(); - var url = parameters.Url(new() { ApiKey = "My API Key", BearerToken = "My Bearer Token" }); + var url = parameters.Url(new() { ApiKey = "My API Key" }); - Assert.Equal(new Uri("https://xquik.com/api/v1/x/media/download"), url); + Assert.True(TestBase.UrisEqual(new Uri("https://xquik.com/api/v1/x/media/download"), url)); } [Fact] diff --git a/src/XTwitterScraper.Tests/Models/X/Media/MediaUploadParamsTest.cs b/src/XTwitterScraper.Tests/Models/X/Media/MediaUploadParamsTest.cs index 6315dc4..3fee666 100644 --- a/src/XTwitterScraper.Tests/Models/X/Media/MediaUploadParamsTest.cs +++ b/src/XTwitterScraper.Tests/Models/X/Media/MediaUploadParamsTest.cs @@ -66,9 +66,9 @@ public void Url_Works() File = Encoding.UTF8.GetBytes("Example data"), }; - var url = parameters.Url(new() { ApiKey = "My API Key", BearerToken = "My Bearer Token" }); + var url = parameters.Url(new() { ApiKey = "My API Key" }); - Assert.Equal(new Uri("https://xquik.com/api/v1/x/media"), url); + Assert.True(TestBase.UrisEqual(new Uri("https://xquik.com/api/v1/x/media"), url)); } [Fact] diff --git a/src/XTwitterScraper.Tests/Models/X/Profile/ProfileUpdateAvatarParamsTest.cs b/src/XTwitterScraper.Tests/Models/X/Profile/ProfileUpdateAvatarParamsTest.cs index 524b9b8..f69a76a 100644 --- a/src/XTwitterScraper.Tests/Models/X/Profile/ProfileUpdateAvatarParamsTest.cs +++ b/src/XTwitterScraper.Tests/Models/X/Profile/ProfileUpdateAvatarParamsTest.cs @@ -30,9 +30,9 @@ public void Url_Works() File = Encoding.UTF8.GetBytes("Example data"), }; - var url = parameters.Url(new() { ApiKey = "My API Key", BearerToken = "My Bearer Token" }); + var url = parameters.Url(new() { ApiKey = "My API Key" }); - Assert.Equal(new Uri("https://xquik.com/api/v1/x/profile/avatar"), url); + Assert.True(TestBase.UrisEqual(new Uri("https://xquik.com/api/v1/x/profile/avatar"), url)); } [Fact] diff --git a/src/XTwitterScraper.Tests/Models/X/Profile/ProfileUpdateBannerParamsTest.cs b/src/XTwitterScraper.Tests/Models/X/Profile/ProfileUpdateBannerParamsTest.cs index d17d042..e05e4d5 100644 --- a/src/XTwitterScraper.Tests/Models/X/Profile/ProfileUpdateBannerParamsTest.cs +++ b/src/XTwitterScraper.Tests/Models/X/Profile/ProfileUpdateBannerParamsTest.cs @@ -30,9 +30,9 @@ public void Url_Works() File = Encoding.UTF8.GetBytes("Example data"), }; - var url = parameters.Url(new() { ApiKey = "My API Key", BearerToken = "My Bearer Token" }); + var url = parameters.Url(new() { ApiKey = "My API Key" }); - Assert.Equal(new Uri("https://xquik.com/api/v1/x/profile/banner"), url); + Assert.True(TestBase.UrisEqual(new Uri("https://xquik.com/api/v1/x/profile/banner"), url)); } [Fact] diff --git a/src/XTwitterScraper.Tests/Models/X/Profile/ProfileUpdateParamsTest.cs b/src/XTwitterScraper.Tests/Models/X/Profile/ProfileUpdateParamsTest.cs index eddb54d..a55cf09 100644 --- a/src/XTwitterScraper.Tests/Models/X/Profile/ProfileUpdateParamsTest.cs +++ b/src/XTwitterScraper.Tests/Models/X/Profile/ProfileUpdateParamsTest.cs @@ -74,9 +74,9 @@ public void Url_Works() { ProfileUpdateParams parameters = new() { Account = "@elonmusk" }; - var url = parameters.Url(new() { ApiKey = "My API Key", BearerToken = "My Bearer Token" }); + var url = parameters.Url(new() { ApiKey = "My API Key" }); - Assert.Equal(new Uri("https://xquik.com/api/v1/x/profile"), url); + Assert.True(TestBase.UrisEqual(new Uri("https://xquik.com/api/v1/x/profile"), url)); } [Fact] diff --git a/src/XTwitterScraper.Tests/Models/X/Tweets/Like/LikeCreateParamsTest.cs b/src/XTwitterScraper.Tests/Models/X/Tweets/Like/LikeCreateParamsTest.cs index 3c77082..282a830 100644 --- a/src/XTwitterScraper.Tests/Models/X/Tweets/Like/LikeCreateParamsTest.cs +++ b/src/XTwitterScraper.Tests/Models/X/Tweets/Like/LikeCreateParamsTest.cs @@ -22,9 +22,9 @@ public void Url_Works() { LikeCreateParams parameters = new() { ID = "id", Account = "@elonmusk" }; - var url = parameters.Url(new() { ApiKey = "My API Key", BearerToken = "My Bearer Token" }); + var url = parameters.Url(new() { ApiKey = "My API Key" }); - Assert.Equal(new Uri("https://xquik.com/api/v1/x/tweets/id/like"), url); + Assert.True(TestBase.UrisEqual(new Uri("https://xquik.com/api/v1/x/tweets/id/like"), url)); } [Fact] diff --git a/src/XTwitterScraper.Tests/Models/X/Tweets/Like/LikeDeleteParamsTest.cs b/src/XTwitterScraper.Tests/Models/X/Tweets/Like/LikeDeleteParamsTest.cs index cac5e24..575c313 100644 --- a/src/XTwitterScraper.Tests/Models/X/Tweets/Like/LikeDeleteParamsTest.cs +++ b/src/XTwitterScraper.Tests/Models/X/Tweets/Like/LikeDeleteParamsTest.cs @@ -22,9 +22,9 @@ public void Url_Works() { LikeDeleteParams parameters = new() { ID = "id", Account = "@elonmusk" }; - var url = parameters.Url(new() { ApiKey = "My API Key", BearerToken = "My Bearer Token" }); + var url = parameters.Url(new() { ApiKey = "My API Key" }); - Assert.Equal(new Uri("https://xquik.com/api/v1/x/tweets/id/like"), url); + Assert.True(TestBase.UrisEqual(new Uri("https://xquik.com/api/v1/x/tweets/id/like"), url)); } [Fact] diff --git a/src/XTwitterScraper.Tests/Models/X/Tweets/Retweet/RetweetCreateParamsTest.cs b/src/XTwitterScraper.Tests/Models/X/Tweets/Retweet/RetweetCreateParamsTest.cs index 729a8bd..8e3a446 100644 --- a/src/XTwitterScraper.Tests/Models/X/Tweets/Retweet/RetweetCreateParamsTest.cs +++ b/src/XTwitterScraper.Tests/Models/X/Tweets/Retweet/RetweetCreateParamsTest.cs @@ -22,9 +22,11 @@ public void Url_Works() { RetweetCreateParams parameters = new() { ID = "id", Account = "@elonmusk" }; - var url = parameters.Url(new() { ApiKey = "My API Key", BearerToken = "My Bearer Token" }); + var url = parameters.Url(new() { ApiKey = "My API Key" }); - Assert.Equal(new Uri("https://xquik.com/api/v1/x/tweets/id/retweet"), url); + Assert.True( + TestBase.UrisEqual(new Uri("https://xquik.com/api/v1/x/tweets/id/retweet"), url) + ); } [Fact] diff --git a/src/XTwitterScraper.Tests/Models/X/Tweets/Retweet/RetweetDeleteParamsTest.cs b/src/XTwitterScraper.Tests/Models/X/Tweets/Retweet/RetweetDeleteParamsTest.cs index 5c5af49..6fa9e98 100644 --- a/src/XTwitterScraper.Tests/Models/X/Tweets/Retweet/RetweetDeleteParamsTest.cs +++ b/src/XTwitterScraper.Tests/Models/X/Tweets/Retweet/RetweetDeleteParamsTest.cs @@ -22,9 +22,11 @@ public void Url_Works() { RetweetDeleteParams parameters = new() { ID = "id", Account = "@elonmusk" }; - var url = parameters.Url(new() { ApiKey = "My API Key", BearerToken = "My Bearer Token" }); + var url = parameters.Url(new() { ApiKey = "My API Key" }); - Assert.Equal(new Uri("https://xquik.com/api/v1/x/tweets/id/retweet"), url); + Assert.True( + TestBase.UrisEqual(new Uri("https://xquik.com/api/v1/x/tweets/id/retweet"), url) + ); } [Fact] diff --git a/src/XTwitterScraper.Tests/Models/X/Tweets/TweetCreateParamsTest.cs b/src/XTwitterScraper.Tests/Models/X/Tweets/TweetCreateParamsTest.cs index 1fd5971..eddadaa 100644 --- a/src/XTwitterScraper.Tests/Models/X/Tweets/TweetCreateParamsTest.cs +++ b/src/XTwitterScraper.Tests/Models/X/Tweets/TweetCreateParamsTest.cs @@ -12,27 +12,34 @@ public void FieldRoundtrip_Works() var parameters = new TweetCreateParams { Account = "@elonmusk", - Text = "Just launched our new feature!", AttachmentUrl = "https://x.com/elonmusk/status/1234567890", CommunityID = "1500000000000000000", IsNoteTweet = false, + Media = ["https://example.com/image.jpg"], MediaIds = ["1234567890123456789"], ReplyToTweetID = "1234567890", + Text = "Just launched our new feature!", }; string expectedAccount = "@elonmusk"; - string expectedText = "Just launched our new feature!"; string expectedAttachmentUrl = "https://x.com/elonmusk/status/1234567890"; string expectedCommunityID = "1500000000000000000"; bool expectedIsNoteTweet = false; + List expectedMedia = ["https://example.com/image.jpg"]; List expectedMediaIds = ["1234567890123456789"]; string expectedReplyToTweetID = "1234567890"; + string expectedText = "Just launched our new feature!"; Assert.Equal(expectedAccount, parameters.Account); - Assert.Equal(expectedText, parameters.Text); Assert.Equal(expectedAttachmentUrl, parameters.AttachmentUrl); Assert.Equal(expectedCommunityID, parameters.CommunityID); Assert.Equal(expectedIsNoteTweet, parameters.IsNoteTweet); + Assert.NotNull(parameters.Media); + Assert.Equal(expectedMedia.Count, parameters.Media.Count); + for (int i = 0; i < expectedMedia.Count; i++) + { + Assert.Equal(expectedMedia[i], parameters.Media[i]); + } Assert.NotNull(parameters.MediaIds); Assert.Equal(expectedMediaIds.Count, parameters.MediaIds.Count); for (int i = 0; i < expectedMediaIds.Count; i++) @@ -40,16 +47,13 @@ public void FieldRoundtrip_Works() Assert.Equal(expectedMediaIds[i], parameters.MediaIds[i]); } Assert.Equal(expectedReplyToTweetID, parameters.ReplyToTweetID); + Assert.Equal(expectedText, parameters.Text); } [Fact] public void OptionalNonNullableParamsUnsetAreNotSet_Works() { - var parameters = new TweetCreateParams - { - Account = "@elonmusk", - Text = "Just launched our new feature!", - }; + var parameters = new TweetCreateParams { Account = "@elonmusk" }; Assert.Null(parameters.AttachmentUrl); Assert.False(parameters.RawBodyData.ContainsKey("attachment_url")); @@ -57,10 +61,14 @@ public void OptionalNonNullableParamsUnsetAreNotSet_Works() Assert.False(parameters.RawBodyData.ContainsKey("community_id")); Assert.Null(parameters.IsNoteTweet); Assert.False(parameters.RawBodyData.ContainsKey("is_note_tweet")); + Assert.Null(parameters.Media); + Assert.False(parameters.RawBodyData.ContainsKey("media")); Assert.Null(parameters.MediaIds); Assert.False(parameters.RawBodyData.ContainsKey("media_ids")); Assert.Null(parameters.ReplyToTweetID); Assert.False(parameters.RawBodyData.ContainsKey("reply_to_tweet_id")); + Assert.Null(parameters.Text); + Assert.False(parameters.RawBodyData.ContainsKey("text")); } [Fact] @@ -69,14 +77,15 @@ public void OptionalNonNullableParamsSetToNullAreNotSet_Works() var parameters = new TweetCreateParams { Account = "@elonmusk", - Text = "Just launched our new feature!", // Null should be interpreted as omitted for these properties AttachmentUrl = null, CommunityID = null, IsNoteTweet = null, + Media = null, MediaIds = null, ReplyToTweetID = null, + Text = null, }; Assert.Null(parameters.AttachmentUrl); @@ -85,24 +94,24 @@ public void OptionalNonNullableParamsSetToNullAreNotSet_Works() Assert.False(parameters.RawBodyData.ContainsKey("community_id")); Assert.Null(parameters.IsNoteTweet); Assert.False(parameters.RawBodyData.ContainsKey("is_note_tweet")); + Assert.Null(parameters.Media); + Assert.False(parameters.RawBodyData.ContainsKey("media")); Assert.Null(parameters.MediaIds); Assert.False(parameters.RawBodyData.ContainsKey("media_ids")); Assert.Null(parameters.ReplyToTweetID); Assert.False(parameters.RawBodyData.ContainsKey("reply_to_tweet_id")); + Assert.Null(parameters.Text); + Assert.False(parameters.RawBodyData.ContainsKey("text")); } [Fact] public void Url_Works() { - TweetCreateParams parameters = new() - { - Account = "@elonmusk", - Text = "Just launched our new feature!", - }; + TweetCreateParams parameters = new() { Account = "@elonmusk" }; - var url = parameters.Url(new() { ApiKey = "My API Key", BearerToken = "My Bearer Token" }); + var url = parameters.Url(new() { ApiKey = "My API Key" }); - Assert.Equal(new Uri("https://xquik.com/api/v1/x/tweets"), url); + Assert.True(TestBase.UrisEqual(new Uri("https://xquik.com/api/v1/x/tweets"), url)); } [Fact] @@ -111,12 +120,13 @@ public void CopyConstructor_Works() var parameters = new TweetCreateParams { Account = "@elonmusk", - Text = "Just launched our new feature!", AttachmentUrl = "https://x.com/elonmusk/status/1234567890", CommunityID = "1500000000000000000", IsNoteTweet = false, + Media = ["https://example.com/image.jpg"], MediaIds = ["1234567890123456789"], ReplyToTweetID = "1234567890", + Text = "Just launched our new feature!", }; TweetCreateParams copied = new(parameters); diff --git a/src/XTwitterScraper.Tests/Models/X/Tweets/TweetDeleteParamsTest.cs b/src/XTwitterScraper.Tests/Models/X/Tweets/TweetDeleteParamsTest.cs index 81ba863..9cc5591 100644 --- a/src/XTwitterScraper.Tests/Models/X/Tweets/TweetDeleteParamsTest.cs +++ b/src/XTwitterScraper.Tests/Models/X/Tweets/TweetDeleteParamsTest.cs @@ -22,9 +22,9 @@ public void Url_Works() { TweetDeleteParams parameters = new() { ID = "id", Account = "@elonmusk" }; - var url = parameters.Url(new() { ApiKey = "My API Key", BearerToken = "My Bearer Token" }); + var url = parameters.Url(new() { ApiKey = "My API Key" }); - Assert.Equal(new Uri("https://xquik.com/api/v1/x/tweets/id"), url); + Assert.True(TestBase.UrisEqual(new Uri("https://xquik.com/api/v1/x/tweets/id"), url)); } [Fact] diff --git a/src/XTwitterScraper.Tests/Models/X/Tweets/TweetGetFavoritersParamsTest.cs b/src/XTwitterScraper.Tests/Models/X/Tweets/TweetGetFavoritersParamsTest.cs index 1823365..9bcb91f 100644 --- a/src/XTwitterScraper.Tests/Models/X/Tweets/TweetGetFavoritersParamsTest.cs +++ b/src/XTwitterScraper.Tests/Models/X/Tweets/TweetGetFavoritersParamsTest.cs @@ -46,9 +46,14 @@ public void Url_Works() { TweetGetFavoritersParams parameters = new() { ID = "id", Cursor = "cursor" }; - var url = parameters.Url(new() { ApiKey = "My API Key", BearerToken = "My Bearer Token" }); + var url = parameters.Url(new() { ApiKey = "My API Key" }); - Assert.Equal(new Uri("https://xquik.com/api/v1/x/tweets/id/favoriters?cursor=cursor"), url); + Assert.True( + TestBase.UrisEqual( + new Uri("https://xquik.com/api/v1/x/tweets/id/favoriters?cursor=cursor"), + url + ) + ); } [Fact] diff --git a/src/XTwitterScraper.Tests/Models/X/Tweets/TweetGetQuotesParamsTest.cs b/src/XTwitterScraper.Tests/Models/X/Tweets/TweetGetQuotesParamsTest.cs index 25c6ed2..a2297ff 100644 --- a/src/XTwitterScraper.Tests/Models/X/Tweets/TweetGetQuotesParamsTest.cs +++ b/src/XTwitterScraper.Tests/Models/X/Tweets/TweetGetQuotesParamsTest.cs @@ -81,13 +81,15 @@ public void Url_Works() UntilTime = "untilTime", }; - var url = parameters.Url(new() { ApiKey = "My API Key", BearerToken = "My Bearer Token" }); + var url = parameters.Url(new() { ApiKey = "My API Key" }); - Assert.Equal( - new Uri( - "https://xquik.com/api/v1/x/tweets/id/quotes?cursor=cursor&includeReplies=true&sinceTime=sinceTime&untilTime=untilTime" - ), - url + Assert.True( + TestBase.UrisEqual( + new Uri( + "https://xquik.com/api/v1/x/tweets/id/quotes?cursor=cursor&includeReplies=true&sinceTime=sinceTime&untilTime=untilTime" + ), + url + ) ); } diff --git a/src/XTwitterScraper.Tests/Models/X/Tweets/TweetGetRepliesParamsTest.cs b/src/XTwitterScraper.Tests/Models/X/Tweets/TweetGetRepliesParamsTest.cs index a662c0c..120856b 100644 --- a/src/XTwitterScraper.Tests/Models/X/Tweets/TweetGetRepliesParamsTest.cs +++ b/src/XTwitterScraper.Tests/Models/X/Tweets/TweetGetRepliesParamsTest.cs @@ -72,13 +72,15 @@ public void Url_Works() UntilTime = "untilTime", }; - var url = parameters.Url(new() { ApiKey = "My API Key", BearerToken = "My Bearer Token" }); + var url = parameters.Url(new() { ApiKey = "My API Key" }); - Assert.Equal( - new Uri( - "https://xquik.com/api/v1/x/tweets/id/replies?cursor=cursor&sinceTime=sinceTime&untilTime=untilTime" - ), - url + Assert.True( + TestBase.UrisEqual( + new Uri( + "https://xquik.com/api/v1/x/tweets/id/replies?cursor=cursor&sinceTime=sinceTime&untilTime=untilTime" + ), + url + ) ); } diff --git a/src/XTwitterScraper.Tests/Models/X/Tweets/TweetGetRetweetersParamsTest.cs b/src/XTwitterScraper.Tests/Models/X/Tweets/TweetGetRetweetersParamsTest.cs index 757486d..86793a3 100644 --- a/src/XTwitterScraper.Tests/Models/X/Tweets/TweetGetRetweetersParamsTest.cs +++ b/src/XTwitterScraper.Tests/Models/X/Tweets/TweetGetRetweetersParamsTest.cs @@ -46,9 +46,14 @@ public void Url_Works() { TweetGetRetweetersParams parameters = new() { ID = "id", Cursor = "cursor" }; - var url = parameters.Url(new() { ApiKey = "My API Key", BearerToken = "My Bearer Token" }); + var url = parameters.Url(new() { ApiKey = "My API Key" }); - Assert.Equal(new Uri("https://xquik.com/api/v1/x/tweets/id/retweeters?cursor=cursor"), url); + Assert.True( + TestBase.UrisEqual( + new Uri("https://xquik.com/api/v1/x/tweets/id/retweeters?cursor=cursor"), + url + ) + ); } [Fact] diff --git a/src/XTwitterScraper.Tests/Models/X/Tweets/TweetGetThreadParamsTest.cs b/src/XTwitterScraper.Tests/Models/X/Tweets/TweetGetThreadParamsTest.cs index e8451ee..70e7624 100644 --- a/src/XTwitterScraper.Tests/Models/X/Tweets/TweetGetThreadParamsTest.cs +++ b/src/XTwitterScraper.Tests/Models/X/Tweets/TweetGetThreadParamsTest.cs @@ -46,9 +46,14 @@ public void Url_Works() { TweetGetThreadParams parameters = new() { ID = "id", Cursor = "cursor" }; - var url = parameters.Url(new() { ApiKey = "My API Key", BearerToken = "My Bearer Token" }); + var url = parameters.Url(new() { ApiKey = "My API Key" }); - Assert.Equal(new Uri("https://xquik.com/api/v1/x/tweets/id/thread?cursor=cursor"), url); + Assert.True( + TestBase.UrisEqual( + new Uri("https://xquik.com/api/v1/x/tweets/id/thread?cursor=cursor"), + url + ) + ); } [Fact] diff --git a/src/XTwitterScraper.Tests/Models/X/Tweets/TweetListParamsTest.cs b/src/XTwitterScraper.Tests/Models/X/Tweets/TweetListParamsTest.cs index f82e710..ad579bc 100644 --- a/src/XTwitterScraper.Tests/Models/X/Tweets/TweetListParamsTest.cs +++ b/src/XTwitterScraper.Tests/Models/X/Tweets/TweetListParamsTest.cs @@ -20,9 +20,9 @@ public void Url_Works() { TweetListParams parameters = new() { Ids = "ids" }; - var url = parameters.Url(new() { ApiKey = "My API Key", BearerToken = "My Bearer Token" }); + var url = parameters.Url(new() { ApiKey = "My API Key" }); - Assert.Equal(new Uri("https://xquik.com/api/v1/x/tweets?ids=ids"), url); + Assert.True(TestBase.UrisEqual(new Uri("https://xquik.com/api/v1/x/tweets?ids=ids"), url)); } [Fact] diff --git a/src/XTwitterScraper.Tests/Models/X/Tweets/TweetRetrieveParamsTest.cs b/src/XTwitterScraper.Tests/Models/X/Tweets/TweetRetrieveParamsTest.cs index 5e69886..0697a10 100644 --- a/src/XTwitterScraper.Tests/Models/X/Tweets/TweetRetrieveParamsTest.cs +++ b/src/XTwitterScraper.Tests/Models/X/Tweets/TweetRetrieveParamsTest.cs @@ -20,9 +20,9 @@ public void Url_Works() { TweetRetrieveParams parameters = new() { ID = "id" }; - var url = parameters.Url(new() { ApiKey = "My API Key", BearerToken = "My Bearer Token" }); + var url = parameters.Url(new() { ApiKey = "My API Key" }); - Assert.Equal(new Uri("https://xquik.com/api/v1/x/tweets/id"), url); + Assert.True(TestBase.UrisEqual(new Uri("https://xquik.com/api/v1/x/tweets/id"), url)); } [Fact] diff --git a/src/XTwitterScraper.Tests/Models/X/Tweets/TweetSearchParamsTest.cs b/src/XTwitterScraper.Tests/Models/X/Tweets/TweetSearchParamsTest.cs index 3c8ee00..8a320a8 100644 --- a/src/XTwitterScraper.Tests/Models/X/Tweets/TweetSearchParamsTest.cs +++ b/src/XTwitterScraper.Tests/Models/X/Tweets/TweetSearchParamsTest.cs @@ -93,13 +93,15 @@ public void Url_Works() UntilTime = "untilTime", }; - var url = parameters.Url(new() { ApiKey = "My API Key", BearerToken = "My Bearer Token" }); - - Assert.Equal( - new Uri( - "https://xquik.com/api/v1/x/tweets/search?q=q&cursor=cursor&limit=200&queryType=Latest&sinceTime=sinceTime&untilTime=untilTime" - ), - url + var url = parameters.Url(new() { ApiKey = "My API Key" }); + + Assert.True( + TestBase.UrisEqual( + new Uri( + "https://xquik.com/api/v1/x/tweets/search?q=q&cursor=cursor&limit=200&queryType=Latest&sinceTime=sinceTime&untilTime=untilTime" + ), + url + ) ); } diff --git a/src/XTwitterScraper.Tests/Models/X/Users/Follow/FollowCreateParamsTest.cs b/src/XTwitterScraper.Tests/Models/X/Users/Follow/FollowCreateParamsTest.cs index aa250f8..a4977a1 100644 --- a/src/XTwitterScraper.Tests/Models/X/Users/Follow/FollowCreateParamsTest.cs +++ b/src/XTwitterScraper.Tests/Models/X/Users/Follow/FollowCreateParamsTest.cs @@ -22,9 +22,9 @@ public void Url_Works() { FollowCreateParams parameters = new() { ID = "id", Account = "@elonmusk" }; - var url = parameters.Url(new() { ApiKey = "My API Key", BearerToken = "My Bearer Token" }); + var url = parameters.Url(new() { ApiKey = "My API Key" }); - Assert.Equal(new Uri("https://xquik.com/api/v1/x/users/id/follow"), url); + Assert.True(TestBase.UrisEqual(new Uri("https://xquik.com/api/v1/x/users/id/follow"), url)); } [Fact] diff --git a/src/XTwitterScraper.Tests/Models/X/Users/Follow/FollowDeleteAllParamsTest.cs b/src/XTwitterScraper.Tests/Models/X/Users/Follow/FollowDeleteAllParamsTest.cs index 1e9ef23..3eaba4e 100644 --- a/src/XTwitterScraper.Tests/Models/X/Users/Follow/FollowDeleteAllParamsTest.cs +++ b/src/XTwitterScraper.Tests/Models/X/Users/Follow/FollowDeleteAllParamsTest.cs @@ -22,9 +22,9 @@ public void Url_Works() { FollowDeleteAllParams parameters = new() { ID = "id", Account = "@elonmusk" }; - var url = parameters.Url(new() { ApiKey = "My API Key", BearerToken = "My Bearer Token" }); + var url = parameters.Url(new() { ApiKey = "My API Key" }); - Assert.Equal(new Uri("https://xquik.com/api/v1/x/users/id/follow"), url); + Assert.True(TestBase.UrisEqual(new Uri("https://xquik.com/api/v1/x/users/id/follow"), url)); } [Fact] diff --git a/src/XTwitterScraper.Tests/Models/X/Users/UserRetrieveBatchParamsTest.cs b/src/XTwitterScraper.Tests/Models/X/Users/UserRetrieveBatchParamsTest.cs index e815b8a..6918b24 100644 --- a/src/XTwitterScraper.Tests/Models/X/Users/UserRetrieveBatchParamsTest.cs +++ b/src/XTwitterScraper.Tests/Models/X/Users/UserRetrieveBatchParamsTest.cs @@ -20,9 +20,11 @@ public void Url_Works() { UserRetrieveBatchParams parameters = new() { Ids = "ids" }; - var url = parameters.Url(new() { ApiKey = "My API Key", BearerToken = "My Bearer Token" }); + var url = parameters.Url(new() { ApiKey = "My API Key" }); - Assert.Equal(new Uri("https://xquik.com/api/v1/x/users/batch?ids=ids"), url); + Assert.True( + TestBase.UrisEqual(new Uri("https://xquik.com/api/v1/x/users/batch?ids=ids"), url) + ); } [Fact] diff --git a/src/XTwitterScraper.Tests/Models/X/Users/UserRetrieveFollowersParamsTest.cs b/src/XTwitterScraper.Tests/Models/X/Users/UserRetrieveFollowersParamsTest.cs index fe0ee59..4d989a5 100644 --- a/src/XTwitterScraper.Tests/Models/X/Users/UserRetrieveFollowersParamsTest.cs +++ b/src/XTwitterScraper.Tests/Models/X/Users/UserRetrieveFollowersParamsTest.cs @@ -63,11 +63,13 @@ public void Url_Works() PageSize = 0, }; - var url = parameters.Url(new() { ApiKey = "My API Key", BearerToken = "My Bearer Token" }); + var url = parameters.Url(new() { ApiKey = "My API Key" }); - Assert.Equal( - new Uri("https://xquik.com/api/v1/x/users/id/followers?cursor=cursor&pageSize=0"), - url + Assert.True( + TestBase.UrisEqual( + new Uri("https://xquik.com/api/v1/x/users/id/followers?cursor=cursor&pageSize=0"), + url + ) ); } diff --git a/src/XTwitterScraper.Tests/Models/X/Users/UserRetrieveFollowersYouKnowParamsTest.cs b/src/XTwitterScraper.Tests/Models/X/Users/UserRetrieveFollowersYouKnowParamsTest.cs index 91d896c..6a2007c 100644 --- a/src/XTwitterScraper.Tests/Models/X/Users/UserRetrieveFollowersYouKnowParamsTest.cs +++ b/src/XTwitterScraper.Tests/Models/X/Users/UserRetrieveFollowersYouKnowParamsTest.cs @@ -46,11 +46,13 @@ public void Url_Works() { UserRetrieveFollowersYouKnowParams parameters = new() { ID = "id", Cursor = "cursor" }; - var url = parameters.Url(new() { ApiKey = "My API Key", BearerToken = "My Bearer Token" }); + var url = parameters.Url(new() { ApiKey = "My API Key" }); - Assert.Equal( - new Uri("https://xquik.com/api/v1/x/users/id/followers-you-know?cursor=cursor"), - url + Assert.True( + TestBase.UrisEqual( + new Uri("https://xquik.com/api/v1/x/users/id/followers-you-know?cursor=cursor"), + url + ) ); } diff --git a/src/XTwitterScraper.Tests/Models/X/Users/UserRetrieveFollowingParamsTest.cs b/src/XTwitterScraper.Tests/Models/X/Users/UserRetrieveFollowingParamsTest.cs index 0ee776e..47784ef 100644 --- a/src/XTwitterScraper.Tests/Models/X/Users/UserRetrieveFollowingParamsTest.cs +++ b/src/XTwitterScraper.Tests/Models/X/Users/UserRetrieveFollowingParamsTest.cs @@ -63,11 +63,13 @@ public void Url_Works() PageSize = 0, }; - var url = parameters.Url(new() { ApiKey = "My API Key", BearerToken = "My Bearer Token" }); + var url = parameters.Url(new() { ApiKey = "My API Key" }); - Assert.Equal( - new Uri("https://xquik.com/api/v1/x/users/id/following?cursor=cursor&pageSize=0"), - url + Assert.True( + TestBase.UrisEqual( + new Uri("https://xquik.com/api/v1/x/users/id/following?cursor=cursor&pageSize=0"), + url + ) ); } diff --git a/src/XTwitterScraper.Tests/Models/X/Users/UserRetrieveLikesParamsTest.cs b/src/XTwitterScraper.Tests/Models/X/Users/UserRetrieveLikesParamsTest.cs index 94144bd..983dcc5 100644 --- a/src/XTwitterScraper.Tests/Models/X/Users/UserRetrieveLikesParamsTest.cs +++ b/src/XTwitterScraper.Tests/Models/X/Users/UserRetrieveLikesParamsTest.cs @@ -46,9 +46,14 @@ public void Url_Works() { UserRetrieveLikesParams parameters = new() { ID = "id", Cursor = "cursor" }; - var url = parameters.Url(new() { ApiKey = "My API Key", BearerToken = "My Bearer Token" }); + var url = parameters.Url(new() { ApiKey = "My API Key" }); - Assert.Equal(new Uri("https://xquik.com/api/v1/x/users/id/likes?cursor=cursor"), url); + Assert.True( + TestBase.UrisEqual( + new Uri("https://xquik.com/api/v1/x/users/id/likes?cursor=cursor"), + url + ) + ); } [Fact] diff --git a/src/XTwitterScraper.Tests/Models/X/Users/UserRetrieveMediaParamsTest.cs b/src/XTwitterScraper.Tests/Models/X/Users/UserRetrieveMediaParamsTest.cs index 98e6829..0dae67d 100644 --- a/src/XTwitterScraper.Tests/Models/X/Users/UserRetrieveMediaParamsTest.cs +++ b/src/XTwitterScraper.Tests/Models/X/Users/UserRetrieveMediaParamsTest.cs @@ -46,9 +46,14 @@ public void Url_Works() { UserRetrieveMediaParams parameters = new() { ID = "id", Cursor = "cursor" }; - var url = parameters.Url(new() { ApiKey = "My API Key", BearerToken = "My Bearer Token" }); + var url = parameters.Url(new() { ApiKey = "My API Key" }); - Assert.Equal(new Uri("https://xquik.com/api/v1/x/users/id/media?cursor=cursor"), url); + Assert.True( + TestBase.UrisEqual( + new Uri("https://xquik.com/api/v1/x/users/id/media?cursor=cursor"), + url + ) + ); } [Fact] diff --git a/src/XTwitterScraper.Tests/Models/X/Users/UserRetrieveMentionsParamsTest.cs b/src/XTwitterScraper.Tests/Models/X/Users/UserRetrieveMentionsParamsTest.cs index 85d4e39..ae91f5c 100644 --- a/src/XTwitterScraper.Tests/Models/X/Users/UserRetrieveMentionsParamsTest.cs +++ b/src/XTwitterScraper.Tests/Models/X/Users/UserRetrieveMentionsParamsTest.cs @@ -72,13 +72,15 @@ public void Url_Works() UntilTime = "untilTime", }; - var url = parameters.Url(new() { ApiKey = "My API Key", BearerToken = "My Bearer Token" }); + var url = parameters.Url(new() { ApiKey = "My API Key" }); - Assert.Equal( - new Uri( - "https://xquik.com/api/v1/x/users/id/mentions?cursor=cursor&sinceTime=sinceTime&untilTime=untilTime" - ), - url + Assert.True( + TestBase.UrisEqual( + new Uri( + "https://xquik.com/api/v1/x/users/id/mentions?cursor=cursor&sinceTime=sinceTime&untilTime=untilTime" + ), + url + ) ); } diff --git a/src/XTwitterScraper.Tests/Models/X/Users/UserRetrieveParamsTest.cs b/src/XTwitterScraper.Tests/Models/X/Users/UserRetrieveParamsTest.cs index d42c4c0..62d9ab5 100644 --- a/src/XTwitterScraper.Tests/Models/X/Users/UserRetrieveParamsTest.cs +++ b/src/XTwitterScraper.Tests/Models/X/Users/UserRetrieveParamsTest.cs @@ -20,9 +20,9 @@ public void Url_Works() { UserRetrieveParams parameters = new() { ID = "id" }; - var url = parameters.Url(new() { ApiKey = "My API Key", BearerToken = "My Bearer Token" }); + var url = parameters.Url(new() { ApiKey = "My API Key" }); - Assert.Equal(new Uri("https://xquik.com/api/v1/x/users/id"), url); + Assert.True(TestBase.UrisEqual(new Uri("https://xquik.com/api/v1/x/users/id"), url)); } [Fact] diff --git a/src/XTwitterScraper.Tests/Models/X/Users/UserRetrieveSearchParamsTest.cs b/src/XTwitterScraper.Tests/Models/X/Users/UserRetrieveSearchParamsTest.cs index 8e6cd48..9d2efd7 100644 --- a/src/XTwitterScraper.Tests/Models/X/Users/UserRetrieveSearchParamsTest.cs +++ b/src/XTwitterScraper.Tests/Models/X/Users/UserRetrieveSearchParamsTest.cs @@ -46,9 +46,14 @@ public void Url_Works() { UserRetrieveSearchParams parameters = new() { Q = "q", Cursor = "cursor" }; - var url = parameters.Url(new() { ApiKey = "My API Key", BearerToken = "My Bearer Token" }); + var url = parameters.Url(new() { ApiKey = "My API Key" }); - Assert.Equal(new Uri("https://xquik.com/api/v1/x/users/search?q=q&cursor=cursor"), url); + Assert.True( + TestBase.UrisEqual( + new Uri("https://xquik.com/api/v1/x/users/search?q=q&cursor=cursor"), + url + ) + ); } [Fact] diff --git a/src/XTwitterScraper.Tests/Models/X/Users/UserRetrieveTweetsParamsTest.cs b/src/XTwitterScraper.Tests/Models/X/Users/UserRetrieveTweetsParamsTest.cs index fdf1550..8d2e741 100644 --- a/src/XTwitterScraper.Tests/Models/X/Users/UserRetrieveTweetsParamsTest.cs +++ b/src/XTwitterScraper.Tests/Models/X/Users/UserRetrieveTweetsParamsTest.cs @@ -72,13 +72,15 @@ public void Url_Works() IncludeReplies = true, }; - var url = parameters.Url(new() { ApiKey = "My API Key", BearerToken = "My Bearer Token" }); + var url = parameters.Url(new() { ApiKey = "My API Key" }); - Assert.Equal( - new Uri( - "https://xquik.com/api/v1/x/users/id/tweets?cursor=cursor&includeParentTweet=true&includeReplies=true" - ), - url + Assert.True( + TestBase.UrisEqual( + new Uri( + "https://xquik.com/api/v1/x/users/id/tweets?cursor=cursor&includeParentTweet=true&includeReplies=true" + ), + url + ) ); } diff --git a/src/XTwitterScraper.Tests/Models/X/Users/UserRetrieveVerifiedFollowersParamsTest.cs b/src/XTwitterScraper.Tests/Models/X/Users/UserRetrieveVerifiedFollowersParamsTest.cs index 37dad8b..e2942b1 100644 --- a/src/XTwitterScraper.Tests/Models/X/Users/UserRetrieveVerifiedFollowersParamsTest.cs +++ b/src/XTwitterScraper.Tests/Models/X/Users/UserRetrieveVerifiedFollowersParamsTest.cs @@ -46,11 +46,13 @@ public void Url_Works() { UserRetrieveVerifiedFollowersParams parameters = new() { ID = "id", Cursor = "cursor" }; - var url = parameters.Url(new() { ApiKey = "My API Key", BearerToken = "My Bearer Token" }); + var url = parameters.Url(new() { ApiKey = "My API Key" }); - Assert.Equal( - new Uri("https://xquik.com/api/v1/x/users/id/verified-followers?cursor=cursor"), - url + Assert.True( + TestBase.UrisEqual( + new Uri("https://xquik.com/api/v1/x/users/id/verified-followers?cursor=cursor"), + url + ) ); } diff --git a/src/XTwitterScraper.Tests/Models/X/XGetArticleParamsTest.cs b/src/XTwitterScraper.Tests/Models/X/XGetArticleParamsTest.cs index d0584af..0072a10 100644 --- a/src/XTwitterScraper.Tests/Models/X/XGetArticleParamsTest.cs +++ b/src/XTwitterScraper.Tests/Models/X/XGetArticleParamsTest.cs @@ -20,9 +20,11 @@ public void Url_Works() { XGetArticleParams parameters = new() { TweetID = "tweetId" }; - var url = parameters.Url(new() { ApiKey = "My API Key", BearerToken = "My Bearer Token" }); + var url = parameters.Url(new() { ApiKey = "My API Key" }); - Assert.Equal(new Uri("https://xquik.com/api/v1/x/articles/tweetId"), url); + Assert.True( + TestBase.UrisEqual(new Uri("https://xquik.com/api/v1/x/articles/tweetId"), url) + ); } [Fact] diff --git a/src/XTwitterScraper.Tests/Models/X/XGetHomeTimelineParamsTest.cs b/src/XTwitterScraper.Tests/Models/X/XGetHomeTimelineParamsTest.cs index 71a55ab..8de94f6 100644 --- a/src/XTwitterScraper.Tests/Models/X/XGetHomeTimelineParamsTest.cs +++ b/src/XTwitterScraper.Tests/Models/X/XGetHomeTimelineParamsTest.cs @@ -57,11 +57,15 @@ public void Url_Works() SeenTweetIds = "seenTweetIds", }; - var url = parameters.Url(new() { ApiKey = "My API Key", BearerToken = "My Bearer Token" }); + var url = parameters.Url(new() { ApiKey = "My API Key" }); - Assert.Equal( - new Uri("https://xquik.com/api/v1/x/timeline?cursor=cursor&seenTweetIds=seenTweetIds"), - url + Assert.True( + TestBase.UrisEqual( + new Uri( + "https://xquik.com/api/v1/x/timeline?cursor=cursor&seenTweetIds=seenTweetIds" + ), + url + ) ); } diff --git a/src/XTwitterScraper.Tests/Models/X/XGetNotificationsParamsTest.cs b/src/XTwitterScraper.Tests/Models/X/XGetNotificationsParamsTest.cs index b81987f..ced9dd0 100644 --- a/src/XTwitterScraper.Tests/Models/X/XGetNotificationsParamsTest.cs +++ b/src/XTwitterScraper.Tests/Models/X/XGetNotificationsParamsTest.cs @@ -52,11 +52,13 @@ public void Url_Works() { X::XGetNotificationsParams parameters = new() { Cursor = "cursor", Type = X::Type.All }; - var url = parameters.Url(new() { ApiKey = "My API Key", BearerToken = "My Bearer Token" }); + var url = parameters.Url(new() { ApiKey = "My API Key" }); - Assert.Equal( - new Uri("https://xquik.com/api/v1/x/notifications?cursor=cursor&type=All"), - url + Assert.True( + TestBase.UrisEqual( + new Uri("https://xquik.com/api/v1/x/notifications?cursor=cursor&type=All"), + url + ) ); } diff --git a/src/XTwitterScraper.Tests/Models/X/XGetTrendsParamsTest.cs b/src/XTwitterScraper.Tests/Models/X/XGetTrendsParamsTest.cs index 2f89428..6acfcaf 100644 --- a/src/XTwitterScraper.Tests/Models/X/XGetTrendsParamsTest.cs +++ b/src/XTwitterScraper.Tests/Models/X/XGetTrendsParamsTest.cs @@ -1 +1,68 @@ +using System; +using XTwitterScraper.Models.X; + namespace XTwitterScraper.Tests.Models.X; + +public class XGetTrendsParamsTest : TestBase +{ + [Fact] + public void FieldRoundtrip_Works() + { + var parameters = new XGetTrendsParams { Count = 1, Woeid = 0 }; + + long expectedCount = 1; + long expectedWoeid = 0; + + Assert.Equal(expectedCount, parameters.Count); + Assert.Equal(expectedWoeid, parameters.Woeid); + } + + [Fact] + public void OptionalNonNullableParamsUnsetAreNotSet_Works() + { + var parameters = new XGetTrendsParams { }; + + Assert.Null(parameters.Count); + Assert.False(parameters.RawQueryData.ContainsKey("count")); + Assert.Null(parameters.Woeid); + Assert.False(parameters.RawQueryData.ContainsKey("woeid")); + } + + [Fact] + public void OptionalNonNullableParamsSetToNullAreNotSet_Works() + { + var parameters = new XGetTrendsParams + { + // Null should be interpreted as omitted for these properties + Count = null, + Woeid = null, + }; + + Assert.Null(parameters.Count); + Assert.False(parameters.RawQueryData.ContainsKey("count")); + Assert.Null(parameters.Woeid); + Assert.False(parameters.RawQueryData.ContainsKey("woeid")); + } + + [Fact] + public void Url_Works() + { + XGetTrendsParams parameters = new() { Count = 1, Woeid = 0 }; + + var url = parameters.Url(new() { ApiKey = "My API Key" }); + + Assert.True( + TestBase.UrisEqual(new Uri("https://xquik.com/api/v1/x/trends?count=1&woeid=0"), url) + ); + } + + [Fact] + public void CopyConstructor_Works() + { + var parameters = new XGetTrendsParams { Count = 1, Woeid = 0 }; + + XGetTrendsParams copied = new(parameters); + + Assert.Equal(parameters, copied); + } +} diff --git a/src/XTwitterScraper.Tests/Services/IntegrationServiceTest.cs b/src/XTwitterScraper.Tests/Services/IntegrationServiceTest.cs deleted file mode 100644 index c9bc18c..0000000 --- a/src/XTwitterScraper.Tests/Services/IntegrationServiceTest.cs +++ /dev/null @@ -1,89 +0,0 @@ -using System.Text.Json; -using System.Threading.Tasks; -using XTwitterScraper.Models; - -namespace XTwitterScraper.Tests.Services; - -public class IntegrationServiceTest : TestBase -{ - [Fact(Skip = "Mock server tests are disabled")] - public async Task Create_Works() - { - var integration = await this.client.Integrations.Create( - new() - { - Config = new("-1001234567890"), - EventTypes = [EventType.TweetNew, EventType.FollowerGained], - Name = "My Telegram Bot", - Type = JsonSerializer.SerializeToElement("telegram"), - }, - TestContext.Current.CancellationToken - ); - integration.Validate(); - } - - [Fact(Skip = "Mock server tests are disabled")] - public async Task Retrieve_Works() - { - var integration = await this.client.Integrations.Retrieve( - "id", - new(), - TestContext.Current.CancellationToken - ); - integration.Validate(); - } - - [Fact(Skip = "Mock server tests are disabled")] - public async Task Update_Works() - { - var integration = await this.client.Integrations.Update( - "id", - new(), - TestContext.Current.CancellationToken - ); - integration.Validate(); - } - - [Fact(Skip = "Mock server tests are disabled")] - public async Task List_Works() - { - var integrations = await this.client.Integrations.List( - new(), - TestContext.Current.CancellationToken - ); - integrations.Validate(); - } - - [Fact(Skip = "Mock server tests are disabled")] - public async Task Delete_Works() - { - var integration = await this.client.Integrations.Delete( - "id", - new(), - TestContext.Current.CancellationToken - ); - integration.Validate(); - } - - [Fact(Skip = "Mock server tests are disabled")] - public async Task ListDeliveries_Works() - { - var response = await this.client.Integrations.ListDeliveries( - "id", - new(), - TestContext.Current.CancellationToken - ); - response.Validate(); - } - - [Fact(Skip = "Mock server tests are disabled")] - public async Task SendTest_Works() - { - var response = await this.client.Integrations.SendTest( - "id", - new(), - TestContext.Current.CancellationToken - ); - response.Validate(); - } -} diff --git a/src/XTwitterScraper.Tests/Services/MonitorServiceTest.cs b/src/XTwitterScraper.Tests/Services/MonitorServiceTest.cs index ac3c150..be5d1f3 100644 --- a/src/XTwitterScraper.Tests/Services/MonitorServiceTest.cs +++ b/src/XTwitterScraper.Tests/Services/MonitorServiceTest.cs @@ -11,7 +11,7 @@ public async Task Create_Works() var monitor = await this.client.Monitors.Create( new() { - EventTypes = [EventType.TweetNew, EventType.FollowerGained], + EventTypes = [EventType.TweetNew, EventType.TweetReply], Username = "elonmusk", }, TestContext.Current.CancellationToken diff --git a/src/XTwitterScraper.Tests/Services/WebhookServiceTest.cs b/src/XTwitterScraper.Tests/Services/WebhookServiceTest.cs index a59306f..1d94d0d 100644 --- a/src/XTwitterScraper.Tests/Services/WebhookServiceTest.cs +++ b/src/XTwitterScraper.Tests/Services/WebhookServiceTest.cs @@ -11,7 +11,7 @@ public async Task Create_Works() var webhook = await this.client.Webhooks.Create( new() { - EventTypes = [EventType.TweetNew, EventType.FollowerGained], + EventTypes = [EventType.TweetNew, EventType.TweetReply], UrlValue = "https://example.com/webhook", }, TestContext.Current.CancellationToken diff --git a/src/XTwitterScraper.Tests/Services/X/TweetServiceTest.cs b/src/XTwitterScraper.Tests/Services/X/TweetServiceTest.cs index d84cb5a..c6c60b0 100644 --- a/src/XTwitterScraper.Tests/Services/X/TweetServiceTest.cs +++ b/src/XTwitterScraper.Tests/Services/X/TweetServiceTest.cs @@ -8,7 +8,7 @@ public class TweetServiceTest : TestBase public async Task Create_Works() { var tweet = await this.client.X.Tweets.Create( - new() { Account = "@elonmusk", Text = "Just launched our new feature!" }, + new() { Account = "@elonmusk" }, TestContext.Current.CancellationToken ); tweet.Validate(); diff --git a/src/XTwitterScraper.Tests/TestBase.cs b/src/XTwitterScraper.Tests/TestBase.cs index e709b24..686ed6e 100644 --- a/src/XTwitterScraper.Tests/TestBase.cs +++ b/src/XTwitterScraper.Tests/TestBase.cs @@ -1,4 +1,6 @@ using System; +using System.Collections.Generic; +using System.Linq; using XTwitterScraper; namespace XTwitterScraper.Tests; @@ -14,7 +16,44 @@ public TestBase() BaseUrl = Environment.GetEnvironmentVariable("TEST_API_BASE_URL") ?? "http://localhost:4010", ApiKey = "My API Key", - BearerToken = "My Bearer Token", }; } + + internal static bool UrisEqual(Uri uri1, Uri uri2) + { + if ( + uri1.Scheme != uri2.Scheme + || uri1.Host != uri2.Host + || uri1.Port != uri2.Port + || uri1.AbsolutePath != uri2.AbsolutePath + ) + { + return false; + } + + var query1 = ParseQueryString(uri1.Query); + var query2 = ParseQueryString(uri2.Query); + + return Enumerable.SequenceEqual(query1, query2); + } + + static SortedDictionary ParseQueryString(string query) + { + var ret = new SortedDictionary(StringComparer.Ordinal); + + if (string.IsNullOrEmpty(query)) + return ret; + + var pairs = query.TrimStart('?').Split(['&'], StringSplitOptions.RemoveEmptyEntries); + + foreach (var pair in pairs) + { + var parts = pair.Split(['&'], 2); + var key = Uri.UnescapeDataString(parts[0]); + var value = parts.Length > 1 ? Uri.UnescapeDataString(parts[1]) : string.Empty; + ret[key] = value; + } + + return ret; + } } diff --git a/src/XTwitterScraper/Core/ModelBase.cs b/src/XTwitterScraper/Core/ModelBase.cs index 6c33f19..50e4c96 100644 --- a/src/XTwitterScraper/Core/ModelBase.cs +++ b/src/XTwitterScraper/Core/ModelBase.cs @@ -6,6 +6,7 @@ using XTwitterScraper.Models.Draws; using XTwitterScraper.Models.Radar; using XTwitterScraper.Models.Subscribe; +using XTwitterScraper.Models.X.Accounts; using Drafts = XTwitterScraper.Models.Drafts; using Extractions = XTwitterScraper.Models.Extractions; using Tickets = XTwitterScraper.Models.Support.Tickets; @@ -40,6 +41,9 @@ protected ModelBase(ModelBase modelBase) new ApiEnumConverter(), new ApiEnumConverter(), new ApiEnumConverter(), + new ApiEnumConverter(), + new ApiEnumConverter(), + new ApiEnumConverter(), new ApiEnumConverter(), new ApiEnumConverter(), new ApiEnumConverter(), @@ -54,6 +58,10 @@ protected ModelBase(ModelBase modelBase) new ApiEnumConverter(), new ApiEnumConverter(), new ApiEnumConverter(), + new ApiEnumConverter(), + new ApiEnumConverter(), + new ApiEnumConverter(), + new ApiEnumConverter(), new ApiEnumConverter(), }, }; diff --git a/src/XTwitterScraper/Core/ParamsBase.cs b/src/XTwitterScraper/Core/ParamsBase.cs index b36c76d..6e400ca 100644 --- a/src/XTwitterScraper/Core/ParamsBase.cs +++ b/src/XTwitterScraper/Core/ParamsBase.cs @@ -156,7 +156,7 @@ JsonElement element } } - internal string QueryString(ClientOptions options, SecurityOptions security) + internal string QueryString(ClientOptions options) { NameValueCollection collection = new(); foreach (var item in this.RawQueryData) @@ -189,22 +189,18 @@ internal string QueryString(ClientOptions options, SecurityOptions security) return null; } - internal static void AddDefaultHeaders( - HttpRequestMessage request, - ClientOptions options, - SecurityOptions security - ) + internal static void AddDefaultHeaders(HttpRequestMessage request, ClientOptions options) { foreach (var header in defaultHeaders) { request.Headers.Add(header.Key, header.Value); } - if (security.ApiKey && options.ApiKey != null) + if (options.ApiKey != null) { request.Headers.Add("X-Api-Key", options.ApiKey); } - if (security.OAuthBearer && options.BearerToken != null) + if (options.BearerToken != null) { request.Headers.Add("Authorization", string.Format("Bearer {0}", options.BearerToken)); } diff --git a/src/XTwitterScraper/Core/SecurityOptions.cs b/src/XTwitterScraper/Core/SecurityOptions.cs deleted file mode 100644 index e2e1ef2..0000000 --- a/src/XTwitterScraper/Core/SecurityOptions.cs +++ /dev/null @@ -1,14 +0,0 @@ -using System; - -namespace XTwitterScraper.Core; - -readonly record struct SecurityOptions -{ - public SecurityOptions() { } - - public Boolean ApiKey { get; init; } = false; - - public Boolean OAuthBearer { get; init; } = false; - - public static SecurityOptions All() => new() { ApiKey = true, OAuthBearer = true }; -} diff --git a/src/XTwitterScraper/IXTwitterScraperClient.cs b/src/XTwitterScraper/IXTwitterScraperClient.cs index 62c44e4..e7703d4 100644 --- a/src/XTwitterScraper/IXTwitterScraperClient.cs +++ b/src/XTwitterScraper/IXTwitterScraperClient.cs @@ -80,14 +80,10 @@ public interface IXTwitterScraperClient : IDisposable IWebhookService Webhooks { get; } - IIntegrationService Integrations { get; } - IXService X { get; } ITrendService Trends { get; } - IBotService Bot { get; } - ISupportService Support { get; } ICreditService Credits { get; } @@ -151,14 +147,10 @@ public interface IXTwitterScraperClientWithRawResponse : IDisposable IWebhookServiceWithRawResponse Webhooks { get; } - IIntegrationServiceWithRawResponse Integrations { get; } - IXServiceWithRawResponse X { get; } ITrendServiceWithRawResponse Trends { get; } - IBotServiceWithRawResponse Bot { get; } - ISupportServiceWithRawResponse Support { get; } ICreditServiceWithRawResponse Credits { get; } diff --git a/src/XTwitterScraper/Models/Account/AccountRetrieveParams.cs b/src/XTwitterScraper/Models/Account/AccountRetrieveParams.cs index efa9533..5a3c130 100644 --- a/src/XTwitterScraper/Models/Account/AccountRetrieveParams.cs +++ b/src/XTwitterScraper/Models/Account/AccountRetrieveParams.cs @@ -88,13 +88,13 @@ public override Uri Url(ClientOptions options) { return new UriBuilder(options.BaseUrl.ToString().TrimEnd('/') + "/account") { - Query = this.QueryString(options, new() { ApiKey = true }), + Query = this.QueryString(options), }.Uri; } internal override void AddHeadersToRequest(HttpRequestMessage request, ClientOptions options) { - ParamsBase.AddDefaultHeaders(request, options, new() { ApiKey = true }); + ParamsBase.AddDefaultHeaders(request, options); foreach (var item in this.RawHeaderData) { ParamsBase.AddHeaderElementToRequest(request, item.Key, item.Value); diff --git a/src/XTwitterScraper/Models/Account/AccountRetrieveResponse.cs b/src/XTwitterScraper/Models/Account/AccountRetrieveResponse.cs index 59a4443..dc1f572 100644 --- a/src/XTwitterScraper/Models/Account/AccountRetrieveResponse.cs +++ b/src/XTwitterScraper/Models/Account/AccountRetrieveResponse.cs @@ -42,12 +42,12 @@ public required ApiEnum Plan init { this._rawData.Set("plan", value); } } - public CurrentPeriod? CurrentPeriod + public CreditInfo? CreditInfo { get { this._rawData.Freeze(); - return this._rawData.GetNullableClass("currentPeriod"); + return this._rawData.GetNullableClass("creditInfo"); } init { @@ -56,7 +56,7 @@ public CurrentPeriod? CurrentPeriod return; } - this._rawData.Set("currentPeriod", value); + this._rawData.Set("creditInfo", value); } } @@ -66,7 +66,7 @@ public override void Validate() _ = this.MonitorsAllowed; _ = this.MonitorsUsed; this.Plan.Validate(); - this.CurrentPeriod?.Validate(); + this.CreditInfo?.Validate(); } public AccountRetrieveResponse() { } @@ -147,78 +147,89 @@ public override void Write(Utf8JsonWriter writer, Plan value, JsonSerializerOpti } } -[JsonConverter(typeof(JsonModelConverter))] -public sealed record class CurrentPeriod : JsonModel +[JsonConverter(typeof(JsonModelConverter))] +public sealed record class CreditInfo : JsonModel { - public required DateTimeOffset End + public required bool AutoTopupEnabled { get { this._rawData.Freeze(); - return this._rawData.GetNotNullStruct("end"); + return this._rawData.GetNotNullStruct("autoTopupEnabled"); } - init { this._rawData.Set("end", value); } + init { this._rawData.Set("autoTopupEnabled", value); } } - public required DateTimeOffset Start + public required long Balance { get { this._rawData.Freeze(); - return this._rawData.GetNotNullStruct("start"); + return this._rawData.GetNotNullStruct("balance"); } - init { this._rawData.Set("start", value); } + init { this._rawData.Set("balance", value); } } - public required double UsagePercent + public required long LifetimePurchased { get { this._rawData.Freeze(); - return this._rawData.GetNotNullStruct("usagePercent"); + return this._rawData.GetNotNullStruct("lifetimePurchased"); } - init { this._rawData.Set("usagePercent", value); } + init { this._rawData.Set("lifetimePurchased", value); } + } + + public required long LifetimeUsed + { + get + { + this._rawData.Freeze(); + return this._rawData.GetNotNullStruct("lifetimeUsed"); + } + init { this._rawData.Set("lifetimeUsed", value); } } /// public override void Validate() { - _ = this.End; - _ = this.Start; - _ = this.UsagePercent; + _ = this.AutoTopupEnabled; + _ = this.Balance; + _ = this.LifetimePurchased; + _ = this.LifetimeUsed; } - public CurrentPeriod() { } + public CreditInfo() { } #pragma warning disable CS8618 [SetsRequiredMembers] - public CurrentPeriod(CurrentPeriod currentPeriod) - : base(currentPeriod) { } + public CreditInfo(CreditInfo creditInfo) + : base(creditInfo) { } #pragma warning restore CS8618 - public CurrentPeriod(IReadOnlyDictionary rawData) + public CreditInfo(IReadOnlyDictionary rawData) { this._rawData = new(rawData); } #pragma warning disable CS8618 [SetsRequiredMembers] - CurrentPeriod(FrozenDictionary rawData) + CreditInfo(FrozenDictionary rawData) { this._rawData = new(rawData); } #pragma warning restore CS8618 - /// - public static CurrentPeriod FromRawUnchecked(IReadOnlyDictionary rawData) + /// + public static CreditInfo FromRawUnchecked(IReadOnlyDictionary rawData) { return new(FrozenDictionary.ToFrozenDictionary(rawData)); } } -class CurrentPeriodFromRaw : IFromRawJson +class CreditInfoFromRaw : IFromRawJson { /// - public CurrentPeriod FromRawUnchecked(IReadOnlyDictionary rawData) => - CurrentPeriod.FromRawUnchecked(rawData); + public CreditInfo FromRawUnchecked(IReadOnlyDictionary rawData) => + CreditInfo.FromRawUnchecked(rawData); } diff --git a/src/XTwitterScraper/Models/Account/AccountSetXUsernameParams.cs b/src/XTwitterScraper/Models/Account/AccountSetXUsernameParams.cs index e3c2322..7f32c6f 100644 --- a/src/XTwitterScraper/Models/Account/AccountSetXUsernameParams.cs +++ b/src/XTwitterScraper/Models/Account/AccountSetXUsernameParams.cs @@ -119,7 +119,7 @@ public override Uri Url(ClientOptions options) { return new UriBuilder(options.BaseUrl.ToString().TrimEnd('/') + "/account/x-identity") { - Query = this.QueryString(options, SecurityOptions.All()), + Query = this.QueryString(options), }.Uri; } @@ -134,7 +134,7 @@ public override Uri Url(ClientOptions options) internal override void AddHeadersToRequest(HttpRequestMessage request, ClientOptions options) { - ParamsBase.AddDefaultHeaders(request, options, SecurityOptions.All()); + ParamsBase.AddDefaultHeaders(request, options); foreach (var item in this.RawHeaderData) { ParamsBase.AddHeaderElementToRequest(request, item.Key, item.Value); diff --git a/src/XTwitterScraper/Models/Account/AccountUpdateLocaleParams.cs b/src/XTwitterScraper/Models/Account/AccountUpdateLocaleParams.cs index e392875..87d54d7 100644 --- a/src/XTwitterScraper/Models/Account/AccountUpdateLocaleParams.cs +++ b/src/XTwitterScraper/Models/Account/AccountUpdateLocaleParams.cs @@ -118,7 +118,7 @@ public override Uri Url(ClientOptions options) { return new UriBuilder(options.BaseUrl.ToString().TrimEnd('/') + "/account") { - Query = this.QueryString(options, new() { ApiKey = true }), + Query = this.QueryString(options), }.Uri; } @@ -133,7 +133,7 @@ public override Uri Url(ClientOptions options) internal override void AddHeadersToRequest(HttpRequestMessage request, ClientOptions options) { - ParamsBase.AddDefaultHeaders(request, options, new() { ApiKey = true }); + ParamsBase.AddDefaultHeaders(request, options); foreach (var item in this.RawHeaderData) { ParamsBase.AddHeaderElementToRequest(request, item.Key, item.Value); diff --git a/src/XTwitterScraper/Models/ApiKeys/ApiKeyCreateParams.cs b/src/XTwitterScraper/Models/ApiKeys/ApiKeyCreateParams.cs index feeeab2..2c9611b 100644 --- a/src/XTwitterScraper/Models/ApiKeys/ApiKeyCreateParams.cs +++ b/src/XTwitterScraper/Models/ApiKeys/ApiKeyCreateParams.cs @@ -124,7 +124,7 @@ public override Uri Url(ClientOptions options) { return new UriBuilder(options.BaseUrl.ToString().TrimEnd('/') + "/api-keys") { - Query = this.QueryString(options, new() { ApiKey = true }), + Query = this.QueryString(options), }.Uri; } @@ -139,7 +139,7 @@ public override Uri Url(ClientOptions options) internal override void AddHeadersToRequest(HttpRequestMessage request, ClientOptions options) { - ParamsBase.AddDefaultHeaders(request, options, new() { ApiKey = true }); + ParamsBase.AddDefaultHeaders(request, options); foreach (var item in this.RawHeaderData) { ParamsBase.AddHeaderElementToRequest(request, item.Key, item.Value); diff --git a/src/XTwitterScraper/Models/ApiKeys/ApiKeyListParams.cs b/src/XTwitterScraper/Models/ApiKeys/ApiKeyListParams.cs index 94f7b5d..986cf50 100644 --- a/src/XTwitterScraper/Models/ApiKeys/ApiKeyListParams.cs +++ b/src/XTwitterScraper/Models/ApiKeys/ApiKeyListParams.cs @@ -88,13 +88,13 @@ public override Uri Url(ClientOptions options) { return new UriBuilder(options.BaseUrl.ToString().TrimEnd('/') + "/api-keys") { - Query = this.QueryString(options, new() { ApiKey = true }), + Query = this.QueryString(options), }.Uri; } internal override void AddHeadersToRequest(HttpRequestMessage request, ClientOptions options) { - ParamsBase.AddDefaultHeaders(request, options, new() { ApiKey = true }); + ParamsBase.AddDefaultHeaders(request, options); foreach (var item in this.RawHeaderData) { ParamsBase.AddHeaderElementToRequest(request, item.Key, item.Value); diff --git a/src/XTwitterScraper/Models/ApiKeys/ApiKeyRevokeParams.cs b/src/XTwitterScraper/Models/ApiKeys/ApiKeyRevokeParams.cs index 28351a2..a087f39 100644 --- a/src/XTwitterScraper/Models/ApiKeys/ApiKeyRevokeParams.cs +++ b/src/XTwitterScraper/Models/ApiKeys/ApiKeyRevokeParams.cs @@ -101,13 +101,13 @@ public override Uri Url(ClientOptions options) options.BaseUrl.ToString().TrimEnd('/') + string.Format("/api-keys/{0}", this.ID) ) { - Query = this.QueryString(options, new() { ApiKey = true }), + Query = this.QueryString(options), }.Uri; } internal override void AddHeadersToRequest(HttpRequestMessage request, ClientOptions options) { - ParamsBase.AddDefaultHeaders(request, options, new() { ApiKey = true }); + ParamsBase.AddDefaultHeaders(request, options); foreach (var item in this.RawHeaderData) { ParamsBase.AddHeaderElementToRequest(request, item.Key, item.Value); diff --git a/src/XTwitterScraper/Models/Compose/ComposeCreateParams.cs b/src/XTwitterScraper/Models/Compose/ComposeCreateParams.cs index 93ef9ce..d645fe4 100644 --- a/src/XTwitterScraper/Models/Compose/ComposeCreateParams.cs +++ b/src/XTwitterScraper/Models/Compose/ComposeCreateParams.cs @@ -331,7 +331,7 @@ public override Uri Url(ClientOptions options) { return new UriBuilder(options.BaseUrl.ToString().TrimEnd('/') + "/compose") { - Query = this.QueryString(options, SecurityOptions.All()), + Query = this.QueryString(options), }.Uri; } @@ -346,7 +346,7 @@ public override Uri Url(ClientOptions options) internal override void AddHeadersToRequest(HttpRequestMessage request, ClientOptions options) { - ParamsBase.AddDefaultHeaders(request, options, SecurityOptions.All()); + ParamsBase.AddDefaultHeaders(request, options); foreach (var item in this.RawHeaderData) { ParamsBase.AddHeaderElementToRequest(request, item.Key, item.Value); diff --git a/src/XTwitterScraper/Models/Credits/CreditRetrieveBalanceParams.cs b/src/XTwitterScraper/Models/Credits/CreditRetrieveBalanceParams.cs index 550bc03..344e8fb 100644 --- a/src/XTwitterScraper/Models/Credits/CreditRetrieveBalanceParams.cs +++ b/src/XTwitterScraper/Models/Credits/CreditRetrieveBalanceParams.cs @@ -88,13 +88,13 @@ public override Uri Url(ClientOptions options) { return new UriBuilder(options.BaseUrl.ToString().TrimEnd('/') + "/credits") { - Query = this.QueryString(options, SecurityOptions.All()), + Query = this.QueryString(options), }.Uri; } internal override void AddHeadersToRequest(HttpRequestMessage request, ClientOptions options) { - ParamsBase.AddDefaultHeaders(request, options, SecurityOptions.All()); + ParamsBase.AddDefaultHeaders(request, options); foreach (var item in this.RawHeaderData) { ParamsBase.AddHeaderElementToRequest(request, item.Key, item.Value); diff --git a/src/XTwitterScraper/Models/Credits/CreditTopupBalanceParams.cs b/src/XTwitterScraper/Models/Credits/CreditTopupBalanceParams.cs index 0dfc5c7..03ac360 100644 --- a/src/XTwitterScraper/Models/Credits/CreditTopupBalanceParams.cs +++ b/src/XTwitterScraper/Models/Credits/CreditTopupBalanceParams.cs @@ -119,7 +119,7 @@ public override Uri Url(ClientOptions options) { return new UriBuilder(options.BaseUrl.ToString().TrimEnd('/') + "/credits/topup") { - Query = this.QueryString(options, SecurityOptions.All()), + Query = this.QueryString(options), }.Uri; } @@ -134,7 +134,7 @@ public override Uri Url(ClientOptions options) internal override void AddHeadersToRequest(HttpRequestMessage request, ClientOptions options) { - ParamsBase.AddDefaultHeaders(request, options, SecurityOptions.All()); + ParamsBase.AddDefaultHeaders(request, options); foreach (var item in this.RawHeaderData) { ParamsBase.AddHeaderElementToRequest(request, item.Key, item.Value); diff --git a/src/XTwitterScraper/Models/Drafts/DraftCreateParams.cs b/src/XTwitterScraper/Models/Drafts/DraftCreateParams.cs index 9c93447..00a2b66 100644 --- a/src/XTwitterScraper/Models/Drafts/DraftCreateParams.cs +++ b/src/XTwitterScraper/Models/Drafts/DraftCreateParams.cs @@ -154,7 +154,7 @@ public override Uri Url(ClientOptions options) { return new UriBuilder(options.BaseUrl.ToString().TrimEnd('/') + "/drafts") { - Query = this.QueryString(options, SecurityOptions.All()), + Query = this.QueryString(options), }.Uri; } @@ -169,7 +169,7 @@ public override Uri Url(ClientOptions options) internal override void AddHeadersToRequest(HttpRequestMessage request, ClientOptions options) { - ParamsBase.AddDefaultHeaders(request, options, SecurityOptions.All()); + ParamsBase.AddDefaultHeaders(request, options); foreach (var item in this.RawHeaderData) { ParamsBase.AddHeaderElementToRequest(request, item.Key, item.Value); diff --git a/src/XTwitterScraper/Models/Drafts/DraftDeleteParams.cs b/src/XTwitterScraper/Models/Drafts/DraftDeleteParams.cs index 8a9463a..f649bc4 100644 --- a/src/XTwitterScraper/Models/Drafts/DraftDeleteParams.cs +++ b/src/XTwitterScraper/Models/Drafts/DraftDeleteParams.cs @@ -101,13 +101,13 @@ public override Uri Url(ClientOptions options) options.BaseUrl.ToString().TrimEnd('/') + string.Format("/drafts/{0}", this.ID) ) { - Query = this.QueryString(options, SecurityOptions.All()), + Query = this.QueryString(options), }.Uri; } internal override void AddHeadersToRequest(HttpRequestMessage request, ClientOptions options) { - ParamsBase.AddDefaultHeaders(request, options, SecurityOptions.All()); + ParamsBase.AddDefaultHeaders(request, options); foreach (var item in this.RawHeaderData) { ParamsBase.AddHeaderElementToRequest(request, item.Key, item.Value); diff --git a/src/XTwitterScraper/Models/Drafts/DraftListParams.cs b/src/XTwitterScraper/Models/Drafts/DraftListParams.cs index bea8198..478cece 100644 --- a/src/XTwitterScraper/Models/Drafts/DraftListParams.cs +++ b/src/XTwitterScraper/Models/Drafts/DraftListParams.cs @@ -130,13 +130,13 @@ public override Uri Url(ClientOptions options) { return new UriBuilder(options.BaseUrl.ToString().TrimEnd('/') + "/drafts") { - Query = this.QueryString(options, SecurityOptions.All()), + Query = this.QueryString(options), }.Uri; } internal override void AddHeadersToRequest(HttpRequestMessage request, ClientOptions options) { - ParamsBase.AddDefaultHeaders(request, options, SecurityOptions.All()); + ParamsBase.AddDefaultHeaders(request, options); foreach (var item in this.RawHeaderData) { ParamsBase.AddHeaderElementToRequest(request, item.Key, item.Value); diff --git a/src/XTwitterScraper/Models/Drafts/DraftRetrieveParams.cs b/src/XTwitterScraper/Models/Drafts/DraftRetrieveParams.cs index b4fc3bb..fa6ccdd 100644 --- a/src/XTwitterScraper/Models/Drafts/DraftRetrieveParams.cs +++ b/src/XTwitterScraper/Models/Drafts/DraftRetrieveParams.cs @@ -101,13 +101,13 @@ public override Uri Url(ClientOptions options) options.BaseUrl.ToString().TrimEnd('/') + string.Format("/drafts/{0}", this.ID) ) { - Query = this.QueryString(options, SecurityOptions.All()), + Query = this.QueryString(options), }.Uri; } internal override void AddHeadersToRequest(HttpRequestMessage request, ClientOptions options) { - ParamsBase.AddDefaultHeaders(request, options, SecurityOptions.All()); + ParamsBase.AddDefaultHeaders(request, options); foreach (var item in this.RawHeaderData) { ParamsBase.AddHeaderElementToRequest(request, item.Key, item.Value); diff --git a/src/XTwitterScraper/Models/Draws/DrawExportParams.cs b/src/XTwitterScraper/Models/Draws/DrawExportParams.cs index 1fd4174..2a96fad 100644 --- a/src/XTwitterScraper/Models/Draws/DrawExportParams.cs +++ b/src/XTwitterScraper/Models/Draws/DrawExportParams.cs @@ -147,13 +147,13 @@ public virtual bool Equals(DrawExportParams? other) options.BaseUrl.ToString().TrimEnd('/') + string.Format("/draws/{0}/export", this.ID) ) { - Query = this.QueryString(options, SecurityOptions.All()), + Query = this.QueryString(options), }.Uri; } internal override void AddHeadersToRequest(HttpRequestMessage request, ClientOptions options) { - ParamsBase.AddDefaultHeaders(request, options, SecurityOptions.All()); + ParamsBase.AddDefaultHeaders(request, options); request.Headers.Add("Accept", "application/octet-stream"); foreach (var item in this.RawHeaderData) { diff --git a/src/XTwitterScraper/Models/Draws/DrawListParams.cs b/src/XTwitterScraper/Models/Draws/DrawListParams.cs index d33d5ee..cbecd4f 100644 --- a/src/XTwitterScraper/Models/Draws/DrawListParams.cs +++ b/src/XTwitterScraper/Models/Draws/DrawListParams.cs @@ -130,13 +130,13 @@ public override Uri Url(ClientOptions options) { return new UriBuilder(options.BaseUrl.ToString().TrimEnd('/') + "/draws") { - Query = this.QueryString(options, SecurityOptions.All()), + Query = this.QueryString(options), }.Uri; } internal override void AddHeadersToRequest(HttpRequestMessage request, ClientOptions options) { - ParamsBase.AddDefaultHeaders(request, options, SecurityOptions.All()); + ParamsBase.AddDefaultHeaders(request, options); foreach (var item in this.RawHeaderData) { ParamsBase.AddHeaderElementToRequest(request, item.Key, item.Value); diff --git a/src/XTwitterScraper/Models/Draws/DrawRetrieveParams.cs b/src/XTwitterScraper/Models/Draws/DrawRetrieveParams.cs index 4709f92..8cb2ada 100644 --- a/src/XTwitterScraper/Models/Draws/DrawRetrieveParams.cs +++ b/src/XTwitterScraper/Models/Draws/DrawRetrieveParams.cs @@ -101,13 +101,13 @@ public override Uri Url(ClientOptions options) options.BaseUrl.ToString().TrimEnd('/') + string.Format("/draws/{0}", this.ID) ) { - Query = this.QueryString(options, SecurityOptions.All()), + Query = this.QueryString(options), }.Uri; } internal override void AddHeadersToRequest(HttpRequestMessage request, ClientOptions options) { - ParamsBase.AddDefaultHeaders(request, options, SecurityOptions.All()); + ParamsBase.AddDefaultHeaders(request, options); foreach (var item in this.RawHeaderData) { ParamsBase.AddHeaderElementToRequest(request, item.Key, item.Value); diff --git a/src/XTwitterScraper/Models/Draws/DrawRunParams.cs b/src/XTwitterScraper/Models/Draws/DrawRunParams.cs index db21031..249bf73 100644 --- a/src/XTwitterScraper/Models/Draws/DrawRunParams.cs +++ b/src/XTwitterScraper/Models/Draws/DrawRunParams.cs @@ -324,7 +324,7 @@ public override Uri Url(ClientOptions options) { return new UriBuilder(options.BaseUrl.ToString().TrimEnd('/') + "/draws") { - Query = this.QueryString(options, SecurityOptions.All()), + Query = this.QueryString(options), }.Uri; } @@ -339,7 +339,7 @@ public override Uri Url(ClientOptions options) internal override void AddHeadersToRequest(HttpRequestMessage request, ClientOptions options) { - ParamsBase.AddDefaultHeaders(request, options, SecurityOptions.All()); + ParamsBase.AddDefaultHeaders(request, options); foreach (var item in this.RawHeaderData) { ParamsBase.AddHeaderElementToRequest(request, item.Key, item.Value); diff --git a/src/XTwitterScraper/Models/Error.cs b/src/XTwitterScraper/Models/Error.cs index c5d163b..3f77851 100644 --- a/src/XTwitterScraper/Models/Error.cs +++ b/src/XTwitterScraper/Models/Error.cs @@ -85,17 +85,17 @@ public enum ErrorError InvalidTweetID, InvalidTweetUrl, InvalidUsername, + InsufficientCredits, MissingParams, MissingQuery, MonitorAlreadyExists, MonitorLimitReached, + NoCredits, NoSubscription, NotFound, - StreamRegistrationFailed, SubscriptionInactive, TweetNotFound, Unauthenticated, - UsageLimitReached, UserNotFound, WebhookInactive, XApiRateLimited, @@ -122,17 +122,17 @@ JsonSerializerOptions options "invalid_tweet_id" => ErrorError.InvalidTweetID, "invalid_tweet_url" => ErrorError.InvalidTweetUrl, "invalid_username" => ErrorError.InvalidUsername, + "insufficient_credits" => ErrorError.InsufficientCredits, "missing_params" => ErrorError.MissingParams, "missing_query" => ErrorError.MissingQuery, "monitor_already_exists" => ErrorError.MonitorAlreadyExists, "monitor_limit_reached" => ErrorError.MonitorLimitReached, + "no_credits" => ErrorError.NoCredits, "no_subscription" => ErrorError.NoSubscription, "not_found" => ErrorError.NotFound, - "stream_registration_failed" => ErrorError.StreamRegistrationFailed, "subscription_inactive" => ErrorError.SubscriptionInactive, "tweet_not_found" => ErrorError.TweetNotFound, "unauthenticated" => ErrorError.Unauthenticated, - "usage_limit_reached" => ErrorError.UsageLimitReached, "user_not_found" => ErrorError.UserNotFound, "webhook_inactive" => ErrorError.WebhookInactive, "x_api_rate_limited" => ErrorError.XApiRateLimited, @@ -161,17 +161,17 @@ JsonSerializerOptions options ErrorError.InvalidTweetID => "invalid_tweet_id", ErrorError.InvalidTweetUrl => "invalid_tweet_url", ErrorError.InvalidUsername => "invalid_username", + ErrorError.InsufficientCredits => "insufficient_credits", ErrorError.MissingParams => "missing_params", ErrorError.MissingQuery => "missing_query", ErrorError.MonitorAlreadyExists => "monitor_already_exists", ErrorError.MonitorLimitReached => "monitor_limit_reached", + ErrorError.NoCredits => "no_credits", ErrorError.NoSubscription => "no_subscription", ErrorError.NotFound => "not_found", - ErrorError.StreamRegistrationFailed => "stream_registration_failed", ErrorError.SubscriptionInactive => "subscription_inactive", ErrorError.TweetNotFound => "tweet_not_found", ErrorError.Unauthenticated => "unauthenticated", - ErrorError.UsageLimitReached => "usage_limit_reached", ErrorError.UserNotFound => "user_not_found", ErrorError.WebhookInactive => "webhook_inactive", ErrorError.XApiRateLimited => "x_api_rate_limited", diff --git a/src/XTwitterScraper/Models/EventType.cs b/src/XTwitterScraper/Models/EventType.cs index 4edb505..f8f09b5 100644 --- a/src/XTwitterScraper/Models/EventType.cs +++ b/src/XTwitterScraper/Models/EventType.cs @@ -15,8 +15,6 @@ public enum EventType TweetReply, TweetRetweet, TweetQuote, - FollowerGained, - FollowerLost, } sealed class EventTypeConverter : JsonConverter @@ -33,8 +31,6 @@ JsonSerializerOptions options "tweet.reply" => EventType.TweetReply, "tweet.retweet" => EventType.TweetRetweet, "tweet.quote" => EventType.TweetQuote, - "follower.gained" => EventType.FollowerGained, - "follower.lost" => EventType.FollowerLost, _ => (EventType)(-1), }; } @@ -53,8 +49,6 @@ JsonSerializerOptions options EventType.TweetReply => "tweet.reply", EventType.TweetRetweet => "tweet.retweet", EventType.TweetQuote => "tweet.quote", - EventType.FollowerGained => "follower.gained", - EventType.FollowerLost => "follower.lost", _ => throw new XTwitterScraperInvalidDataException( string.Format("Invalid value '{0}' in {1}", value, nameof(value)) ), diff --git a/src/XTwitterScraper/Models/Events/EventListParams.cs b/src/XTwitterScraper/Models/Events/EventListParams.cs index ef5ac95..6fb729b 100644 --- a/src/XTwitterScraper/Models/Events/EventListParams.cs +++ b/src/XTwitterScraper/Models/Events/EventListParams.cs @@ -172,13 +172,13 @@ public override Uri Url(ClientOptions options) { return new UriBuilder(options.BaseUrl.ToString().TrimEnd('/') + "/events") { - Query = this.QueryString(options, new() { ApiKey = true }), + Query = this.QueryString(options), }.Uri; } internal override void AddHeadersToRequest(HttpRequestMessage request, ClientOptions options) { - ParamsBase.AddDefaultHeaders(request, options, new() { ApiKey = true }); + ParamsBase.AddDefaultHeaders(request, options); foreach (var item in this.RawHeaderData) { ParamsBase.AddHeaderElementToRequest(request, item.Key, item.Value); diff --git a/src/XTwitterScraper/Models/Events/EventRetrieveParams.cs b/src/XTwitterScraper/Models/Events/EventRetrieveParams.cs index 1cc2ebb..af696fa 100644 --- a/src/XTwitterScraper/Models/Events/EventRetrieveParams.cs +++ b/src/XTwitterScraper/Models/Events/EventRetrieveParams.cs @@ -101,13 +101,13 @@ public override Uri Url(ClientOptions options) options.BaseUrl.ToString().TrimEnd('/') + string.Format("/events/{0}", this.ID) ) { - Query = this.QueryString(options, SecurityOptions.All()), + Query = this.QueryString(options), }.Uri; } internal override void AddHeadersToRequest(HttpRequestMessage request, ClientOptions options) { - ParamsBase.AddDefaultHeaders(request, options, SecurityOptions.All()); + ParamsBase.AddDefaultHeaders(request, options); foreach (var item in this.RawHeaderData) { ParamsBase.AddHeaderElementToRequest(request, item.Key, item.Value); diff --git a/src/XTwitterScraper/Models/Extractions/ExtractionEstimateCostParams.cs b/src/XTwitterScraper/Models/Extractions/ExtractionEstimateCostParams.cs index 640225d..f8848ae 100644 --- a/src/XTwitterScraper/Models/Extractions/ExtractionEstimateCostParams.cs +++ b/src/XTwitterScraper/Models/Extractions/ExtractionEstimateCostParams.cs @@ -294,7 +294,7 @@ public override Uri Url(ClientOptions options) { return new UriBuilder(options.BaseUrl.ToString().TrimEnd('/') + "/extractions/estimate") { - Query = this.QueryString(options, SecurityOptions.All()), + Query = this.QueryString(options), }.Uri; } @@ -309,7 +309,7 @@ public override Uri Url(ClientOptions options) internal override void AddHeadersToRequest(HttpRequestMessage request, ClientOptions options) { - ParamsBase.AddDefaultHeaders(request, options, SecurityOptions.All()); + ParamsBase.AddDefaultHeaders(request, options); foreach (var item in this.RawHeaderData) { ParamsBase.AddHeaderElementToRequest(request, item.Key, item.Value); diff --git a/src/XTwitterScraper/Models/Extractions/ExtractionEstimateCostResponse.cs b/src/XTwitterScraper/Models/Extractions/ExtractionEstimateCostResponse.cs index b6df094..7298270 100644 --- a/src/XTwitterScraper/Models/Extractions/ExtractionEstimateCostResponse.cs +++ b/src/XTwitterScraper/Models/Extractions/ExtractionEstimateCostResponse.cs @@ -25,24 +25,34 @@ public required bool Allowed init { this._rawData.Set("allowed", value); } } - public required long EstimatedResults + public required string CreditsAvailable { get { this._rawData.Freeze(); - return this._rawData.GetNotNullStruct("estimatedResults"); + return this._rawData.GetNotNullClass("creditsAvailable"); } - init { this._rawData.Set("estimatedResults", value); } + init { this._rawData.Set("creditsAvailable", value); } + } + + public required string CreditsRequired + { + get + { + this._rawData.Freeze(); + return this._rawData.GetNotNullClass("creditsRequired"); + } + init { this._rawData.Set("creditsRequired", value); } } - public required double ProjectedPercent + public required long EstimatedResults { get { this._rawData.Freeze(); - return this._rawData.GetNotNullStruct("projectedPercent"); + return this._rawData.GetNotNullStruct("estimatedResults"); } - init { this._rawData.Set("projectedPercent", value); } + init { this._rawData.Set("estimatedResults", value); } } public required string Source @@ -55,24 +65,33 @@ public required string Source init { this._rawData.Set("source", value); } } - public required double UsagePercent + public string? ResolvedXUserID { get { this._rawData.Freeze(); - return this._rawData.GetNotNullStruct("usagePercent"); + return this._rawData.GetNullableClass("resolvedXUserId"); + } + init + { + if (value == null) + { + return; + } + + this._rawData.Set("resolvedXUserId", value); } - init { this._rawData.Set("usagePercent", value); } } /// public override void Validate() { _ = this.Allowed; + _ = this.CreditsAvailable; + _ = this.CreditsRequired; _ = this.EstimatedResults; - _ = this.ProjectedPercent; _ = this.Source; - _ = this.UsagePercent; + _ = this.ResolvedXUserID; } public ExtractionEstimateCostResponse() { } diff --git a/src/XTwitterScraper/Models/Extractions/ExtractionExportResultsParams.cs b/src/XTwitterScraper/Models/Extractions/ExtractionExportResultsParams.cs index db1903e..b2956a6 100644 --- a/src/XTwitterScraper/Models/Extractions/ExtractionExportResultsParams.cs +++ b/src/XTwitterScraper/Models/Extractions/ExtractionExportResultsParams.cs @@ -127,13 +127,13 @@ public override Uri Url(ClientOptions options) + string.Format("/extractions/{0}/export", this.ID) ) { - Query = this.QueryString(options, SecurityOptions.All()), + Query = this.QueryString(options), }.Uri; } internal override void AddHeadersToRequest(HttpRequestMessage request, ClientOptions options) { - ParamsBase.AddDefaultHeaders(request, options, SecurityOptions.All()); + ParamsBase.AddDefaultHeaders(request, options); request.Headers.Add("Accept", "application/octet-stream"); foreach (var item in this.RawHeaderData) { diff --git a/src/XTwitterScraper/Models/Extractions/ExtractionListParams.cs b/src/XTwitterScraper/Models/Extractions/ExtractionListParams.cs index a269736..e2f051a 100644 --- a/src/XTwitterScraper/Models/Extractions/ExtractionListParams.cs +++ b/src/XTwitterScraper/Models/Extractions/ExtractionListParams.cs @@ -174,13 +174,13 @@ public override Uri Url(ClientOptions options) { return new UriBuilder(options.BaseUrl.ToString().TrimEnd('/') + "/extractions") { - Query = this.QueryString(options, SecurityOptions.All()), + Query = this.QueryString(options), }.Uri; } internal override void AddHeadersToRequest(HttpRequestMessage request, ClientOptions options) { - ParamsBase.AddDefaultHeaders(request, options, SecurityOptions.All()); + ParamsBase.AddDefaultHeaders(request, options); foreach (var item in this.RawHeaderData) { ParamsBase.AddHeaderElementToRequest(request, item.Key, item.Value); diff --git a/src/XTwitterScraper/Models/Extractions/ExtractionRetrieveParams.cs b/src/XTwitterScraper/Models/Extractions/ExtractionRetrieveParams.cs index f3f3c82..28b263a 100644 --- a/src/XTwitterScraper/Models/Extractions/ExtractionRetrieveParams.cs +++ b/src/XTwitterScraper/Models/Extractions/ExtractionRetrieveParams.cs @@ -143,13 +143,13 @@ public override Uri Url(ClientOptions options) options.BaseUrl.ToString().TrimEnd('/') + string.Format("/extractions/{0}", this.ID) ) { - Query = this.QueryString(options, SecurityOptions.All()), + Query = this.QueryString(options), }.Uri; } internal override void AddHeadersToRequest(HttpRequestMessage request, ClientOptions options) { - ParamsBase.AddDefaultHeaders(request, options, SecurityOptions.All()); + ParamsBase.AddDefaultHeaders(request, options); foreach (var item in this.RawHeaderData) { ParamsBase.AddHeaderElementToRequest(request, item.Key, item.Value); diff --git a/src/XTwitterScraper/Models/Extractions/ExtractionRunParams.cs b/src/XTwitterScraper/Models/Extractions/ExtractionRunParams.cs index ea221fd..71642af 100644 --- a/src/XTwitterScraper/Models/Extractions/ExtractionRunParams.cs +++ b/src/XTwitterScraper/Models/Extractions/ExtractionRunParams.cs @@ -294,7 +294,7 @@ public override Uri Url(ClientOptions options) { return new UriBuilder(options.BaseUrl.ToString().TrimEnd('/') + "/extractions") { - Query = this.QueryString(options, SecurityOptions.All()), + Query = this.QueryString(options), }.Uri; } @@ -309,7 +309,7 @@ public override Uri Url(ClientOptions options) internal override void AddHeadersToRequest(HttpRequestMessage request, ClientOptions options) { - ParamsBase.AddDefaultHeaders(request, options, SecurityOptions.All()); + ParamsBase.AddDefaultHeaders(request, options); foreach (var item in this.RawHeaderData) { ParamsBase.AddHeaderElementToRequest(request, item.Key, item.Value); diff --git a/src/XTwitterScraper/Models/Integrations/Integration.cs b/src/XTwitterScraper/Models/Integrations/Integration.cs deleted file mode 100644 index 8e88fd1..0000000 --- a/src/XTwitterScraper/Models/Integrations/Integration.cs +++ /dev/null @@ -1,247 +0,0 @@ -using System; -using System.Collections.Frozen; -using System.Collections.Generic; -using System.Collections.Immutable; -using System.Diagnostics.CodeAnalysis; -using System.Text.Json; -using System.Text.Json.Serialization; -using XTwitterScraper.Core; -using XTwitterScraper.Exceptions; - -namespace XTwitterScraper.Models.Integrations; - -/// -/// Third-party integration (e.g. Telegram) subscribed to monitor events. -/// -[JsonConverter(typeof(JsonModelConverter))] -public sealed record class Integration : JsonModel -{ - public required string ID - { - get - { - this._rawData.Freeze(); - return this._rawData.GetNotNullClass("id"); - } - init { this._rawData.Set("id", value); } - } - - /// - /// Integration config — shape varies by type (JSON) - /// - public required IReadOnlyDictionary Config - { - get - { - this._rawData.Freeze(); - return this._rawData.GetNotNullClass>("config"); - } - init - { - this._rawData.Set>( - "config", - FrozenDictionary.ToFrozenDictionary(value) - ); - } - } - - public required DateTimeOffset CreatedAt - { - get - { - this._rawData.Freeze(); - return this._rawData.GetNotNullStruct("createdAt"); - } - init { this._rawData.Set("createdAt", value); } - } - - /// - /// Array of event types to subscribe to. - /// - public required IReadOnlyList> EventTypes - { - get - { - this._rawData.Freeze(); - return this._rawData.GetNotNullStruct>>( - "eventTypes" - ); - } - init - { - this._rawData.Set>>( - "eventTypes", - ImmutableArray.ToImmutableArray(value) - ); - } - } - - public required bool IsActive - { - get - { - this._rawData.Freeze(); - return this._rawData.GetNotNullStruct("isActive"); - } - init { this._rawData.Set("isActive", value); } - } - - public required string Name - { - get - { - this._rawData.Freeze(); - return this._rawData.GetNotNullClass("name"); - } - init { this._rawData.Set("name", value); } - } - - public JsonElement Type - { - get - { - this._rawData.Freeze(); - return this._rawData.GetNotNullStruct("type"); - } - init { this._rawData.Set("type", value); } - } - - /// - /// Event filter rules (JSON) - /// - public IReadOnlyDictionary? Filters - { - get - { - this._rawData.Freeze(); - return this._rawData.GetNullableClass>("filters"); - } - init - { - if (value == null) - { - return; - } - - this._rawData.Set?>( - "filters", - value == null ? null : FrozenDictionary.ToFrozenDictionary(value) - ); - } - } - - public string? MessageTemplate - { - get - { - this._rawData.Freeze(); - return this._rawData.GetNullableClass("messageTemplate"); - } - init - { - if (value == null) - { - return; - } - - this._rawData.Set("messageTemplate", value); - } - } - - public bool? ScopeAllMonitors - { - get - { - this._rawData.Freeze(); - return this._rawData.GetNullableStruct("scopeAllMonitors"); - } - init - { - if (value == null) - { - return; - } - - this._rawData.Set("scopeAllMonitors", value); - } - } - - public bool? SilentPush - { - get - { - this._rawData.Freeze(); - return this._rawData.GetNullableStruct("silentPush"); - } - init - { - if (value == null) - { - return; - } - - this._rawData.Set("silentPush", value); - } - } - - /// - public override void Validate() - { - _ = this.ID; - _ = this.Config; - _ = this.CreatedAt; - foreach (var item in this.EventTypes) - { - item.Validate(); - } - _ = this.IsActive; - _ = this.Name; - if (!JsonElement.DeepEquals(this.Type, JsonSerializer.SerializeToElement("telegram"))) - { - throw new XTwitterScraperInvalidDataException("Invalid value given for constant"); - } - _ = this.Filters; - _ = this.MessageTemplate; - _ = this.ScopeAllMonitors; - _ = this.SilentPush; - } - - public Integration() - { - this.Type = JsonSerializer.SerializeToElement("telegram"); - } - -#pragma warning disable CS8618 - [SetsRequiredMembers] - public Integration(Integration integration) - : base(integration) { } -#pragma warning restore CS8618 - - public Integration(IReadOnlyDictionary rawData) - { - this._rawData = new(rawData); - - this.Type = JsonSerializer.SerializeToElement("telegram"); - } - -#pragma warning disable CS8618 - [SetsRequiredMembers] - Integration(FrozenDictionary rawData) - { - this._rawData = new(rawData); - } -#pragma warning restore CS8618 - - /// - public static Integration FromRawUnchecked(IReadOnlyDictionary rawData) - { - return new(FrozenDictionary.ToFrozenDictionary(rawData)); - } -} - -class IntegrationFromRaw : IFromRawJson -{ - /// - public Integration FromRawUnchecked(IReadOnlyDictionary rawData) => - Integration.FromRawUnchecked(rawData); -} diff --git a/src/XTwitterScraper/Models/Integrations/IntegrationCreateParams.cs b/src/XTwitterScraper/Models/Integrations/IntegrationCreateParams.cs deleted file mode 100644 index c0f58ce..0000000 --- a/src/XTwitterScraper/Models/Integrations/IntegrationCreateParams.cs +++ /dev/null @@ -1,258 +0,0 @@ -using System; -using System.Collections.Frozen; -using System.Collections.Generic; -using System.Collections.Immutable; -using System.Diagnostics.CodeAnalysis; -using System.Net.Http; -using System.Text; -using System.Text.Json; -using System.Text.Json.Serialization; -using XTwitterScraper.Core; - -namespace XTwitterScraper.Models.Integrations; - -/// -/// Create integration -/// -/// NOTE: Do not inherit from this type outside the SDK unless you're okay with -/// breaking changes in non-major versions. We may add new methods in the future that -/// cause existing derived classes to break. -/// -public record class IntegrationCreateParams : ParamsBase -{ - readonly JsonDictionary _rawBodyData = new(); - public IReadOnlyDictionary RawBodyData - { - get { return this._rawBodyData.Freeze(); } - } - - /// - /// Integration config (e.g. Telegram chatId) - /// - public required Config Config - { - get - { - this._rawBodyData.Freeze(); - return this._rawBodyData.GetNotNullClass("config"); - } - init { this._rawBodyData.Set("config", value); } - } - - /// - /// Array of event types to subscribe to. - /// - public required IReadOnlyList> EventTypes - { - get - { - this._rawBodyData.Freeze(); - return this._rawBodyData.GetNotNullStruct>>( - "eventTypes" - ); - } - init - { - this._rawBodyData.Set>>( - "eventTypes", - ImmutableArray.ToImmutableArray(value) - ); - } - } - - public required string Name - { - get - { - this._rawBodyData.Freeze(); - return this._rawBodyData.GetNotNullClass("name"); - } - init { this._rawBodyData.Set("name", value); } - } - - public JsonElement Type - { - get - { - this._rawBodyData.Freeze(); - return this._rawBodyData.GetNotNullStruct("type"); - } - init { this._rawBodyData.Set("type", value); } - } - - public IntegrationCreateParams() - { - this.Type = JsonSerializer.SerializeToElement("telegram"); - } - -#pragma warning disable CS8618 - [SetsRequiredMembers] - public IntegrationCreateParams(IntegrationCreateParams integrationCreateParams) - : base(integrationCreateParams) - { - this._rawBodyData = new(integrationCreateParams._rawBodyData); - } -#pragma warning restore CS8618 - - public IntegrationCreateParams( - IReadOnlyDictionary rawHeaderData, - IReadOnlyDictionary rawQueryData, - IReadOnlyDictionary rawBodyData - ) - { - this._rawHeaderData = new(rawHeaderData); - this._rawQueryData = new(rawQueryData); - this._rawBodyData = new(rawBodyData); - } - -#pragma warning disable CS8618 - [SetsRequiredMembers] - IntegrationCreateParams( - FrozenDictionary rawHeaderData, - FrozenDictionary rawQueryData, - FrozenDictionary rawBodyData - ) - { - this._rawHeaderData = new(rawHeaderData); - this._rawQueryData = new(rawQueryData); - this._rawBodyData = new(rawBodyData); - } -#pragma warning restore CS8618 - - /// - public static IntegrationCreateParams FromRawUnchecked( - IReadOnlyDictionary rawHeaderData, - IReadOnlyDictionary rawQueryData, - IReadOnlyDictionary rawBodyData - ) - { - return new( - FrozenDictionary.ToFrozenDictionary(rawHeaderData), - FrozenDictionary.ToFrozenDictionary(rawQueryData), - FrozenDictionary.ToFrozenDictionary(rawBodyData) - ); - } - - public override string ToString() => - JsonSerializer.Serialize( - FriendlyJsonPrinter.PrintValue( - new Dictionary() - { - ["HeaderData"] = FriendlyJsonPrinter.PrintValue( - JsonSerializer.SerializeToElement(this._rawHeaderData.Freeze()) - ), - ["QueryData"] = FriendlyJsonPrinter.PrintValue( - JsonSerializer.SerializeToElement(this._rawQueryData.Freeze()) - ), - ["BodyData"] = FriendlyJsonPrinter.PrintValue(this._rawBodyData.Freeze()), - } - ), - ModelBase.ToStringSerializerOptions - ); - - public virtual bool Equals(IntegrationCreateParams? other) - { - if (other == null) - { - return false; - } - return this._rawHeaderData.Equals(other._rawHeaderData) - && this._rawQueryData.Equals(other._rawQueryData) - && this._rawBodyData.Equals(other._rawBodyData); - } - - public override Uri Url(ClientOptions options) - { - return new UriBuilder(options.BaseUrl.ToString().TrimEnd('/') + "/integrations") - { - Query = this.QueryString(options, SecurityOptions.All()), - }.Uri; - } - - internal override HttpContent? BodyContent() - { - return new StringContent( - JsonSerializer.Serialize(this.RawBodyData, ModelBase.SerializerOptions), - Encoding.UTF8, - "application/json" - ); - } - - internal override void AddHeadersToRequest(HttpRequestMessage request, ClientOptions options) - { - ParamsBase.AddDefaultHeaders(request, options, SecurityOptions.All()); - foreach (var item in this.RawHeaderData) - { - ParamsBase.AddHeaderElementToRequest(request, item.Key, item.Value); - } - } - - public override int GetHashCode() - { - return 0; - } -} - -/// -/// Integration config (e.g. Telegram chatId) -/// -[JsonConverter(typeof(JsonModelConverter))] -public sealed record class Config : JsonModel -{ - public required string ChatID - { - get - { - this._rawData.Freeze(); - return this._rawData.GetNotNullClass("chatId"); - } - init { this._rawData.Set("chatId", value); } - } - - /// - public override void Validate() - { - _ = this.ChatID; - } - - public Config() { } - -#pragma warning disable CS8618 - [SetsRequiredMembers] - public Config(Config config) - : base(config) { } -#pragma warning restore CS8618 - - public Config(IReadOnlyDictionary rawData) - { - this._rawData = new(rawData); - } - -#pragma warning disable CS8618 - [SetsRequiredMembers] - Config(FrozenDictionary rawData) - { - this._rawData = new(rawData); - } -#pragma warning restore CS8618 - - /// - public static Config FromRawUnchecked(IReadOnlyDictionary rawData) - { - return new(FrozenDictionary.ToFrozenDictionary(rawData)); - } - - [SetsRequiredMembers] - public Config(string chatID) - : this() - { - this.ChatID = chatID; - } -} - -class ConfigFromRaw : IFromRawJson -{ - /// - public Config FromRawUnchecked(IReadOnlyDictionary rawData) => - Config.FromRawUnchecked(rawData); -} diff --git a/src/XTwitterScraper/Models/Integrations/IntegrationDeleteParams.cs b/src/XTwitterScraper/Models/Integrations/IntegrationDeleteParams.cs deleted file mode 100644 index 147529a..0000000 --- a/src/XTwitterScraper/Models/Integrations/IntegrationDeleteParams.cs +++ /dev/null @@ -1,121 +0,0 @@ -using System; -using System.Collections.Frozen; -using System.Collections.Generic; -using System.Diagnostics.CodeAnalysis; -using System.Net.Http; -using System.Text.Json; -using XTwitterScraper.Core; - -namespace XTwitterScraper.Models.Integrations; - -/// -/// Delete integration -/// -/// NOTE: Do not inherit from this type outside the SDK unless you're okay with -/// breaking changes in non-major versions. We may add new methods in the future that -/// cause existing derived classes to break. -/// -public record class IntegrationDeleteParams : ParamsBase -{ - public string? ID { get; init; } - - public IntegrationDeleteParams() { } - -#pragma warning disable CS8618 - [SetsRequiredMembers] - public IntegrationDeleteParams(IntegrationDeleteParams integrationDeleteParams) - : base(integrationDeleteParams) - { - this.ID = integrationDeleteParams.ID; - } -#pragma warning restore CS8618 - - public IntegrationDeleteParams( - IReadOnlyDictionary rawHeaderData, - IReadOnlyDictionary rawQueryData - ) - { - this._rawHeaderData = new(rawHeaderData); - this._rawQueryData = new(rawQueryData); - } - -#pragma warning disable CS8618 - [SetsRequiredMembers] - IntegrationDeleteParams( - FrozenDictionary rawHeaderData, - FrozenDictionary rawQueryData, - string id - ) - { - this._rawHeaderData = new(rawHeaderData); - this._rawQueryData = new(rawQueryData); - this.ID = id; - } -#pragma warning restore CS8618 - - /// - public static IntegrationDeleteParams FromRawUnchecked( - IReadOnlyDictionary rawHeaderData, - IReadOnlyDictionary rawQueryData, - string id - ) - { - return new( - FrozenDictionary.ToFrozenDictionary(rawHeaderData), - FrozenDictionary.ToFrozenDictionary(rawQueryData), - id - ); - } - - public override string ToString() => - JsonSerializer.Serialize( - FriendlyJsonPrinter.PrintValue( - new Dictionary() - { - ["ID"] = JsonSerializer.SerializeToElement(this.ID), - ["HeaderData"] = FriendlyJsonPrinter.PrintValue( - JsonSerializer.SerializeToElement(this._rawHeaderData.Freeze()) - ), - ["QueryData"] = FriendlyJsonPrinter.PrintValue( - JsonSerializer.SerializeToElement(this._rawQueryData.Freeze()) - ), - } - ), - ModelBase.ToStringSerializerOptions - ); - - public virtual bool Equals(IntegrationDeleteParams? other) - { - if (other == null) - { - return false; - } - return (this.ID?.Equals(other.ID) ?? other.ID == null) - && this._rawHeaderData.Equals(other._rawHeaderData) - && this._rawQueryData.Equals(other._rawQueryData); - } - - public override Uri Url(ClientOptions options) - { - return new UriBuilder( - options.BaseUrl.ToString().TrimEnd('/') + string.Format("/integrations/{0}", this.ID) - ) - { - Query = this.QueryString(options, SecurityOptions.All()), - }.Uri; - } - - internal override void AddHeadersToRequest(HttpRequestMessage request, ClientOptions options) - { - ParamsBase.AddDefaultHeaders(request, options, SecurityOptions.All()); - foreach (var item in this.RawHeaderData) - { - ParamsBase.AddHeaderElementToRequest(request, item.Key, item.Value); - } - } - - public override int GetHashCode() - { - return 0; - } -} diff --git a/src/XTwitterScraper/Models/Integrations/IntegrationDeleteResponse.cs b/src/XTwitterScraper/Models/Integrations/IntegrationDeleteResponse.cs deleted file mode 100644 index daf9cbe..0000000 --- a/src/XTwitterScraper/Models/Integrations/IntegrationDeleteResponse.cs +++ /dev/null @@ -1,76 +0,0 @@ -using System.Collections.Frozen; -using System.Collections.Generic; -using System.Diagnostics.CodeAnalysis; -using System.Text.Json; -using System.Text.Json.Serialization; -using XTwitterScraper.Core; -using XTwitterScraper.Exceptions; - -namespace XTwitterScraper.Models.Integrations; - -[JsonConverter( - typeof(JsonModelConverter) -)] -public sealed record class IntegrationDeleteResponse : JsonModel -{ - public JsonElement Success - { - get - { - this._rawData.Freeze(); - return this._rawData.GetNotNullStruct("success"); - } - init { this._rawData.Set("success", value); } - } - - /// - public override void Validate() - { - if (!JsonElement.DeepEquals(this.Success, JsonSerializer.SerializeToElement(true))) - { - throw new XTwitterScraperInvalidDataException("Invalid value given for constant"); - } - } - - public IntegrationDeleteResponse() - { - this.Success = JsonSerializer.SerializeToElement(true); - } - -#pragma warning disable CS8618 - [SetsRequiredMembers] - public IntegrationDeleteResponse(IntegrationDeleteResponse integrationDeleteResponse) - : base(integrationDeleteResponse) { } -#pragma warning restore CS8618 - - public IntegrationDeleteResponse(IReadOnlyDictionary rawData) - { - this._rawData = new(rawData); - - this.Success = JsonSerializer.SerializeToElement(true); - } - -#pragma warning disable CS8618 - [SetsRequiredMembers] - IntegrationDeleteResponse(FrozenDictionary rawData) - { - this._rawData = new(rawData); - } -#pragma warning restore CS8618 - - /// - public static IntegrationDeleteResponse FromRawUnchecked( - IReadOnlyDictionary rawData - ) - { - return new(FrozenDictionary.ToFrozenDictionary(rawData)); - } -} - -class IntegrationDeleteResponseFromRaw : IFromRawJson -{ - /// - public IntegrationDeleteResponse FromRawUnchecked( - IReadOnlyDictionary rawData - ) => IntegrationDeleteResponse.FromRawUnchecked(rawData); -} diff --git a/src/XTwitterScraper/Models/Integrations/IntegrationDelivery.cs b/src/XTwitterScraper/Models/Integrations/IntegrationDelivery.cs deleted file mode 100644 index c9007db..0000000 --- a/src/XTwitterScraper/Models/Integrations/IntegrationDelivery.cs +++ /dev/null @@ -1,207 +0,0 @@ -using System; -using System.Collections.Frozen; -using System.Collections.Generic; -using System.Diagnostics.CodeAnalysis; -using System.Text.Json; -using System.Text.Json.Serialization; -using XTwitterScraper.Core; - -namespace XTwitterScraper.Models.Integrations; - -/// -/// Integration delivery attempt record with status and retry count. -/// -[JsonConverter(typeof(JsonModelConverter))] -public sealed record class IntegrationDelivery : JsonModel -{ - public required string ID - { - get - { - this._rawData.Freeze(); - return this._rawData.GetNotNullClass("id"); - } - init { this._rawData.Set("id", value); } - } - - public required long Attempts - { - get - { - this._rawData.Freeze(); - return this._rawData.GetNotNullStruct("attempts"); - } - init { this._rawData.Set("attempts", value); } - } - - public required DateTimeOffset CreatedAt - { - get - { - this._rawData.Freeze(); - return this._rawData.GetNotNullStruct("createdAt"); - } - init { this._rawData.Set("createdAt", value); } - } - - public required string EventType - { - get - { - this._rawData.Freeze(); - return this._rawData.GetNotNullClass("eventType"); - } - init { this._rawData.Set("eventType", value); } - } - - public required string Status - { - get - { - this._rawData.Freeze(); - return this._rawData.GetNotNullClass("status"); - } - init { this._rawData.Set("status", value); } - } - - public DateTimeOffset? DeliveredAt - { - get - { - this._rawData.Freeze(); - return this._rawData.GetNullableStruct("deliveredAt"); - } - init - { - if (value == null) - { - return; - } - - this._rawData.Set("deliveredAt", value); - } - } - - public string? LastError - { - get - { - this._rawData.Freeze(); - return this._rawData.GetNullableClass("lastError"); - } - init - { - if (value == null) - { - return; - } - - this._rawData.Set("lastError", value); - } - } - - public long? LastStatusCode - { - get - { - this._rawData.Freeze(); - return this._rawData.GetNullableStruct("lastStatusCode"); - } - init - { - if (value == null) - { - return; - } - - this._rawData.Set("lastStatusCode", value); - } - } - - public string? SourceID - { - get - { - this._rawData.Freeze(); - return this._rawData.GetNullableClass("sourceId"); - } - init - { - if (value == null) - { - return; - } - - this._rawData.Set("sourceId", value); - } - } - - public string? SourceType - { - get - { - this._rawData.Freeze(); - return this._rawData.GetNullableClass("sourceType"); - } - init - { - if (value == null) - { - return; - } - - this._rawData.Set("sourceType", value); - } - } - - /// - public override void Validate() - { - _ = this.ID; - _ = this.Attempts; - _ = this.CreatedAt; - _ = this.EventType; - _ = this.Status; - _ = this.DeliveredAt; - _ = this.LastError; - _ = this.LastStatusCode; - _ = this.SourceID; - _ = this.SourceType; - } - - public IntegrationDelivery() { } - -#pragma warning disable CS8618 - [SetsRequiredMembers] - public IntegrationDelivery(IntegrationDelivery integrationDelivery) - : base(integrationDelivery) { } -#pragma warning restore CS8618 - - public IntegrationDelivery(IReadOnlyDictionary rawData) - { - this._rawData = new(rawData); - } - -#pragma warning disable CS8618 - [SetsRequiredMembers] - IntegrationDelivery(FrozenDictionary rawData) - { - this._rawData = new(rawData); - } -#pragma warning restore CS8618 - - /// - public static IntegrationDelivery FromRawUnchecked( - IReadOnlyDictionary rawData - ) - { - return new(FrozenDictionary.ToFrozenDictionary(rawData)); - } -} - -class IntegrationDeliveryFromRaw : IFromRawJson -{ - /// - public IntegrationDelivery FromRawUnchecked(IReadOnlyDictionary rawData) => - IntegrationDelivery.FromRawUnchecked(rawData); -} diff --git a/src/XTwitterScraper/Models/Integrations/IntegrationListDeliveriesParams.cs b/src/XTwitterScraper/Models/Integrations/IntegrationListDeliveriesParams.cs deleted file mode 100644 index 68a4c99..0000000 --- a/src/XTwitterScraper/Models/Integrations/IntegrationListDeliveriesParams.cs +++ /dev/null @@ -1,145 +0,0 @@ -using System; -using System.Collections.Frozen; -using System.Collections.Generic; -using System.Diagnostics.CodeAnalysis; -using System.Net.Http; -using System.Text.Json; -using XTwitterScraper.Core; - -namespace XTwitterScraper.Models.Integrations; - -/// -/// List integration delivery history -/// -/// NOTE: Do not inherit from this type outside the SDK unless you're okay with -/// breaking changes in non-major versions. We may add new methods in the future that -/// cause existing derived classes to break. -/// -public record class IntegrationListDeliveriesParams : ParamsBase -{ - public string? ID { get; init; } - - /// - /// Maximum number of items to return (1-100, default 50) - /// - public long? Limit - { - get - { - this._rawQueryData.Freeze(); - return this._rawQueryData.GetNullableStruct("limit"); - } - init - { - if (value == null) - { - return; - } - - this._rawQueryData.Set("limit", value); - } - } - - public IntegrationListDeliveriesParams() { } - -#pragma warning disable CS8618 - [SetsRequiredMembers] - public IntegrationListDeliveriesParams( - IntegrationListDeliveriesParams integrationListDeliveriesParams - ) - : base(integrationListDeliveriesParams) - { - this.ID = integrationListDeliveriesParams.ID; - } -#pragma warning restore CS8618 - - public IntegrationListDeliveriesParams( - IReadOnlyDictionary rawHeaderData, - IReadOnlyDictionary rawQueryData - ) - { - this._rawHeaderData = new(rawHeaderData); - this._rawQueryData = new(rawQueryData); - } - -#pragma warning disable CS8618 - [SetsRequiredMembers] - IntegrationListDeliveriesParams( - FrozenDictionary rawHeaderData, - FrozenDictionary rawQueryData, - string id - ) - { - this._rawHeaderData = new(rawHeaderData); - this._rawQueryData = new(rawQueryData); - this.ID = id; - } -#pragma warning restore CS8618 - - /// - public static IntegrationListDeliveriesParams FromRawUnchecked( - IReadOnlyDictionary rawHeaderData, - IReadOnlyDictionary rawQueryData, - string id - ) - { - return new( - FrozenDictionary.ToFrozenDictionary(rawHeaderData), - FrozenDictionary.ToFrozenDictionary(rawQueryData), - id - ); - } - - public override string ToString() => - JsonSerializer.Serialize( - FriendlyJsonPrinter.PrintValue( - new Dictionary() - { - ["ID"] = JsonSerializer.SerializeToElement(this.ID), - ["HeaderData"] = FriendlyJsonPrinter.PrintValue( - JsonSerializer.SerializeToElement(this._rawHeaderData.Freeze()) - ), - ["QueryData"] = FriendlyJsonPrinter.PrintValue( - JsonSerializer.SerializeToElement(this._rawQueryData.Freeze()) - ), - } - ), - ModelBase.ToStringSerializerOptions - ); - - public virtual bool Equals(IntegrationListDeliveriesParams? other) - { - if (other == null) - { - return false; - } - return (this.ID?.Equals(other.ID) ?? other.ID == null) - && this._rawHeaderData.Equals(other._rawHeaderData) - && this._rawQueryData.Equals(other._rawQueryData); - } - - public override Uri Url(ClientOptions options) - { - return new UriBuilder( - options.BaseUrl.ToString().TrimEnd('/') - + string.Format("/integrations/{0}/deliveries", this.ID) - ) - { - Query = this.QueryString(options, SecurityOptions.All()), - }.Uri; - } - - internal override void AddHeadersToRequest(HttpRequestMessage request, ClientOptions options) - { - ParamsBase.AddDefaultHeaders(request, options, SecurityOptions.All()); - foreach (var item in this.RawHeaderData) - { - ParamsBase.AddHeaderElementToRequest(request, item.Key, item.Value); - } - } - - public override int GetHashCode() - { - return 0; - } -} diff --git a/src/XTwitterScraper/Models/Integrations/IntegrationListDeliveriesResponse.cs b/src/XTwitterScraper/Models/Integrations/IntegrationListDeliveriesResponse.cs deleted file mode 100644 index dfc7f45..0000000 --- a/src/XTwitterScraper/Models/Integrations/IntegrationListDeliveriesResponse.cs +++ /dev/null @@ -1,91 +0,0 @@ -using System.Collections.Frozen; -using System.Collections.Generic; -using System.Collections.Immutable; -using System.Diagnostics.CodeAnalysis; -using System.Text.Json; -using System.Text.Json.Serialization; -using XTwitterScraper.Core; - -namespace XTwitterScraper.Models.Integrations; - -[JsonConverter( - typeof(JsonModelConverter< - IntegrationListDeliveriesResponse, - IntegrationListDeliveriesResponseFromRaw - >) -)] -public sealed record class IntegrationListDeliveriesResponse : JsonModel -{ - public required IReadOnlyList Deliveries - { - get - { - this._rawData.Freeze(); - return this._rawData.GetNotNullStruct>( - "deliveries" - ); - } - init - { - this._rawData.Set>( - "deliveries", - ImmutableArray.ToImmutableArray(value) - ); - } - } - - /// - public override void Validate() - { - foreach (var item in this.Deliveries) - { - item.Validate(); - } - } - - public IntegrationListDeliveriesResponse() { } - -#pragma warning disable CS8618 - [SetsRequiredMembers] - public IntegrationListDeliveriesResponse( - IntegrationListDeliveriesResponse integrationListDeliveriesResponse - ) - : base(integrationListDeliveriesResponse) { } -#pragma warning restore CS8618 - - public IntegrationListDeliveriesResponse(IReadOnlyDictionary rawData) - { - this._rawData = new(rawData); - } - -#pragma warning disable CS8618 - [SetsRequiredMembers] - IntegrationListDeliveriesResponse(FrozenDictionary rawData) - { - this._rawData = new(rawData); - } -#pragma warning restore CS8618 - - /// - public static IntegrationListDeliveriesResponse FromRawUnchecked( - IReadOnlyDictionary rawData - ) - { - return new(FrozenDictionary.ToFrozenDictionary(rawData)); - } - - [SetsRequiredMembers] - public IntegrationListDeliveriesResponse(IReadOnlyList deliveries) - : this() - { - this.Deliveries = deliveries; - } -} - -class IntegrationListDeliveriesResponseFromRaw : IFromRawJson -{ - /// - public IntegrationListDeliveriesResponse FromRawUnchecked( - IReadOnlyDictionary rawData - ) => IntegrationListDeliveriesResponse.FromRawUnchecked(rawData); -} diff --git a/src/XTwitterScraper/Models/Integrations/IntegrationListParams.cs b/src/XTwitterScraper/Models/Integrations/IntegrationListParams.cs deleted file mode 100644 index 99186a6..0000000 --- a/src/XTwitterScraper/Models/Integrations/IntegrationListParams.cs +++ /dev/null @@ -1,108 +0,0 @@ -using System; -using System.Collections.Frozen; -using System.Collections.Generic; -using System.Diagnostics.CodeAnalysis; -using System.Net.Http; -using System.Text.Json; -using XTwitterScraper.Core; - -namespace XTwitterScraper.Models.Integrations; - -/// -/// List integrations -/// -/// NOTE: Do not inherit from this type outside the SDK unless you're okay with -/// breaking changes in non-major versions. We may add new methods in the future that -/// cause existing derived classes to break. -/// -public record class IntegrationListParams : ParamsBase -{ - public IntegrationListParams() { } - -#pragma warning disable CS8618 - [SetsRequiredMembers] - public IntegrationListParams(IntegrationListParams integrationListParams) - : base(integrationListParams) { } -#pragma warning restore CS8618 - - public IntegrationListParams( - IReadOnlyDictionary rawHeaderData, - IReadOnlyDictionary rawQueryData - ) - { - this._rawHeaderData = new(rawHeaderData); - this._rawQueryData = new(rawQueryData); - } - -#pragma warning disable CS8618 - [SetsRequiredMembers] - IntegrationListParams( - FrozenDictionary rawHeaderData, - FrozenDictionary rawQueryData - ) - { - this._rawHeaderData = new(rawHeaderData); - this._rawQueryData = new(rawQueryData); - } -#pragma warning restore CS8618 - - /// - public static IntegrationListParams FromRawUnchecked( - IReadOnlyDictionary rawHeaderData, - IReadOnlyDictionary rawQueryData - ) - { - return new( - FrozenDictionary.ToFrozenDictionary(rawHeaderData), - FrozenDictionary.ToFrozenDictionary(rawQueryData) - ); - } - - public override string ToString() => - JsonSerializer.Serialize( - FriendlyJsonPrinter.PrintValue( - new Dictionary() - { - ["HeaderData"] = FriendlyJsonPrinter.PrintValue( - JsonSerializer.SerializeToElement(this._rawHeaderData.Freeze()) - ), - ["QueryData"] = FriendlyJsonPrinter.PrintValue( - JsonSerializer.SerializeToElement(this._rawQueryData.Freeze()) - ), - } - ), - ModelBase.ToStringSerializerOptions - ); - - public virtual bool Equals(IntegrationListParams? other) - { - if (other == null) - { - return false; - } - return this._rawHeaderData.Equals(other._rawHeaderData) - && this._rawQueryData.Equals(other._rawQueryData); - } - - public override Uri Url(ClientOptions options) - { - return new UriBuilder(options.BaseUrl.ToString().TrimEnd('/') + "/integrations") - { - Query = this.QueryString(options, SecurityOptions.All()), - }.Uri; - } - - internal override void AddHeadersToRequest(HttpRequestMessage request, ClientOptions options) - { - ParamsBase.AddDefaultHeaders(request, options, SecurityOptions.All()); - foreach (var item in this.RawHeaderData) - { - ParamsBase.AddHeaderElementToRequest(request, item.Key, item.Value); - } - } - - public override int GetHashCode() - { - return 0; - } -} diff --git a/src/XTwitterScraper/Models/Integrations/IntegrationListResponse.cs b/src/XTwitterScraper/Models/Integrations/IntegrationListResponse.cs deleted file mode 100644 index 08a034c..0000000 --- a/src/XTwitterScraper/Models/Integrations/IntegrationListResponse.cs +++ /dev/null @@ -1,82 +0,0 @@ -using System.Collections.Frozen; -using System.Collections.Generic; -using System.Collections.Immutable; -using System.Diagnostics.CodeAnalysis; -using System.Text.Json; -using System.Text.Json.Serialization; -using XTwitterScraper.Core; - -namespace XTwitterScraper.Models.Integrations; - -[JsonConverter(typeof(JsonModelConverter))] -public sealed record class IntegrationListResponse : JsonModel -{ - public required IReadOnlyList Integrations - { - get - { - this._rawData.Freeze(); - return this._rawData.GetNotNullStruct>("integrations"); - } - init - { - this._rawData.Set>( - "integrations", - ImmutableArray.ToImmutableArray(value) - ); - } - } - - /// - public override void Validate() - { - foreach (var item in this.Integrations) - { - item.Validate(); - } - } - - public IntegrationListResponse() { } - -#pragma warning disable CS8618 - [SetsRequiredMembers] - public IntegrationListResponse(IntegrationListResponse integrationListResponse) - : base(integrationListResponse) { } -#pragma warning restore CS8618 - - public IntegrationListResponse(IReadOnlyDictionary rawData) - { - this._rawData = new(rawData); - } - -#pragma warning disable CS8618 - [SetsRequiredMembers] - IntegrationListResponse(FrozenDictionary rawData) - { - this._rawData = new(rawData); - } -#pragma warning restore CS8618 - - /// - public static IntegrationListResponse FromRawUnchecked( - IReadOnlyDictionary rawData - ) - { - return new(FrozenDictionary.ToFrozenDictionary(rawData)); - } - - [SetsRequiredMembers] - public IntegrationListResponse(IReadOnlyList integrations) - : this() - { - this.Integrations = integrations; - } -} - -class IntegrationListResponseFromRaw : IFromRawJson -{ - /// - public IntegrationListResponse FromRawUnchecked( - IReadOnlyDictionary rawData - ) => IntegrationListResponse.FromRawUnchecked(rawData); -} diff --git a/src/XTwitterScraper/Models/Integrations/IntegrationRetrieveParams.cs b/src/XTwitterScraper/Models/Integrations/IntegrationRetrieveParams.cs deleted file mode 100644 index b59363c..0000000 --- a/src/XTwitterScraper/Models/Integrations/IntegrationRetrieveParams.cs +++ /dev/null @@ -1,121 +0,0 @@ -using System; -using System.Collections.Frozen; -using System.Collections.Generic; -using System.Diagnostics.CodeAnalysis; -using System.Net.Http; -using System.Text.Json; -using XTwitterScraper.Core; - -namespace XTwitterScraper.Models.Integrations; - -/// -/// Get integration details -/// -/// NOTE: Do not inherit from this type outside the SDK unless you're okay with -/// breaking changes in non-major versions. We may add new methods in the future that -/// cause existing derived classes to break. -/// -public record class IntegrationRetrieveParams : ParamsBase -{ - public string? ID { get; init; } - - public IntegrationRetrieveParams() { } - -#pragma warning disable CS8618 - [SetsRequiredMembers] - public IntegrationRetrieveParams(IntegrationRetrieveParams integrationRetrieveParams) - : base(integrationRetrieveParams) - { - this.ID = integrationRetrieveParams.ID; - } -#pragma warning restore CS8618 - - public IntegrationRetrieveParams( - IReadOnlyDictionary rawHeaderData, - IReadOnlyDictionary rawQueryData - ) - { - this._rawHeaderData = new(rawHeaderData); - this._rawQueryData = new(rawQueryData); - } - -#pragma warning disable CS8618 - [SetsRequiredMembers] - IntegrationRetrieveParams( - FrozenDictionary rawHeaderData, - FrozenDictionary rawQueryData, - string id - ) - { - this._rawHeaderData = new(rawHeaderData); - this._rawQueryData = new(rawQueryData); - this.ID = id; - } -#pragma warning restore CS8618 - - /// - public static IntegrationRetrieveParams FromRawUnchecked( - IReadOnlyDictionary rawHeaderData, - IReadOnlyDictionary rawQueryData, - string id - ) - { - return new( - FrozenDictionary.ToFrozenDictionary(rawHeaderData), - FrozenDictionary.ToFrozenDictionary(rawQueryData), - id - ); - } - - public override string ToString() => - JsonSerializer.Serialize( - FriendlyJsonPrinter.PrintValue( - new Dictionary() - { - ["ID"] = JsonSerializer.SerializeToElement(this.ID), - ["HeaderData"] = FriendlyJsonPrinter.PrintValue( - JsonSerializer.SerializeToElement(this._rawHeaderData.Freeze()) - ), - ["QueryData"] = FriendlyJsonPrinter.PrintValue( - JsonSerializer.SerializeToElement(this._rawQueryData.Freeze()) - ), - } - ), - ModelBase.ToStringSerializerOptions - ); - - public virtual bool Equals(IntegrationRetrieveParams? other) - { - if (other == null) - { - return false; - } - return (this.ID?.Equals(other.ID) ?? other.ID == null) - && this._rawHeaderData.Equals(other._rawHeaderData) - && this._rawQueryData.Equals(other._rawQueryData); - } - - public override Uri Url(ClientOptions options) - { - return new UriBuilder( - options.BaseUrl.ToString().TrimEnd('/') + string.Format("/integrations/{0}", this.ID) - ) - { - Query = this.QueryString(options, SecurityOptions.All()), - }.Uri; - } - - internal override void AddHeadersToRequest(HttpRequestMessage request, ClientOptions options) - { - ParamsBase.AddDefaultHeaders(request, options, SecurityOptions.All()); - foreach (var item in this.RawHeaderData) - { - ParamsBase.AddHeaderElementToRequest(request, item.Key, item.Value); - } - } - - public override int GetHashCode() - { - return 0; - } -} diff --git a/src/XTwitterScraper/Models/Integrations/IntegrationSendTestParams.cs b/src/XTwitterScraper/Models/Integrations/IntegrationSendTestParams.cs deleted file mode 100644 index bc80e52..0000000 --- a/src/XTwitterScraper/Models/Integrations/IntegrationSendTestParams.cs +++ /dev/null @@ -1,122 +0,0 @@ -using System; -using System.Collections.Frozen; -using System.Collections.Generic; -using System.Diagnostics.CodeAnalysis; -using System.Net.Http; -using System.Text.Json; -using XTwitterScraper.Core; - -namespace XTwitterScraper.Models.Integrations; - -/// -/// Send test delivery -/// -/// NOTE: Do not inherit from this type outside the SDK unless you're okay with -/// breaking changes in non-major versions. We may add new methods in the future that -/// cause existing derived classes to break. -/// -public record class IntegrationSendTestParams : ParamsBase -{ - public string? ID { get; init; } - - public IntegrationSendTestParams() { } - -#pragma warning disable CS8618 - [SetsRequiredMembers] - public IntegrationSendTestParams(IntegrationSendTestParams integrationSendTestParams) - : base(integrationSendTestParams) - { - this.ID = integrationSendTestParams.ID; - } -#pragma warning restore CS8618 - - public IntegrationSendTestParams( - IReadOnlyDictionary rawHeaderData, - IReadOnlyDictionary rawQueryData - ) - { - this._rawHeaderData = new(rawHeaderData); - this._rawQueryData = new(rawQueryData); - } - -#pragma warning disable CS8618 - [SetsRequiredMembers] - IntegrationSendTestParams( - FrozenDictionary rawHeaderData, - FrozenDictionary rawQueryData, - string id - ) - { - this._rawHeaderData = new(rawHeaderData); - this._rawQueryData = new(rawQueryData); - this.ID = id; - } -#pragma warning restore CS8618 - - /// - public static IntegrationSendTestParams FromRawUnchecked( - IReadOnlyDictionary rawHeaderData, - IReadOnlyDictionary rawQueryData, - string id - ) - { - return new( - FrozenDictionary.ToFrozenDictionary(rawHeaderData), - FrozenDictionary.ToFrozenDictionary(rawQueryData), - id - ); - } - - public override string ToString() => - JsonSerializer.Serialize( - FriendlyJsonPrinter.PrintValue( - new Dictionary() - { - ["ID"] = JsonSerializer.SerializeToElement(this.ID), - ["HeaderData"] = FriendlyJsonPrinter.PrintValue( - JsonSerializer.SerializeToElement(this._rawHeaderData.Freeze()) - ), - ["QueryData"] = FriendlyJsonPrinter.PrintValue( - JsonSerializer.SerializeToElement(this._rawQueryData.Freeze()) - ), - } - ), - ModelBase.ToStringSerializerOptions - ); - - public virtual bool Equals(IntegrationSendTestParams? other) - { - if (other == null) - { - return false; - } - return (this.ID?.Equals(other.ID) ?? other.ID == null) - && this._rawHeaderData.Equals(other._rawHeaderData) - && this._rawQueryData.Equals(other._rawQueryData); - } - - public override Uri Url(ClientOptions options) - { - return new UriBuilder( - options.BaseUrl.ToString().TrimEnd('/') - + string.Format("/integrations/{0}/test", this.ID) - ) - { - Query = this.QueryString(options, SecurityOptions.All()), - }.Uri; - } - - internal override void AddHeadersToRequest(HttpRequestMessage request, ClientOptions options) - { - ParamsBase.AddDefaultHeaders(request, options, SecurityOptions.All()); - foreach (var item in this.RawHeaderData) - { - ParamsBase.AddHeaderElementToRequest(request, item.Key, item.Value); - } - } - - public override int GetHashCode() - { - return 0; - } -} diff --git a/src/XTwitterScraper/Models/Integrations/IntegrationSendTestResponse.cs b/src/XTwitterScraper/Models/Integrations/IntegrationSendTestResponse.cs deleted file mode 100644 index f2ce44a..0000000 --- a/src/XTwitterScraper/Models/Integrations/IntegrationSendTestResponse.cs +++ /dev/null @@ -1,76 +0,0 @@ -using System.Collections.Frozen; -using System.Collections.Generic; -using System.Diagnostics.CodeAnalysis; -using System.Text.Json; -using System.Text.Json.Serialization; -using XTwitterScraper.Core; -using XTwitterScraper.Exceptions; - -namespace XTwitterScraper.Models.Integrations; - -[JsonConverter( - typeof(JsonModelConverter) -)] -public sealed record class IntegrationSendTestResponse : JsonModel -{ - public JsonElement Success - { - get - { - this._rawData.Freeze(); - return this._rawData.GetNotNullStruct("success"); - } - init { this._rawData.Set("success", value); } - } - - /// - public override void Validate() - { - if (!JsonElement.DeepEquals(this.Success, JsonSerializer.SerializeToElement(true))) - { - throw new XTwitterScraperInvalidDataException("Invalid value given for constant"); - } - } - - public IntegrationSendTestResponse() - { - this.Success = JsonSerializer.SerializeToElement(true); - } - -#pragma warning disable CS8618 - [SetsRequiredMembers] - public IntegrationSendTestResponse(IntegrationSendTestResponse integrationSendTestResponse) - : base(integrationSendTestResponse) { } -#pragma warning restore CS8618 - - public IntegrationSendTestResponse(IReadOnlyDictionary rawData) - { - this._rawData = new(rawData); - - this.Success = JsonSerializer.SerializeToElement(true); - } - -#pragma warning disable CS8618 - [SetsRequiredMembers] - IntegrationSendTestResponse(FrozenDictionary rawData) - { - this._rawData = new(rawData); - } -#pragma warning restore CS8618 - - /// - public static IntegrationSendTestResponse FromRawUnchecked( - IReadOnlyDictionary rawData - ) - { - return new(FrozenDictionary.ToFrozenDictionary(rawData)); - } -} - -class IntegrationSendTestResponseFromRaw : IFromRawJson -{ - /// - public IntegrationSendTestResponse FromRawUnchecked( - IReadOnlyDictionary rawData - ) => IntegrationSendTestResponse.FromRawUnchecked(rawData); -} diff --git a/src/XTwitterScraper/Models/Integrations/IntegrationUpdateParams.cs b/src/XTwitterScraper/Models/Integrations/IntegrationUpdateParams.cs deleted file mode 100644 index 45593af..0000000 --- a/src/XTwitterScraper/Models/Integrations/IntegrationUpdateParams.cs +++ /dev/null @@ -1,298 +0,0 @@ -using System; -using System.Collections.Frozen; -using System.Collections.Generic; -using System.Collections.Immutable; -using System.Diagnostics.CodeAnalysis; -using System.Net.Http; -using System.Text; -using System.Text.Json; -using XTwitterScraper.Core; - -namespace XTwitterScraper.Models.Integrations; - -/// -/// Update integration -/// -/// NOTE: Do not inherit from this type outside the SDK unless you're okay with -/// breaking changes in non-major versions. We may add new methods in the future that -/// cause existing derived classes to break. -/// -public record class IntegrationUpdateParams : ParamsBase -{ - readonly JsonDictionary _rawBodyData = new(); - public IReadOnlyDictionary RawBodyData - { - get { return this._rawBodyData.Freeze(); } - } - - public string? ID { get; init; } - - /// - /// Array of event types to subscribe to. - /// - public IReadOnlyList>? EventTypes - { - get - { - this._rawBodyData.Freeze(); - return this._rawBodyData.GetNullableStruct>>( - "eventTypes" - ); - } - init - { - if (value == null) - { - return; - } - - this._rawBodyData.Set>?>( - "eventTypes", - value == null ? null : ImmutableArray.ToImmutableArray(value) - ); - } - } - - /// - /// Event filter rules (JSON) - /// - public IReadOnlyDictionary? Filters - { - get - { - this._rawBodyData.Freeze(); - return this._rawBodyData.GetNullableClass>( - "filters" - ); - } - init - { - if (value == null) - { - return; - } - - this._rawBodyData.Set?>( - "filters", - value == null ? null : FrozenDictionary.ToFrozenDictionary(value) - ); - } - } - - public bool? IsActive - { - get - { - this._rawBodyData.Freeze(); - return this._rawBodyData.GetNullableStruct("isActive"); - } - init - { - if (value == null) - { - return; - } - - this._rawBodyData.Set("isActive", value); - } - } - - /// - /// Custom message template (JSON) - /// - public IReadOnlyDictionary? MessageTemplate - { - get - { - this._rawBodyData.Freeze(); - return this._rawBodyData.GetNullableClass>( - "messageTemplate" - ); - } - init - { - if (value == null) - { - return; - } - - this._rawBodyData.Set?>( - "messageTemplate", - value == null ? null : FrozenDictionary.ToFrozenDictionary(value) - ); - } - } - - public string? Name - { - get - { - this._rawBodyData.Freeze(); - return this._rawBodyData.GetNullableClass("name"); - } - init - { - if (value == null) - { - return; - } - - this._rawBodyData.Set("name", value); - } - } - - public bool? ScopeAllMonitors - { - get - { - this._rawBodyData.Freeze(); - return this._rawBodyData.GetNullableStruct("scopeAllMonitors"); - } - init - { - if (value == null) - { - return; - } - - this._rawBodyData.Set("scopeAllMonitors", value); - } - } - - public bool? SilentPush - { - get - { - this._rawBodyData.Freeze(); - return this._rawBodyData.GetNullableStruct("silentPush"); - } - init - { - if (value == null) - { - return; - } - - this._rawBodyData.Set("silentPush", value); - } - } - - public IntegrationUpdateParams() { } - -#pragma warning disable CS8618 - [SetsRequiredMembers] - public IntegrationUpdateParams(IntegrationUpdateParams integrationUpdateParams) - : base(integrationUpdateParams) - { - this.ID = integrationUpdateParams.ID; - - this._rawBodyData = new(integrationUpdateParams._rawBodyData); - } -#pragma warning restore CS8618 - - public IntegrationUpdateParams( - IReadOnlyDictionary rawHeaderData, - IReadOnlyDictionary rawQueryData, - IReadOnlyDictionary rawBodyData - ) - { - this._rawHeaderData = new(rawHeaderData); - this._rawQueryData = new(rawQueryData); - this._rawBodyData = new(rawBodyData); - } - -#pragma warning disable CS8618 - [SetsRequiredMembers] - IntegrationUpdateParams( - FrozenDictionary rawHeaderData, - FrozenDictionary rawQueryData, - FrozenDictionary rawBodyData, - string id - ) - { - this._rawHeaderData = new(rawHeaderData); - this._rawQueryData = new(rawQueryData); - this._rawBodyData = new(rawBodyData); - this.ID = id; - } -#pragma warning restore CS8618 - - /// - public static IntegrationUpdateParams FromRawUnchecked( - IReadOnlyDictionary rawHeaderData, - IReadOnlyDictionary rawQueryData, - IReadOnlyDictionary rawBodyData, - string id - ) - { - return new( - FrozenDictionary.ToFrozenDictionary(rawHeaderData), - FrozenDictionary.ToFrozenDictionary(rawQueryData), - FrozenDictionary.ToFrozenDictionary(rawBodyData), - id - ); - } - - public override string ToString() => - JsonSerializer.Serialize( - FriendlyJsonPrinter.PrintValue( - new Dictionary() - { - ["ID"] = JsonSerializer.SerializeToElement(this.ID), - ["HeaderData"] = FriendlyJsonPrinter.PrintValue( - JsonSerializer.SerializeToElement(this._rawHeaderData.Freeze()) - ), - ["QueryData"] = FriendlyJsonPrinter.PrintValue( - JsonSerializer.SerializeToElement(this._rawQueryData.Freeze()) - ), - ["BodyData"] = FriendlyJsonPrinter.PrintValue(this._rawBodyData.Freeze()), - } - ), - ModelBase.ToStringSerializerOptions - ); - - public virtual bool Equals(IntegrationUpdateParams? other) - { - if (other == null) - { - return false; - } - return (this.ID?.Equals(other.ID) ?? other.ID == null) - && this._rawHeaderData.Equals(other._rawHeaderData) - && this._rawQueryData.Equals(other._rawQueryData) - && this._rawBodyData.Equals(other._rawBodyData); - } - - public override Uri Url(ClientOptions options) - { - return new UriBuilder( - options.BaseUrl.ToString().TrimEnd('/') + string.Format("/integrations/{0}", this.ID) - ) - { - Query = this.QueryString(options, SecurityOptions.All()), - }.Uri; - } - - internal override HttpContent? BodyContent() - { - return new StringContent( - JsonSerializer.Serialize(this.RawBodyData, ModelBase.SerializerOptions), - Encoding.UTF8, - "application/json" - ); - } - - internal override void AddHeadersToRequest(HttpRequestMessage request, ClientOptions options) - { - ParamsBase.AddDefaultHeaders(request, options, SecurityOptions.All()); - foreach (var item in this.RawHeaderData) - { - ParamsBase.AddHeaderElementToRequest(request, item.Key, item.Value); - } - } - - public override int GetHashCode() - { - return 0; - } -} diff --git a/src/XTwitterScraper/Models/Monitors/MonitorCreateParams.cs b/src/XTwitterScraper/Models/Monitors/MonitorCreateParams.cs index c8a08b9..3d5aaee 100644 --- a/src/XTwitterScraper/Models/Monitors/MonitorCreateParams.cs +++ b/src/XTwitterScraper/Models/Monitors/MonitorCreateParams.cs @@ -141,7 +141,7 @@ public override Uri Url(ClientOptions options) { return new UriBuilder(options.BaseUrl.ToString().TrimEnd('/') + "/monitors") { - Query = this.QueryString(options, SecurityOptions.All()), + Query = this.QueryString(options), }.Uri; } @@ -156,7 +156,7 @@ public override Uri Url(ClientOptions options) internal override void AddHeadersToRequest(HttpRequestMessage request, ClientOptions options) { - ParamsBase.AddDefaultHeaders(request, options, SecurityOptions.All()); + ParamsBase.AddDefaultHeaders(request, options); foreach (var item in this.RawHeaderData) { ParamsBase.AddHeaderElementToRequest(request, item.Key, item.Value); diff --git a/src/XTwitterScraper/Models/Monitors/MonitorDeactivateParams.cs b/src/XTwitterScraper/Models/Monitors/MonitorDeactivateParams.cs index 28e1487..df2c73f 100644 --- a/src/XTwitterScraper/Models/Monitors/MonitorDeactivateParams.cs +++ b/src/XTwitterScraper/Models/Monitors/MonitorDeactivateParams.cs @@ -101,13 +101,13 @@ public override Uri Url(ClientOptions options) options.BaseUrl.ToString().TrimEnd('/') + string.Format("/monitors/{0}", this.ID) ) { - Query = this.QueryString(options, SecurityOptions.All()), + Query = this.QueryString(options), }.Uri; } internal override void AddHeadersToRequest(HttpRequestMessage request, ClientOptions options) { - ParamsBase.AddDefaultHeaders(request, options, SecurityOptions.All()); + ParamsBase.AddDefaultHeaders(request, options); foreach (var item in this.RawHeaderData) { ParamsBase.AddHeaderElementToRequest(request, item.Key, item.Value); diff --git a/src/XTwitterScraper/Models/Monitors/MonitorListParams.cs b/src/XTwitterScraper/Models/Monitors/MonitorListParams.cs index b95815b..3f20809 100644 --- a/src/XTwitterScraper/Models/Monitors/MonitorListParams.cs +++ b/src/XTwitterScraper/Models/Monitors/MonitorListParams.cs @@ -88,13 +88,13 @@ public override Uri Url(ClientOptions options) { return new UriBuilder(options.BaseUrl.ToString().TrimEnd('/') + "/monitors") { - Query = this.QueryString(options, SecurityOptions.All()), + Query = this.QueryString(options), }.Uri; } internal override void AddHeadersToRequest(HttpRequestMessage request, ClientOptions options) { - ParamsBase.AddDefaultHeaders(request, options, SecurityOptions.All()); + ParamsBase.AddDefaultHeaders(request, options); foreach (var item in this.RawHeaderData) { ParamsBase.AddHeaderElementToRequest(request, item.Key, item.Value); diff --git a/src/XTwitterScraper/Models/Monitors/MonitorRetrieveParams.cs b/src/XTwitterScraper/Models/Monitors/MonitorRetrieveParams.cs index c3ab890..cff2d21 100644 --- a/src/XTwitterScraper/Models/Monitors/MonitorRetrieveParams.cs +++ b/src/XTwitterScraper/Models/Monitors/MonitorRetrieveParams.cs @@ -101,13 +101,13 @@ public override Uri Url(ClientOptions options) options.BaseUrl.ToString().TrimEnd('/') + string.Format("/monitors/{0}", this.ID) ) { - Query = this.QueryString(options, SecurityOptions.All()), + Query = this.QueryString(options), }.Uri; } internal override void AddHeadersToRequest(HttpRequestMessage request, ClientOptions options) { - ParamsBase.AddDefaultHeaders(request, options, SecurityOptions.All()); + ParamsBase.AddDefaultHeaders(request, options); foreach (var item in this.RawHeaderData) { ParamsBase.AddHeaderElementToRequest(request, item.Key, item.Value); diff --git a/src/XTwitterScraper/Models/Monitors/MonitorUpdateParams.cs b/src/XTwitterScraper/Models/Monitors/MonitorUpdateParams.cs index c663e04..590303c 100644 --- a/src/XTwitterScraper/Models/Monitors/MonitorUpdateParams.cs +++ b/src/XTwitterScraper/Models/Monitors/MonitorUpdateParams.cs @@ -163,7 +163,7 @@ public override Uri Url(ClientOptions options) options.BaseUrl.ToString().TrimEnd('/') + string.Format("/monitors/{0}", this.ID) ) { - Query = this.QueryString(options, SecurityOptions.All()), + Query = this.QueryString(options), }.Uri; } @@ -178,7 +178,7 @@ public override Uri Url(ClientOptions options) internal override void AddHeadersToRequest(HttpRequestMessage request, ClientOptions options) { - ParamsBase.AddDefaultHeaders(request, options, SecurityOptions.All()); + ParamsBase.AddDefaultHeaders(request, options); foreach (var item in this.RawHeaderData) { ParamsBase.AddHeaderElementToRequest(request, item.Key, item.Value); diff --git a/src/XTwitterScraper/Models/PaginatedTweets.cs b/src/XTwitterScraper/Models/PaginatedTweets.cs index 6430f8e..e80e879 100644 --- a/src/XTwitterScraper/Models/PaginatedTweets.cs +++ b/src/XTwitterScraper/Models/PaginatedTweets.cs @@ -5,7 +5,6 @@ using System.Text.Json; using System.Text.Json.Serialization; using XTwitterScraper.Core; -using XTwitterScraper.Models.X.Tweets; namespace XTwitterScraper.Models; diff --git a/src/XTwitterScraper/Models/PaginatedUsers.cs b/src/XTwitterScraper/Models/PaginatedUsers.cs index cc48a07..ae840e8 100644 --- a/src/XTwitterScraper/Models/PaginatedUsers.cs +++ b/src/XTwitterScraper/Models/PaginatedUsers.cs @@ -5,7 +5,6 @@ using System.Text.Json; using System.Text.Json.Serialization; using XTwitterScraper.Core; -using XTwitterScraper.Models.X.Users; namespace XTwitterScraper.Models; diff --git a/src/XTwitterScraper/Models/Radar/RadarItem.cs b/src/XTwitterScraper/Models/Radar/RadarItem.cs index 52b06f3..f311f39 100644 --- a/src/XTwitterScraper/Models/Radar/RadarItem.cs +++ b/src/XTwitterScraper/Models/Radar/RadarItem.cs @@ -5,25 +5,84 @@ using System.Text.Json; using System.Text.Json.Serialization; using XTwitterScraper.Core; +using XTwitterScraper.Exceptions; namespace XTwitterScraper.Models.Radar; /// -/// Trending topic with score, category, source, and region. +/// Trending topic with score, category, source, region, language, and source-specific metadata. /// [JsonConverter(typeof(JsonModelConverter))] public sealed record class RadarItem : JsonModel { - public required string Category + /// + /// Internal numeric identifier (stringified bigint). + /// + public required string ID { get { this._rawData.Freeze(); - return this._rawData.GetNotNullClass("category"); + return this._rawData.GetNotNullClass("id"); + } + init { this._rawData.Set("id", value); } + } + + public required ApiEnum Category + { + get + { + this._rawData.Freeze(); + return this._rawData.GetNotNullClass>("category"); } init { this._rawData.Set("category", value); } } + public required DateTimeOffset CreatedAt + { + get + { + this._rawData.Freeze(); + return this._rawData.GetNotNullStruct("createdAt"); + } + init { this._rawData.Set("createdAt", value); } + } + + public required string Language + { + get + { + this._rawData.Freeze(); + return this._rawData.GetNotNullClass("language"); + } + init { this._rawData.Set("language", value); } + } + + /// + /// Source-specific fields. Shape varies per source: - reddit: { subreddit: string, + /// author: string } - github: { starsToday: number } - hacker_news: { points: + /// number, numberComments: number } - google_trends: { approxTraffic: number + /// } - polymarket: { volume24hr: number } - wikipedia: { views: number } - trustmrr: + /// { mrr, growthPercent, last30Days, total, customers, activeSubscriptions, onSale, + /// xHandle?, category?, askingPrice?, country?, growthMrrPercent?, multiple?, + /// paymentProvider?, rank? } + /// + public required IReadOnlyDictionary Metadata + { + get + { + this._rawData.Freeze(); + return this._rawData.GetNotNullClass>("metadata"); + } + init + { + this._rawData.Set>( + "metadata", + FrozenDictionary.ToFrozenDictionary(value) + ); + } + } + public required DateTimeOffset PublishedAt { get @@ -54,16 +113,29 @@ public required double Score init { this._rawData.Set("score", value); } } - public required string Source + public required ApiEnum Source { get { this._rawData.Freeze(); - return this._rawData.GetNotNullClass("source"); + return this._rawData.GetNotNullClass>("source"); } init { this._rawData.Set("source", value); } } + /// + /// Source-specific identifier used for deduplication. + /// + public required string SourceID + { + get + { + this._rawData.Freeze(); + return this._rawData.GetNotNullClass("sourceId"); + } + init { this._rawData.Set("sourceId", value); } + } + public required string Title { get @@ -131,11 +203,16 @@ public string? Url /// public override void Validate() { - _ = this.Category; + _ = this.ID; + this.Category.Validate(); + _ = this.CreatedAt; + _ = this.Language; + _ = this.Metadata; _ = this.PublishedAt; _ = this.Region; _ = this.Score; - _ = this.Source; + this.Source.Validate(); + _ = this.SourceID; _ = this.Title; _ = this.Description; _ = this.ImageUrl; @@ -176,3 +253,124 @@ class RadarItemFromRaw : IFromRawJson public RadarItem FromRawUnchecked(IReadOnlyDictionary rawData) => RadarItem.FromRawUnchecked(rawData); } + +[JsonConverter(typeof(RadarItemCategoryConverter))] +public enum RadarItemCategory +{ + General, + Tech, + Dev, + Science, + Culture, + Politics, + Business, + Entertainment, +} + +sealed class RadarItemCategoryConverter : JsonConverter +{ + public override RadarItemCategory Read( + ref Utf8JsonReader reader, + Type typeToConvert, + JsonSerializerOptions options + ) + { + return JsonSerializer.Deserialize(ref reader, options) switch + { + "general" => RadarItemCategory.General, + "tech" => RadarItemCategory.Tech, + "dev" => RadarItemCategory.Dev, + "science" => RadarItemCategory.Science, + "culture" => RadarItemCategory.Culture, + "politics" => RadarItemCategory.Politics, + "business" => RadarItemCategory.Business, + "entertainment" => RadarItemCategory.Entertainment, + _ => (RadarItemCategory)(-1), + }; + } + + public override void Write( + Utf8JsonWriter writer, + RadarItemCategory value, + JsonSerializerOptions options + ) + { + JsonSerializer.Serialize( + writer, + value switch + { + RadarItemCategory.General => "general", + RadarItemCategory.Tech => "tech", + RadarItemCategory.Dev => "dev", + RadarItemCategory.Science => "science", + RadarItemCategory.Culture => "culture", + RadarItemCategory.Politics => "politics", + RadarItemCategory.Business => "business", + RadarItemCategory.Entertainment => "entertainment", + _ => throw new XTwitterScraperInvalidDataException( + string.Format("Invalid value '{0}' in {1}", value, nameof(value)) + ), + }, + options + ); + } +} + +[JsonConverter(typeof(RadarItemSourceConverter))] +public enum RadarItemSource +{ + GitHub, + GoogleTrends, + HackerNews, + Polymarket, + Reddit, + Trustmrr, + Wikipedia, +} + +sealed class RadarItemSourceConverter : JsonConverter +{ + public override RadarItemSource Read( + ref Utf8JsonReader reader, + Type typeToConvert, + JsonSerializerOptions options + ) + { + return JsonSerializer.Deserialize(ref reader, options) switch + { + "github" => RadarItemSource.GitHub, + "google_trends" => RadarItemSource.GoogleTrends, + "hacker_news" => RadarItemSource.HackerNews, + "polymarket" => RadarItemSource.Polymarket, + "reddit" => RadarItemSource.Reddit, + "trustmrr" => RadarItemSource.Trustmrr, + "wikipedia" => RadarItemSource.Wikipedia, + _ => (RadarItemSource)(-1), + }; + } + + public override void Write( + Utf8JsonWriter writer, + RadarItemSource value, + JsonSerializerOptions options + ) + { + JsonSerializer.Serialize( + writer, + value switch + { + RadarItemSource.GitHub => "github", + RadarItemSource.GoogleTrends => "google_trends", + RadarItemSource.HackerNews => "hacker_news", + RadarItemSource.Polymarket => "polymarket", + RadarItemSource.Reddit => "reddit", + RadarItemSource.Trustmrr => "trustmrr", + RadarItemSource.Wikipedia => "wikipedia", + _ => throw new XTwitterScraperInvalidDataException( + string.Format("Invalid value '{0}' in {1}", value, nameof(value)) + ), + }, + options + ); + } +} diff --git a/src/XTwitterScraper/Models/Radar/RadarRetrieveTrendingTopicsParams.cs b/src/XTwitterScraper/Models/Radar/RadarRetrieveTrendingTopicsParams.cs index 49256bf..cf57275 100644 --- a/src/XTwitterScraper/Models/Radar/RadarRetrieveTrendingTopicsParams.cs +++ b/src/XTwitterScraper/Models/Radar/RadarRetrieveTrendingTopicsParams.cs @@ -20,14 +20,14 @@ namespace XTwitterScraper.Models.Radar; public record class RadarRetrieveTrendingTopicsParams : ParamsBase { /// - /// Filter by category (general, tech, dev, etc.) + /// Cursor for pagination (from prior response nextCursor). /// - public string? Category + public string? After { get { this._rawQueryData.Freeze(); - return this._rawQueryData.GetNullableClass("category"); + return this._rawQueryData.GetNullableClass("after"); } init { @@ -36,19 +36,19 @@ public string? Category return; } - this._rawQueryData.Set("category", value); + this._rawQueryData.Set("after", value); } } /// - /// Number of items to return + /// Filter by category. /// - public long? Count + public ApiEnum? Category { get { this._rawQueryData.Freeze(); - return this._rawQueryData.GetNullableStruct("count"); + return this._rawQueryData.GetNullableClass>("category"); } init { @@ -57,12 +57,12 @@ public long? Count return; } - this._rawQueryData.Set("count", value); + this._rawQueryData.Set("category", value); } } /// - /// Lookback window in hours + /// Lookback window in hours (1-168, default 24). /// public long? Hours { @@ -82,6 +82,27 @@ public long? Hours } } + /// + /// Number of items to return (1-100, default 50). + /// + public long? Limit + { + get + { + this._rawQueryData.Freeze(); + return this._rawQueryData.GetNullableStruct("limit"); + } + init + { + if (value == null) + { + return; + } + + this._rawQueryData.Set("limit", value); + } + } + /// /// Region filter (us, global, etc.) /// @@ -198,13 +219,13 @@ public override Uri Url(ClientOptions options) { return new UriBuilder(options.BaseUrl.ToString().TrimEnd('/') + "/radar") { - Query = this.QueryString(options, SecurityOptions.All()), + Query = this.QueryString(options), }.Uri; } internal override void AddHeadersToRequest(HttpRequestMessage request, ClientOptions options) { - ParamsBase.AddDefaultHeaders(request, options, SecurityOptions.All()); + ParamsBase.AddDefaultHeaders(request, options); foreach (var item in this.RawHeaderData) { ParamsBase.AddHeaderElementToRequest(request, item.Key, item.Value); @@ -217,6 +238,67 @@ public override int GetHashCode() } } +/// +/// Filter by category. +/// +[JsonConverter(typeof(CategoryConverter))] +public enum Category +{ + General, + Tech, + Dev, + Science, + Culture, + Politics, + Business, + Entertainment, +} + +sealed class CategoryConverter : JsonConverter +{ + public override Category Read( + ref Utf8JsonReader reader, + Type typeToConvert, + JsonSerializerOptions options + ) + { + return JsonSerializer.Deserialize(ref reader, options) switch + { + "general" => Category.General, + "tech" => Category.Tech, + "dev" => Category.Dev, + "science" => Category.Science, + "culture" => Category.Culture, + "politics" => Category.Politics, + "business" => Category.Business, + "entertainment" => Category.Entertainment, + _ => (Category)(-1), + }; + } + + public override void Write(Utf8JsonWriter writer, Category value, JsonSerializerOptions options) + { + JsonSerializer.Serialize( + writer, + value switch + { + Category.General => "general", + Category.Tech => "tech", + Category.Dev => "dev", + Category.Science => "science", + Category.Culture => "culture", + Category.Politics => "politics", + Category.Business => "business", + Category.Entertainment => "entertainment", + _ => throw new XTwitterScraperInvalidDataException( + string.Format("Invalid value '{0}' in {1}", value, nameof(value)) + ), + }, + options + ); + } +} + /// /// Source filter. One of: github, google_trends, hacker_news, polymarket, reddit, /// trustmrr, wikipedia diff --git a/src/XTwitterScraper/Models/Radar/RadarRetrieveTrendingTopicsResponse.cs b/src/XTwitterScraper/Models/Radar/RadarRetrieveTrendingTopicsResponse.cs index 49119cc..6bfe047 100644 --- a/src/XTwitterScraper/Models/Radar/RadarRetrieveTrendingTopicsResponse.cs +++ b/src/XTwitterScraper/Models/Radar/RadarRetrieveTrendingTopicsResponse.cs @@ -16,6 +16,16 @@ namespace XTwitterScraper.Models.Radar; )] public sealed record class RadarRetrieveTrendingTopicsResponse : JsonModel { + public required bool HasMore + { + get + { + this._rawData.Freeze(); + return this._rawData.GetNotNullStruct("hasMore"); + } + init { this._rawData.Set("hasMore", value); } + } + public required IReadOnlyList Items { get @@ -32,24 +42,36 @@ public required IReadOnlyList Items } } - public required long Total + /// + /// Opaque cursor for the next page (present only when hasMore is true). + /// + public string? NextCursor { get { this._rawData.Freeze(); - return this._rawData.GetNotNullStruct("total"); + return this._rawData.GetNullableClass("nextCursor"); + } + init + { + if (value == null) + { + return; + } + + this._rawData.Set("nextCursor", value); } - init { this._rawData.Set("total", value); } } /// public override void Validate() { + _ = this.HasMore; foreach (var item in this.Items) { item.Validate(); } - _ = this.Total; + _ = this.NextCursor; } public RadarRetrieveTrendingTopicsResponse() { } diff --git a/src/XTwitterScraper/Models/X/Tweets/SearchTweet.cs b/src/XTwitterScraper/Models/SearchTweet.cs similarity index 95% rename from src/XTwitterScraper/Models/X/Tweets/SearchTweet.cs rename to src/XTwitterScraper/Models/SearchTweet.cs index ff98ace..94ad547 100644 --- a/src/XTwitterScraper/Models/X/Tweets/SearchTweet.cs +++ b/src/XTwitterScraper/Models/SearchTweet.cs @@ -5,7 +5,7 @@ using System.Text.Json.Serialization; using XTwitterScraper.Core; -namespace XTwitterScraper.Models.X.Tweets; +namespace XTwitterScraper.Models; /// /// Tweet returned from search results with inline author info. diff --git a/src/XTwitterScraper/Models/Styles/StyleAnalyzeParams.cs b/src/XTwitterScraper/Models/Styles/StyleAnalyzeParams.cs index 6eb38b2..2a6d7fe 100644 --- a/src/XTwitterScraper/Models/Styles/StyleAnalyzeParams.cs +++ b/src/XTwitterScraper/Models/Styles/StyleAnalyzeParams.cs @@ -119,7 +119,7 @@ public override Uri Url(ClientOptions options) { return new UriBuilder(options.BaseUrl.ToString().TrimEnd('/') + "/styles") { - Query = this.QueryString(options, SecurityOptions.All()), + Query = this.QueryString(options), }.Uri; } @@ -134,7 +134,7 @@ public override Uri Url(ClientOptions options) internal override void AddHeadersToRequest(HttpRequestMessage request, ClientOptions options) { - ParamsBase.AddDefaultHeaders(request, options, SecurityOptions.All()); + ParamsBase.AddDefaultHeaders(request, options); foreach (var item in this.RawHeaderData) { ParamsBase.AddHeaderElementToRequest(request, item.Key, item.Value); diff --git a/src/XTwitterScraper/Models/Styles/StyleCompareParams.cs b/src/XTwitterScraper/Models/Styles/StyleCompareParams.cs index 20ea10e..c74281f 100644 --- a/src/XTwitterScraper/Models/Styles/StyleCompareParams.cs +++ b/src/XTwitterScraper/Models/Styles/StyleCompareParams.cs @@ -114,13 +114,13 @@ public override Uri Url(ClientOptions options) { return new UriBuilder(options.BaseUrl.ToString().TrimEnd('/') + "/styles/compare") { - Query = this.QueryString(options, SecurityOptions.All()), + Query = this.QueryString(options), }.Uri; } internal override void AddHeadersToRequest(HttpRequestMessage request, ClientOptions options) { - ParamsBase.AddDefaultHeaders(request, options, SecurityOptions.All()); + ParamsBase.AddDefaultHeaders(request, options); foreach (var item in this.RawHeaderData) { ParamsBase.AddHeaderElementToRequest(request, item.Key, item.Value); diff --git a/src/XTwitterScraper/Models/Styles/StyleDeleteParams.cs b/src/XTwitterScraper/Models/Styles/StyleDeleteParams.cs index 3c1b0c3..19cb7fc 100644 --- a/src/XTwitterScraper/Models/Styles/StyleDeleteParams.cs +++ b/src/XTwitterScraper/Models/Styles/StyleDeleteParams.cs @@ -101,13 +101,13 @@ public override Uri Url(ClientOptions options) options.BaseUrl.ToString().TrimEnd('/') + string.Format("/styles/{0}", this.ID) ) { - Query = this.QueryString(options, SecurityOptions.All()), + Query = this.QueryString(options), }.Uri; } internal override void AddHeadersToRequest(HttpRequestMessage request, ClientOptions options) { - ParamsBase.AddDefaultHeaders(request, options, SecurityOptions.All()); + ParamsBase.AddDefaultHeaders(request, options); foreach (var item in this.RawHeaderData) { ParamsBase.AddHeaderElementToRequest(request, item.Key, item.Value); diff --git a/src/XTwitterScraper/Models/Styles/StyleGetPerformanceParams.cs b/src/XTwitterScraper/Models/Styles/StyleGetPerformanceParams.cs index 54c5c7a..42deb85 100644 --- a/src/XTwitterScraper/Models/Styles/StyleGetPerformanceParams.cs +++ b/src/XTwitterScraper/Models/Styles/StyleGetPerformanceParams.cs @@ -102,13 +102,13 @@ public override Uri Url(ClientOptions options) + string.Format("/styles/{0}/performance", this.ID) ) { - Query = this.QueryString(options, SecurityOptions.All()), + Query = this.QueryString(options), }.Uri; } internal override void AddHeadersToRequest(HttpRequestMessage request, ClientOptions options) { - ParamsBase.AddDefaultHeaders(request, options, SecurityOptions.All()); + ParamsBase.AddDefaultHeaders(request, options); foreach (var item in this.RawHeaderData) { ParamsBase.AddHeaderElementToRequest(request, item.Key, item.Value); diff --git a/src/XTwitterScraper/Models/Styles/StyleListParams.cs b/src/XTwitterScraper/Models/Styles/StyleListParams.cs index ce0176a..4bba7e9 100644 --- a/src/XTwitterScraper/Models/Styles/StyleListParams.cs +++ b/src/XTwitterScraper/Models/Styles/StyleListParams.cs @@ -88,13 +88,13 @@ public override Uri Url(ClientOptions options) { return new UriBuilder(options.BaseUrl.ToString().TrimEnd('/') + "/styles") { - Query = this.QueryString(options, SecurityOptions.All()), + Query = this.QueryString(options), }.Uri; } internal override void AddHeadersToRequest(HttpRequestMessage request, ClientOptions options) { - ParamsBase.AddDefaultHeaders(request, options, SecurityOptions.All()); + ParamsBase.AddDefaultHeaders(request, options); foreach (var item in this.RawHeaderData) { ParamsBase.AddHeaderElementToRequest(request, item.Key, item.Value); diff --git a/src/XTwitterScraper/Models/Styles/StyleRetrieveParams.cs b/src/XTwitterScraper/Models/Styles/StyleRetrieveParams.cs index 0464804..728334b 100644 --- a/src/XTwitterScraper/Models/Styles/StyleRetrieveParams.cs +++ b/src/XTwitterScraper/Models/Styles/StyleRetrieveParams.cs @@ -101,13 +101,13 @@ public override Uri Url(ClientOptions options) options.BaseUrl.ToString().TrimEnd('/') + string.Format("/styles/{0}", this.ID) ) { - Query = this.QueryString(options, SecurityOptions.All()), + Query = this.QueryString(options), }.Uri; } internal override void AddHeadersToRequest(HttpRequestMessage request, ClientOptions options) { - ParamsBase.AddDefaultHeaders(request, options, SecurityOptions.All()); + ParamsBase.AddDefaultHeaders(request, options); foreach (var item in this.RawHeaderData) { ParamsBase.AddHeaderElementToRequest(request, item.Key, item.Value); diff --git a/src/XTwitterScraper/Models/Styles/StyleUpdateParams.cs b/src/XTwitterScraper/Models/Styles/StyleUpdateParams.cs index 3a7868b..103d6d0 100644 --- a/src/XTwitterScraper/Models/Styles/StyleUpdateParams.cs +++ b/src/XTwitterScraper/Models/Styles/StyleUpdateParams.cs @@ -152,7 +152,7 @@ public override Uri Url(ClientOptions options) options.BaseUrl.ToString().TrimEnd('/') + string.Format("/styles/{0}", this.ID) ) { - Query = this.QueryString(options, SecurityOptions.All()), + Query = this.QueryString(options), }.Uri; } @@ -167,7 +167,7 @@ public override Uri Url(ClientOptions options) internal override void AddHeadersToRequest(HttpRequestMessage request, ClientOptions options) { - ParamsBase.AddDefaultHeaders(request, options, SecurityOptions.All()); + ParamsBase.AddDefaultHeaders(request, options); foreach (var item in this.RawHeaderData) { ParamsBase.AddHeaderElementToRequest(request, item.Key, item.Value); diff --git a/src/XTwitterScraper/Models/Subscribe/SubscribeCreateParams.cs b/src/XTwitterScraper/Models/Subscribe/SubscribeCreateParams.cs index 8ed2f52..6f153c2 100644 --- a/src/XTwitterScraper/Models/Subscribe/SubscribeCreateParams.cs +++ b/src/XTwitterScraper/Models/Subscribe/SubscribeCreateParams.cs @@ -88,13 +88,13 @@ public override Uri Url(ClientOptions options) { return new UriBuilder(options.BaseUrl.ToString().TrimEnd('/') + "/subscribe") { - Query = this.QueryString(options, SecurityOptions.All()), + Query = this.QueryString(options), }.Uri; } internal override void AddHeadersToRequest(HttpRequestMessage request, ClientOptions options) { - ParamsBase.AddDefaultHeaders(request, options, SecurityOptions.All()); + ParamsBase.AddDefaultHeaders(request, options); foreach (var item in this.RawHeaderData) { ParamsBase.AddHeaderElementToRequest(request, item.Key, item.Value); diff --git a/src/XTwitterScraper/Models/Support/Tickets/TicketCreateParams.cs b/src/XTwitterScraper/Models/Support/Tickets/TicketCreateParams.cs index fdba99e..573f01b 100644 --- a/src/XTwitterScraper/Models/Support/Tickets/TicketCreateParams.cs +++ b/src/XTwitterScraper/Models/Support/Tickets/TicketCreateParams.cs @@ -126,7 +126,7 @@ public override Uri Url(ClientOptions options) { return new UriBuilder(options.BaseUrl.ToString().TrimEnd('/') + "/support/tickets") { - Query = this.QueryString(options, SecurityOptions.All()), + Query = this.QueryString(options), }.Uri; } @@ -141,7 +141,7 @@ public override Uri Url(ClientOptions options) internal override void AddHeadersToRequest(HttpRequestMessage request, ClientOptions options) { - ParamsBase.AddDefaultHeaders(request, options, SecurityOptions.All()); + ParamsBase.AddDefaultHeaders(request, options); foreach (var item in this.RawHeaderData) { ParamsBase.AddHeaderElementToRequest(request, item.Key, item.Value); diff --git a/src/XTwitterScraper/Models/Support/Tickets/TicketListParams.cs b/src/XTwitterScraper/Models/Support/Tickets/TicketListParams.cs index da239df..8f8d39d 100644 --- a/src/XTwitterScraper/Models/Support/Tickets/TicketListParams.cs +++ b/src/XTwitterScraper/Models/Support/Tickets/TicketListParams.cs @@ -88,13 +88,13 @@ public override Uri Url(ClientOptions options) { return new UriBuilder(options.BaseUrl.ToString().TrimEnd('/') + "/support/tickets") { - Query = this.QueryString(options, SecurityOptions.All()), + Query = this.QueryString(options), }.Uri; } internal override void AddHeadersToRequest(HttpRequestMessage request, ClientOptions options) { - ParamsBase.AddDefaultHeaders(request, options, SecurityOptions.All()); + ParamsBase.AddDefaultHeaders(request, options); foreach (var item in this.RawHeaderData) { ParamsBase.AddHeaderElementToRequest(request, item.Key, item.Value); diff --git a/src/XTwitterScraper/Models/Support/Tickets/TicketReplyParams.cs b/src/XTwitterScraper/Models/Support/Tickets/TicketReplyParams.cs index 9c504b9..f36f56c 100644 --- a/src/XTwitterScraper/Models/Support/Tickets/TicketReplyParams.cs +++ b/src/XTwitterScraper/Models/Support/Tickets/TicketReplyParams.cs @@ -129,7 +129,7 @@ public override Uri Url(ClientOptions options) + string.Format("/support/tickets/{0}/messages", this.ID) ) { - Query = this.QueryString(options, SecurityOptions.All()), + Query = this.QueryString(options), }.Uri; } @@ -144,7 +144,7 @@ public override Uri Url(ClientOptions options) internal override void AddHeadersToRequest(HttpRequestMessage request, ClientOptions options) { - ParamsBase.AddDefaultHeaders(request, options, SecurityOptions.All()); + ParamsBase.AddDefaultHeaders(request, options); foreach (var item in this.RawHeaderData) { ParamsBase.AddHeaderElementToRequest(request, item.Key, item.Value); diff --git a/src/XTwitterScraper/Models/Support/Tickets/TicketRetrieveParams.cs b/src/XTwitterScraper/Models/Support/Tickets/TicketRetrieveParams.cs index d1edb35..9304e8c 100644 --- a/src/XTwitterScraper/Models/Support/Tickets/TicketRetrieveParams.cs +++ b/src/XTwitterScraper/Models/Support/Tickets/TicketRetrieveParams.cs @@ -101,13 +101,13 @@ public override Uri Url(ClientOptions options) options.BaseUrl.ToString().TrimEnd('/') + string.Format("/support/tickets/{0}", this.ID) ) { - Query = this.QueryString(options, SecurityOptions.All()), + Query = this.QueryString(options), }.Uri; } internal override void AddHeadersToRequest(HttpRequestMessage request, ClientOptions options) { - ParamsBase.AddDefaultHeaders(request, options, SecurityOptions.All()); + ParamsBase.AddDefaultHeaders(request, options); foreach (var item in this.RawHeaderData) { ParamsBase.AddHeaderElementToRequest(request, item.Key, item.Value); diff --git a/src/XTwitterScraper/Models/Support/Tickets/TicketUpdateParams.cs b/src/XTwitterScraper/Models/Support/Tickets/TicketUpdateParams.cs index 2dc03f8..b062c9e 100644 --- a/src/XTwitterScraper/Models/Support/Tickets/TicketUpdateParams.cs +++ b/src/XTwitterScraper/Models/Support/Tickets/TicketUpdateParams.cs @@ -130,7 +130,7 @@ public override Uri Url(ClientOptions options) options.BaseUrl.ToString().TrimEnd('/') + string.Format("/support/tickets/{0}", this.ID) ) { - Query = this.QueryString(options, SecurityOptions.All()), + Query = this.QueryString(options), }.Uri; } @@ -145,7 +145,7 @@ public override Uri Url(ClientOptions options) internal override void AddHeadersToRequest(HttpRequestMessage request, ClientOptions options) { - ParamsBase.AddDefaultHeaders(request, options, SecurityOptions.All()); + ParamsBase.AddDefaultHeaders(request, options); foreach (var item in this.RawHeaderData) { ParamsBase.AddHeaderElementToRequest(request, item.Key, item.Value); diff --git a/src/XTwitterScraper/Models/Trends/TrendListParams.cs b/src/XTwitterScraper/Models/Trends/TrendListParams.cs index 34974b5..3a32374 100644 --- a/src/XTwitterScraper/Models/Trends/TrendListParams.cs +++ b/src/XTwitterScraper/Models/Trends/TrendListParams.cs @@ -9,7 +9,7 @@ namespace XTwitterScraper.Models.Trends; /// -/// Get regional trending topics +/// Get trending hashtags & topics by region (alias) /// /// NOTE: Do not inherit from this type outside the SDK unless you're okay with /// breaking changes in non-major versions. We may add new methods in the future that @@ -130,13 +130,13 @@ public override Uri Url(ClientOptions options) { return new UriBuilder(options.BaseUrl.ToString().TrimEnd('/') + "/trends") { - Query = this.QueryString(options, SecurityOptions.All()), + Query = this.QueryString(options), }.Uri; } internal override void AddHeadersToRequest(HttpRequestMessage request, ClientOptions options) { - ParamsBase.AddDefaultHeaders(request, options, SecurityOptions.All()); + ParamsBase.AddDefaultHeaders(request, options); foreach (var item in this.RawHeaderData) { ParamsBase.AddHeaderElementToRequest(request, item.Key, item.Value); diff --git a/src/XTwitterScraper/Models/X/Users/UserProfile.cs b/src/XTwitterScraper/Models/UserProfile.cs similarity index 94% rename from src/XTwitterScraper/Models/X/Users/UserProfile.cs rename to src/XTwitterScraper/Models/UserProfile.cs index 9b387eb..6d531c9 100644 --- a/src/XTwitterScraper/Models/X/Users/UserProfile.cs +++ b/src/XTwitterScraper/Models/UserProfile.cs @@ -5,7 +5,7 @@ using System.Text.Json.Serialization; using XTwitterScraper.Core; -namespace XTwitterScraper.Models.X.Users; +namespace XTwitterScraper.Models; /// /// X user profile with bio, follower counts, and verification status. diff --git a/src/XTwitterScraper/Models/Webhooks/WebhookCreateParams.cs b/src/XTwitterScraper/Models/Webhooks/WebhookCreateParams.cs index c0f5434..ad603f7 100644 --- a/src/XTwitterScraper/Models/Webhooks/WebhookCreateParams.cs +++ b/src/XTwitterScraper/Models/Webhooks/WebhookCreateParams.cs @@ -141,7 +141,7 @@ public override Uri Url(ClientOptions options) { return new UriBuilder(options.BaseUrl.ToString().TrimEnd('/') + "/webhooks") { - Query = this.QueryString(options, SecurityOptions.All()), + Query = this.QueryString(options), }.Uri; } @@ -156,7 +156,7 @@ public override Uri Url(ClientOptions options) internal override void AddHeadersToRequest(HttpRequestMessage request, ClientOptions options) { - ParamsBase.AddDefaultHeaders(request, options, SecurityOptions.All()); + ParamsBase.AddDefaultHeaders(request, options); foreach (var item in this.RawHeaderData) { ParamsBase.AddHeaderElementToRequest(request, item.Key, item.Value); diff --git a/src/XTwitterScraper/Models/Webhooks/WebhookDeactivateParams.cs b/src/XTwitterScraper/Models/Webhooks/WebhookDeactivateParams.cs index e31bc5d..b1eac0f 100644 --- a/src/XTwitterScraper/Models/Webhooks/WebhookDeactivateParams.cs +++ b/src/XTwitterScraper/Models/Webhooks/WebhookDeactivateParams.cs @@ -101,13 +101,13 @@ public override Uri Url(ClientOptions options) options.BaseUrl.ToString().TrimEnd('/') + string.Format("/webhooks/{0}", this.ID) ) { - Query = this.QueryString(options, SecurityOptions.All()), + Query = this.QueryString(options), }.Uri; } internal override void AddHeadersToRequest(HttpRequestMessage request, ClientOptions options) { - ParamsBase.AddDefaultHeaders(request, options, SecurityOptions.All()); + ParamsBase.AddDefaultHeaders(request, options); foreach (var item in this.RawHeaderData) { ParamsBase.AddHeaderElementToRequest(request, item.Key, item.Value); diff --git a/src/XTwitterScraper/Models/Webhooks/WebhookListDeliveriesParams.cs b/src/XTwitterScraper/Models/Webhooks/WebhookListDeliveriesParams.cs index 9c42b31..e5ec9b7 100644 --- a/src/XTwitterScraper/Models/Webhooks/WebhookListDeliveriesParams.cs +++ b/src/XTwitterScraper/Models/Webhooks/WebhookListDeliveriesParams.cs @@ -102,13 +102,13 @@ public override Uri Url(ClientOptions options) + string.Format("/webhooks/{0}/deliveries", this.ID) ) { - Query = this.QueryString(options, SecurityOptions.All()), + Query = this.QueryString(options), }.Uri; } internal override void AddHeadersToRequest(HttpRequestMessage request, ClientOptions options) { - ParamsBase.AddDefaultHeaders(request, options, SecurityOptions.All()); + ParamsBase.AddDefaultHeaders(request, options); foreach (var item in this.RawHeaderData) { ParamsBase.AddHeaderElementToRequest(request, item.Key, item.Value); diff --git a/src/XTwitterScraper/Models/Webhooks/WebhookListParams.cs b/src/XTwitterScraper/Models/Webhooks/WebhookListParams.cs index a5267e2..bd7a348 100644 --- a/src/XTwitterScraper/Models/Webhooks/WebhookListParams.cs +++ b/src/XTwitterScraper/Models/Webhooks/WebhookListParams.cs @@ -88,13 +88,13 @@ public override Uri Url(ClientOptions options) { return new UriBuilder(options.BaseUrl.ToString().TrimEnd('/') + "/webhooks") { - Query = this.QueryString(options, SecurityOptions.All()), + Query = this.QueryString(options), }.Uri; } internal override void AddHeadersToRequest(HttpRequestMessage request, ClientOptions options) { - ParamsBase.AddDefaultHeaders(request, options, SecurityOptions.All()); + ParamsBase.AddDefaultHeaders(request, options); foreach (var item in this.RawHeaderData) { ParamsBase.AddHeaderElementToRequest(request, item.Key, item.Value); diff --git a/src/XTwitterScraper/Models/Webhooks/WebhookTestParams.cs b/src/XTwitterScraper/Models/Webhooks/WebhookTestParams.cs index ad2a869..defac58 100644 --- a/src/XTwitterScraper/Models/Webhooks/WebhookTestParams.cs +++ b/src/XTwitterScraper/Models/Webhooks/WebhookTestParams.cs @@ -101,13 +101,13 @@ public override Uri Url(ClientOptions options) options.BaseUrl.ToString().TrimEnd('/') + string.Format("/webhooks/{0}/test", this.ID) ) { - Query = this.QueryString(options, SecurityOptions.All()), + Query = this.QueryString(options), }.Uri; } internal override void AddHeadersToRequest(HttpRequestMessage request, ClientOptions options) { - ParamsBase.AddDefaultHeaders(request, options, SecurityOptions.All()); + ParamsBase.AddDefaultHeaders(request, options); foreach (var item in this.RawHeaderData) { ParamsBase.AddHeaderElementToRequest(request, item.Key, item.Value); diff --git a/src/XTwitterScraper/Models/Webhooks/WebhookUpdateParams.cs b/src/XTwitterScraper/Models/Webhooks/WebhookUpdateParams.cs index 3e9e870..37f190b 100644 --- a/src/XTwitterScraper/Models/Webhooks/WebhookUpdateParams.cs +++ b/src/XTwitterScraper/Models/Webhooks/WebhookUpdateParams.cs @@ -181,7 +181,7 @@ public override Uri Url(ClientOptions options) options.BaseUrl.ToString().TrimEnd('/') + string.Format("/webhooks/{0}", this.ID) ) { - Query = this.QueryString(options, SecurityOptions.All()), + Query = this.QueryString(options), }.Uri; } @@ -196,7 +196,7 @@ public override Uri Url(ClientOptions options) internal override void AddHeadersToRequest(HttpRequestMessage request, ClientOptions options) { - ParamsBase.AddDefaultHeaders(request, options, SecurityOptions.All()); + ParamsBase.AddDefaultHeaders(request, options); foreach (var item in this.RawHeaderData) { ParamsBase.AddHeaderElementToRequest(request, item.Key, item.Value); diff --git a/src/XTwitterScraper/Models/X/Accounts/AccountBulkRetryParams.cs b/src/XTwitterScraper/Models/X/Accounts/AccountBulkRetryParams.cs index 3f66283..0c9b28d 100644 --- a/src/XTwitterScraper/Models/X/Accounts/AccountBulkRetryParams.cs +++ b/src/XTwitterScraper/Models/X/Accounts/AccountBulkRetryParams.cs @@ -89,13 +89,13 @@ public override Uri Url(ClientOptions options) { return new UriBuilder(options.BaseUrl.ToString().TrimEnd('/') + "/x/accounts/bulk-retry") { - Query = this.QueryString(options, new() { ApiKey = true }), + Query = this.QueryString(options), }.Uri; } internal override void AddHeadersToRequest(HttpRequestMessage request, ClientOptions options) { - ParamsBase.AddDefaultHeaders(request, options, new() { ApiKey = true }); + ParamsBase.AddDefaultHeaders(request, options); foreach (var item in this.RawHeaderData) { ParamsBase.AddHeaderElementToRequest(request, item.Key, item.Value); diff --git a/src/XTwitterScraper/Models/X/Accounts/AccountCreateParams.cs b/src/XTwitterScraper/Models/X/Accounts/AccountCreateParams.cs index 154d0cf..aa09556 100644 --- a/src/XTwitterScraper/Models/X/Accounts/AccountCreateParams.cs +++ b/src/XTwitterScraper/Models/X/Accounts/AccountCreateParams.cs @@ -187,7 +187,7 @@ public override Uri Url(ClientOptions options) { return new UriBuilder(options.BaseUrl.ToString().TrimEnd('/') + "/x/accounts") { - Query = this.QueryString(options, new() { ApiKey = true }), + Query = this.QueryString(options), }.Uri; } @@ -202,7 +202,7 @@ public override Uri Url(ClientOptions options) internal override void AddHeadersToRequest(HttpRequestMessage request, ClientOptions options) { - ParamsBase.AddDefaultHeaders(request, options, new() { ApiKey = true }); + ParamsBase.AddDefaultHeaders(request, options); foreach (var item in this.RawHeaderData) { ParamsBase.AddHeaderElementToRequest(request, item.Key, item.Value); diff --git a/src/XTwitterScraper/Models/X/Accounts/AccountCreateResponse.cs b/src/XTwitterScraper/Models/X/Accounts/AccountCreateResponse.cs index a2566d6..ec59324 100644 --- a/src/XTwitterScraper/Models/X/Accounts/AccountCreateResponse.cs +++ b/src/XTwitterScraper/Models/X/Accounts/AccountCreateResponse.cs @@ -4,9 +4,18 @@ using System.Text.Json; using System.Text.Json.Serialization; using XTwitterScraper.Core; +using XTwitterScraper.Exceptions; +using System = System; namespace XTwitterScraper.Models.X.Accounts; +/// +/// Sanitized X account summary returned by connect and reauth. Includes an optional +/// `loginCountry` field surfaced only when the declared proxy region had no Driver +/// capacity and the login fell back to a single US consumer device for this one-time +/// action. Future activity continues to use the selected `proxy_country`; the field +/// is omitted on normal logins. +/// [JsonConverter(typeof(JsonModelConverter))] public sealed record class AccountCreateResponse : JsonModel { @@ -20,6 +29,28 @@ public required string ID init { this._rawData.Set("id", value); } } + public required System::DateTimeOffset CreatedAt + { + get + { + this._rawData.Freeze(); + return this._rawData.GetNotNullStruct("createdAt"); + } + init { this._rawData.Set("createdAt", value); } + } + + public required ApiEnum Health + { + get + { + this._rawData.Freeze(); + return this._rawData.GetNotNullClass>( + "health" + ); + } + init { this._rawData.Set("health", value); } + } + public required string Status { get @@ -50,13 +81,39 @@ public required string XUsername init { this._rawData.Set("xUsername", value); } } + /// + /// ISO-3166-1 alpha-2 country code of the Driver consumer device used for this + /// login. Present only when the US fallback was triggered because Driver had + /// no capacity in the declared region. Omitted otherwise. + /// + public string? LoginCountry + { + get + { + this._rawData.Freeze(); + return this._rawData.GetNullableClass("loginCountry"); + } + init + { + if (value == null) + { + return; + } + + this._rawData.Set("loginCountry", value); + } + } + /// public override void Validate() { _ = this.ID; + _ = this.CreatedAt; + this.Health.Validate(); _ = this.Status; _ = this.XUserID; _ = this.XUsername; + _ = this.LoginCountry; } public AccountCreateResponse() { } @@ -96,3 +153,59 @@ public AccountCreateResponse FromRawUnchecked( IReadOnlyDictionary rawData ) => AccountCreateResponse.FromRawUnchecked(rawData); } + +[JsonConverter(typeof(AccountCreateResponseHealthConverter))] +public enum AccountCreateResponseHealth +{ + Healthy, + Locked, + NeedsReauth, + Recovering, + Suspended, + TemporaryIssue, +} + +sealed class AccountCreateResponseHealthConverter : JsonConverter +{ + public override AccountCreateResponseHealth Read( + ref Utf8JsonReader reader, + System::Type typeToConvert, + JsonSerializerOptions options + ) + { + return JsonSerializer.Deserialize(ref reader, options) switch + { + "healthy" => AccountCreateResponseHealth.Healthy, + "locked" => AccountCreateResponseHealth.Locked, + "needsReauth" => AccountCreateResponseHealth.NeedsReauth, + "recovering" => AccountCreateResponseHealth.Recovering, + "suspended" => AccountCreateResponseHealth.Suspended, + "temporaryIssue" => AccountCreateResponseHealth.TemporaryIssue, + _ => (AccountCreateResponseHealth)(-1), + }; + } + + public override void Write( + Utf8JsonWriter writer, + AccountCreateResponseHealth value, + JsonSerializerOptions options + ) + { + JsonSerializer.Serialize( + writer, + value switch + { + AccountCreateResponseHealth.Healthy => "healthy", + AccountCreateResponseHealth.Locked => "locked", + AccountCreateResponseHealth.NeedsReauth => "needsReauth", + AccountCreateResponseHealth.Recovering => "recovering", + AccountCreateResponseHealth.Suspended => "suspended", + AccountCreateResponseHealth.TemporaryIssue => "temporaryIssue", + _ => throw new XTwitterScraperInvalidDataException( + string.Format("Invalid value '{0}' in {1}", value, nameof(value)) + ), + }, + options + ); + } +} diff --git a/src/XTwitterScraper/Models/X/Accounts/AccountDeleteParams.cs b/src/XTwitterScraper/Models/X/Accounts/AccountDeleteParams.cs index 2511b16..609a581 100644 --- a/src/XTwitterScraper/Models/X/Accounts/AccountDeleteParams.cs +++ b/src/XTwitterScraper/Models/X/Accounts/AccountDeleteParams.cs @@ -101,13 +101,13 @@ public override Uri Url(ClientOptions options) options.BaseUrl.ToString().TrimEnd('/') + string.Format("/x/accounts/{0}", this.ID) ) { - Query = this.QueryString(options, new() { ApiKey = true }), + Query = this.QueryString(options), }.Uri; } internal override void AddHeadersToRequest(HttpRequestMessage request, ClientOptions options) { - ParamsBase.AddDefaultHeaders(request, options, new() { ApiKey = true }); + ParamsBase.AddDefaultHeaders(request, options); foreach (var item in this.RawHeaderData) { ParamsBase.AddHeaderElementToRequest(request, item.Key, item.Value); diff --git a/src/XTwitterScraper/Models/X/Accounts/AccountListParams.cs b/src/XTwitterScraper/Models/X/Accounts/AccountListParams.cs index 168d148..5740935 100644 --- a/src/XTwitterScraper/Models/X/Accounts/AccountListParams.cs +++ b/src/XTwitterScraper/Models/X/Accounts/AccountListParams.cs @@ -88,13 +88,13 @@ public override Uri Url(ClientOptions options) { return new UriBuilder(options.BaseUrl.ToString().TrimEnd('/') + "/x/accounts") { - Query = this.QueryString(options, new() { ApiKey = true }), + Query = this.QueryString(options), }.Uri; } internal override void AddHeadersToRequest(HttpRequestMessage request, ClientOptions options) { - ParamsBase.AddDefaultHeaders(request, options, new() { ApiKey = true }); + ParamsBase.AddDefaultHeaders(request, options); foreach (var item in this.RawHeaderData) { ParamsBase.AddHeaderElementToRequest(request, item.Key, item.Value); diff --git a/src/XTwitterScraper/Models/X/Accounts/AccountReauthParams.cs b/src/XTwitterScraper/Models/X/Accounts/AccountReauthParams.cs index a6d5300..1344361 100644 --- a/src/XTwitterScraper/Models/X/Accounts/AccountReauthParams.cs +++ b/src/XTwitterScraper/Models/X/Accounts/AccountReauthParams.cs @@ -39,6 +39,48 @@ public required string Password init { this._rawBodyData.Set("password", value); } } + /// + /// Email for the X account (updates stored email) + /// + public string? Email + { + get + { + this._rawBodyData.Freeze(); + return this._rawBodyData.GetNullableClass("email"); + } + init + { + if (value == null) + { + return; + } + + this._rawBodyData.Set("email", value); + } + } + + /// + /// Two-letter country code for login proxy region + /// + public string? ProxyCountry + { + get + { + this._rawBodyData.Freeze(); + return this._rawBodyData.GetNullableClass("proxy_country"); + } + init + { + if (value == null) + { + return; + } + + this._rawBodyData.Set("proxy_country", value); + } + } + /// /// TOTP secret for 2FA re-authentication /// @@ -153,7 +195,7 @@ public override Uri Url(ClientOptions options) + string.Format("/x/accounts/{0}/reauth", this.ID) ) { - Query = this.QueryString(options, new() { ApiKey = true }), + Query = this.QueryString(options), }.Uri; } @@ -168,7 +210,7 @@ public override Uri Url(ClientOptions options) internal override void AddHeadersToRequest(HttpRequestMessage request, ClientOptions options) { - ParamsBase.AddDefaultHeaders(request, options, new() { ApiKey = true }); + ParamsBase.AddDefaultHeaders(request, options); foreach (var item in this.RawHeaderData) { ParamsBase.AddHeaderElementToRequest(request, item.Key, item.Value); diff --git a/src/XTwitterScraper/Models/X/Accounts/AccountReauthResponse.cs b/src/XTwitterScraper/Models/X/Accounts/AccountReauthResponse.cs index ce75d7c..877db6d 100644 --- a/src/XTwitterScraper/Models/X/Accounts/AccountReauthResponse.cs +++ b/src/XTwitterScraper/Models/X/Accounts/AccountReauthResponse.cs @@ -4,9 +4,18 @@ using System.Text.Json; using System.Text.Json.Serialization; using XTwitterScraper.Core; +using XTwitterScraper.Exceptions; +using System = System; namespace XTwitterScraper.Models.X.Accounts; +/// +/// Sanitized X account summary returned by connect and reauth. Includes an optional +/// `loginCountry` field surfaced only when the declared proxy region had no Driver +/// capacity and the login fell back to a single US consumer device for this one-time +/// action. Future activity continues to use the selected `proxy_country`; the field +/// is omitted on normal logins. +/// [JsonConverter(typeof(JsonModelConverter))] public sealed record class AccountReauthResponse : JsonModel { @@ -20,6 +29,28 @@ public required string ID init { this._rawData.Set("id", value); } } + public required System::DateTimeOffset CreatedAt + { + get + { + this._rawData.Freeze(); + return this._rawData.GetNotNullStruct("createdAt"); + } + init { this._rawData.Set("createdAt", value); } + } + + public required ApiEnum Health + { + get + { + this._rawData.Freeze(); + return this._rawData.GetNotNullClass>( + "health" + ); + } + init { this._rawData.Set("health", value); } + } + public required string Status { get @@ -30,6 +61,16 @@ public required string Status init { this._rawData.Set("status", value); } } + public required string XUserID + { + get + { + this._rawData.Freeze(); + return this._rawData.GetNotNullClass("xUserId"); + } + init { this._rawData.Set("xUserId", value); } + } + public required string XUsername { get @@ -40,12 +81,39 @@ public required string XUsername init { this._rawData.Set("xUsername", value); } } + /// + /// ISO-3166-1 alpha-2 country code of the Driver consumer device used for this + /// login. Present only when the US fallback was triggered because Driver had + /// no capacity in the declared region. Omitted otherwise. + /// + public string? LoginCountry + { + get + { + this._rawData.Freeze(); + return this._rawData.GetNullableClass("loginCountry"); + } + init + { + if (value == null) + { + return; + } + + this._rawData.Set("loginCountry", value); + } + } + /// public override void Validate() { _ = this.ID; + _ = this.CreatedAt; + this.Health.Validate(); _ = this.Status; + _ = this.XUserID; _ = this.XUsername; + _ = this.LoginCountry; } public AccountReauthResponse() { } @@ -85,3 +153,59 @@ public AccountReauthResponse FromRawUnchecked( IReadOnlyDictionary rawData ) => AccountReauthResponse.FromRawUnchecked(rawData); } + +[JsonConverter(typeof(AccountReauthResponseHealthConverter))] +public enum AccountReauthResponseHealth +{ + Healthy, + Locked, + NeedsReauth, + Recovering, + Suspended, + TemporaryIssue, +} + +sealed class AccountReauthResponseHealthConverter : JsonConverter +{ + public override AccountReauthResponseHealth Read( + ref Utf8JsonReader reader, + System::Type typeToConvert, + JsonSerializerOptions options + ) + { + return JsonSerializer.Deserialize(ref reader, options) switch + { + "healthy" => AccountReauthResponseHealth.Healthy, + "locked" => AccountReauthResponseHealth.Locked, + "needsReauth" => AccountReauthResponseHealth.NeedsReauth, + "recovering" => AccountReauthResponseHealth.Recovering, + "suspended" => AccountReauthResponseHealth.Suspended, + "temporaryIssue" => AccountReauthResponseHealth.TemporaryIssue, + _ => (AccountReauthResponseHealth)(-1), + }; + } + + public override void Write( + Utf8JsonWriter writer, + AccountReauthResponseHealth value, + JsonSerializerOptions options + ) + { + JsonSerializer.Serialize( + writer, + value switch + { + AccountReauthResponseHealth.Healthy => "healthy", + AccountReauthResponseHealth.Locked => "locked", + AccountReauthResponseHealth.NeedsReauth => "needsReauth", + AccountReauthResponseHealth.Recovering => "recovering", + AccountReauthResponseHealth.Suspended => "suspended", + AccountReauthResponseHealth.TemporaryIssue => "temporaryIssue", + _ => throw new XTwitterScraperInvalidDataException( + string.Format("Invalid value '{0}' in {1}", value, nameof(value)) + ), + }, + options + ); + } +} diff --git a/src/XTwitterScraper/Models/X/Accounts/AccountRetrieveParams.cs b/src/XTwitterScraper/Models/X/Accounts/AccountRetrieveParams.cs index f4f4239..5872499 100644 --- a/src/XTwitterScraper/Models/X/Accounts/AccountRetrieveParams.cs +++ b/src/XTwitterScraper/Models/X/Accounts/AccountRetrieveParams.cs @@ -101,13 +101,13 @@ public override Uri Url(ClientOptions options) options.BaseUrl.ToString().TrimEnd('/') + string.Format("/x/accounts/{0}", this.ID) ) { - Query = this.QueryString(options, new() { ApiKey = true }), + Query = this.QueryString(options), }.Uri; } internal override void AddHeadersToRequest(HttpRequestMessage request, ClientOptions options) { - ParamsBase.AddDefaultHeaders(request, options, new() { ApiKey = true }); + ParamsBase.AddDefaultHeaders(request, options); foreach (var item in this.RawHeaderData) { ParamsBase.AddHeaderElementToRequest(request, item.Key, item.Value); diff --git a/src/XTwitterScraper/Models/X/Accounts/XAccount.cs b/src/XTwitterScraper/Models/X/Accounts/XAccount.cs index a049376..efd3b2a 100644 --- a/src/XTwitterScraper/Models/X/Accounts/XAccount.cs +++ b/src/XTwitterScraper/Models/X/Accounts/XAccount.cs @@ -1,10 +1,11 @@ -using System; using System.Collections.Frozen; using System.Collections.Generic; using System.Diagnostics.CodeAnalysis; using System.Text.Json; using System.Text.Json.Serialization; using XTwitterScraper.Core; +using XTwitterScraper.Exceptions; +using System = System; namespace XTwitterScraper.Models.X.Accounts; @@ -24,16 +25,33 @@ public required string ID init { this._rawData.Set("id", value); } } - public required DateTimeOffset CreatedAt + public required System::DateTimeOffset CreatedAt { get { this._rawData.Freeze(); - return this._rawData.GetNotNullStruct("createdAt"); + return this._rawData.GetNotNullStruct("createdAt"); } init { this._rawData.Set("createdAt", value); } } + /// + /// Derived login/cookie health. `healthy` = cookies valid. `needsReauth` = user + /// must submit fresh credentials. `locked` = X locked the account; unlock on + /// x.com first. `suspended` = X banned the account. `recovering` = past cooldown, + /// will auto-retry on next use. `temporaryIssue` = transient backend problem; + /// retry shortly. + /// + public required ApiEnum Health + { + get + { + this._rawData.Freeze(); + return this._rawData.GetNotNullClass>("health"); + } + init { this._rawData.Set("health", value); } + } + public required string Status { get @@ -69,6 +87,7 @@ public override void Validate() { _ = this.ID; _ = this.CreatedAt; + this.Health.Validate(); _ = this.Status; _ = this.XUserID; _ = this.XUsername; @@ -108,3 +127,61 @@ class XAccountFromRaw : IFromRawJson public XAccount FromRawUnchecked(IReadOnlyDictionary rawData) => XAccount.FromRawUnchecked(rawData); } + +/// +/// Derived login/cookie health. `healthy` = cookies valid. `needsReauth` = user +/// must submit fresh credentials. `locked` = X locked the account; unlock on x.com +/// first. `suspended` = X banned the account. `recovering` = past cooldown, will +/// auto-retry on next use. `temporaryIssue` = transient backend problem; retry shortly. +/// +[JsonConverter(typeof(HealthConverter))] +public enum Health +{ + Healthy, + Locked, + NeedsReauth, + Recovering, + Suspended, + TemporaryIssue, +} + +sealed class HealthConverter : JsonConverter +{ + public override Health Read( + ref Utf8JsonReader reader, + System::Type typeToConvert, + JsonSerializerOptions options + ) + { + return JsonSerializer.Deserialize(ref reader, options) switch + { + "healthy" => Health.Healthy, + "locked" => Health.Locked, + "needsReauth" => Health.NeedsReauth, + "recovering" => Health.Recovering, + "suspended" => Health.Suspended, + "temporaryIssue" => Health.TemporaryIssue, + _ => (Health)(-1), + }; + } + + public override void Write(Utf8JsonWriter writer, Health value, JsonSerializerOptions options) + { + JsonSerializer.Serialize( + writer, + value switch + { + Health.Healthy => "healthy", + Health.Locked => "locked", + Health.NeedsReauth => "needsReauth", + Health.Recovering => "recovering", + Health.Suspended => "suspended", + Health.TemporaryIssue => "temporaryIssue", + _ => throw new XTwitterScraperInvalidDataException( + string.Format("Invalid value '{0}' in {1}", value, nameof(value)) + ), + }, + options + ); + } +} diff --git a/src/XTwitterScraper/Models/X/Accounts/XAccountDetail.cs b/src/XTwitterScraper/Models/X/Accounts/XAccountDetail.cs index 226c70a..a86250d 100644 --- a/src/XTwitterScraper/Models/X/Accounts/XAccountDetail.cs +++ b/src/XTwitterScraper/Models/X/Accounts/XAccountDetail.cs @@ -1,10 +1,11 @@ -using System; using System.Collections.Frozen; using System.Collections.Generic; using System.Diagnostics.CodeAnalysis; using System.Text.Json; using System.Text.Json.Serialization; using XTwitterScraper.Core; +using XTwitterScraper.Exceptions; +using System = System; namespace XTwitterScraper.Models.X.Accounts; @@ -24,16 +25,26 @@ public required string ID init { this._rawData.Set("id", value); } } - public required DateTimeOffset CreatedAt + public required System::DateTimeOffset CreatedAt { get { this._rawData.Freeze(); - return this._rawData.GetNotNullStruct("createdAt"); + return this._rawData.GetNotNullStruct("createdAt"); } init { this._rawData.Set("createdAt", value); } } + public required ApiEnum Health + { + get + { + this._rawData.Freeze(); + return this._rawData.GetNotNullClass>("health"); + } + init { this._rawData.Set("health", value); } + } + public required string Status { get @@ -64,12 +75,12 @@ public required string XUsername init { this._rawData.Set("xUsername", value); } } - public DateTimeOffset? CookiesObtainedAt + public System::DateTimeOffset? CookiesObtainedAt { get { this._rawData.Freeze(); - return this._rawData.GetNullableStruct("cookiesObtainedAt"); + return this._rawData.GetNullableStruct("cookiesObtainedAt"); } init { @@ -100,12 +111,12 @@ public string? ProxyCountry } } - public DateTimeOffset? UpdatedAt + public System::DateTimeOffset? UpdatedAt { get { this._rawData.Freeze(); - return this._rawData.GetNullableStruct("updatedAt"); + return this._rawData.GetNullableStruct("updatedAt"); } init { @@ -123,6 +134,7 @@ public override void Validate() { _ = this.ID; _ = this.CreatedAt; + this.Health.Validate(); _ = this.Status; _ = this.XUserID; _ = this.XUsername; @@ -165,3 +177,59 @@ class XAccountDetailFromRaw : IFromRawJson public XAccountDetail FromRawUnchecked(IReadOnlyDictionary rawData) => XAccountDetail.FromRawUnchecked(rawData); } + +[JsonConverter(typeof(XAccountDetailHealthConverter))] +public enum XAccountDetailHealth +{ + Healthy, + Locked, + NeedsReauth, + Recovering, + Suspended, + TemporaryIssue, +} + +sealed class XAccountDetailHealthConverter : JsonConverter +{ + public override XAccountDetailHealth Read( + ref Utf8JsonReader reader, + System::Type typeToConvert, + JsonSerializerOptions options + ) + { + return JsonSerializer.Deserialize(ref reader, options) switch + { + "healthy" => XAccountDetailHealth.Healthy, + "locked" => XAccountDetailHealth.Locked, + "needsReauth" => XAccountDetailHealth.NeedsReauth, + "recovering" => XAccountDetailHealth.Recovering, + "suspended" => XAccountDetailHealth.Suspended, + "temporaryIssue" => XAccountDetailHealth.TemporaryIssue, + _ => (XAccountDetailHealth)(-1), + }; + } + + public override void Write( + Utf8JsonWriter writer, + XAccountDetailHealth value, + JsonSerializerOptions options + ) + { + JsonSerializer.Serialize( + writer, + value switch + { + XAccountDetailHealth.Healthy => "healthy", + XAccountDetailHealth.Locked => "locked", + XAccountDetailHealth.NeedsReauth => "needsReauth", + XAccountDetailHealth.Recovering => "recovering", + XAccountDetailHealth.Suspended => "suspended", + XAccountDetailHealth.TemporaryIssue => "temporaryIssue", + _ => throw new XTwitterScraperInvalidDataException( + string.Format("Invalid value '{0}' in {1}", value, nameof(value)) + ), + }, + options + ); + } +} diff --git a/src/XTwitterScraper/Models/X/Bookmarks/BookmarkListParams.cs b/src/XTwitterScraper/Models/X/Bookmarks/BookmarkListParams.cs index f8b8dd6..31dffe8 100644 --- a/src/XTwitterScraper/Models/X/Bookmarks/BookmarkListParams.cs +++ b/src/XTwitterScraper/Models/X/Bookmarks/BookmarkListParams.cs @@ -130,13 +130,13 @@ public override Uri Url(ClientOptions options) { return new UriBuilder(options.BaseUrl.ToString().TrimEnd('/') + "/x/bookmarks") { - Query = this.QueryString(options, SecurityOptions.All()), + Query = this.QueryString(options), }.Uri; } internal override void AddHeadersToRequest(HttpRequestMessage request, ClientOptions options) { - ParamsBase.AddDefaultHeaders(request, options, SecurityOptions.All()); + ParamsBase.AddDefaultHeaders(request, options); foreach (var item in this.RawHeaderData) { ParamsBase.AddHeaderElementToRequest(request, item.Key, item.Value); diff --git a/src/XTwitterScraper/Models/X/Bookmarks/BookmarkRetrieveFoldersParams.cs b/src/XTwitterScraper/Models/X/Bookmarks/BookmarkRetrieveFoldersParams.cs index 6b97673..a375363 100644 --- a/src/XTwitterScraper/Models/X/Bookmarks/BookmarkRetrieveFoldersParams.cs +++ b/src/XTwitterScraper/Models/X/Bookmarks/BookmarkRetrieveFoldersParams.cs @@ -90,13 +90,13 @@ public override Uri Url(ClientOptions options) { return new UriBuilder(options.BaseUrl.ToString().TrimEnd('/') + "/x/bookmarks/folders") { - Query = this.QueryString(options, SecurityOptions.All()), + Query = this.QueryString(options), }.Uri; } internal override void AddHeadersToRequest(HttpRequestMessage request, ClientOptions options) { - ParamsBase.AddDefaultHeaders(request, options, SecurityOptions.All()); + ParamsBase.AddDefaultHeaders(request, options); foreach (var item in this.RawHeaderData) { ParamsBase.AddHeaderElementToRequest(request, item.Key, item.Value); diff --git a/src/XTwitterScraper/Models/X/Communities/CommunityCreateParams.cs b/src/XTwitterScraper/Models/X/Communities/CommunityCreateParams.cs index 4bc9905..ea6357b 100644 --- a/src/XTwitterScraper/Models/X/Communities/CommunityCreateParams.cs +++ b/src/XTwitterScraper/Models/X/Communities/CommunityCreateParams.cs @@ -153,7 +153,7 @@ public override Uri Url(ClientOptions options) { return new UriBuilder(options.BaseUrl.ToString().TrimEnd('/') + "/x/communities") { - Query = this.QueryString(options, SecurityOptions.All()), + Query = this.QueryString(options), }.Uri; } @@ -168,7 +168,7 @@ public override Uri Url(ClientOptions options) internal override void AddHeadersToRequest(HttpRequestMessage request, ClientOptions options) { - ParamsBase.AddDefaultHeaders(request, options, SecurityOptions.All()); + ParamsBase.AddDefaultHeaders(request, options); foreach (var item in this.RawHeaderData) { ParamsBase.AddHeaderElementToRequest(request, item.Key, item.Value); diff --git a/src/XTwitterScraper/Models/X/Communities/CommunityDeleteParams.cs b/src/XTwitterScraper/Models/X/Communities/CommunityDeleteParams.cs index 0021b7f..922515a 100644 --- a/src/XTwitterScraper/Models/X/Communities/CommunityDeleteParams.cs +++ b/src/XTwitterScraper/Models/X/Communities/CommunityDeleteParams.cs @@ -144,7 +144,7 @@ public override Uri Url(ClientOptions options) options.BaseUrl.ToString().TrimEnd('/') + string.Format("/x/communities/{0}", this.ID) ) { - Query = this.QueryString(options, SecurityOptions.All()), + Query = this.QueryString(options), }.Uri; } @@ -159,7 +159,7 @@ public override Uri Url(ClientOptions options) internal override void AddHeadersToRequest(HttpRequestMessage request, ClientOptions options) { - ParamsBase.AddDefaultHeaders(request, options, SecurityOptions.All()); + ParamsBase.AddDefaultHeaders(request, options); foreach (var item in this.RawHeaderData) { ParamsBase.AddHeaderElementToRequest(request, item.Key, item.Value); diff --git a/src/XTwitterScraper/Models/X/Communities/CommunityRetrieveInfoParams.cs b/src/XTwitterScraper/Models/X/Communities/CommunityRetrieveInfoParams.cs index a12be46..5cb1786 100644 --- a/src/XTwitterScraper/Models/X/Communities/CommunityRetrieveInfoParams.cs +++ b/src/XTwitterScraper/Models/X/Communities/CommunityRetrieveInfoParams.cs @@ -9,7 +9,7 @@ namespace XTwitterScraper.Models.X.Communities; /// -/// Get community details +/// Get community name, description & member count /// /// NOTE: Do not inherit from this type outside the SDK unless you're okay with /// breaking changes in non-major versions. We may add new methods in the future that @@ -102,13 +102,13 @@ public override Uri Url(ClientOptions options) + string.Format("/x/communities/{0}/info", this.ID) ) { - Query = this.QueryString(options, SecurityOptions.All()), + Query = this.QueryString(options), }.Uri; } internal override void AddHeadersToRequest(HttpRequestMessage request, ClientOptions options) { - ParamsBase.AddDefaultHeaders(request, options, SecurityOptions.All()); + ParamsBase.AddDefaultHeaders(request, options); foreach (var item in this.RawHeaderData) { ParamsBase.AddHeaderElementToRequest(request, item.Key, item.Value); diff --git a/src/XTwitterScraper/Models/X/Communities/CommunityRetrieveMembersParams.cs b/src/XTwitterScraper/Models/X/Communities/CommunityRetrieveMembersParams.cs index 9634d07..acebfb6 100644 --- a/src/XTwitterScraper/Models/X/Communities/CommunityRetrieveMembersParams.cs +++ b/src/XTwitterScraper/Models/X/Communities/CommunityRetrieveMembersParams.cs @@ -9,7 +9,7 @@ namespace XTwitterScraper.Models.X.Communities; /// -/// Get community members +/// List members of a community /// /// NOTE: Do not inherit from this type outside the SDK unless you're okay with /// breaking changes in non-major versions. We may add new methods in the future that @@ -125,13 +125,13 @@ public override Uri Url(ClientOptions options) + string.Format("/x/communities/{0}/members", this.ID) ) { - Query = this.QueryString(options, SecurityOptions.All()), + Query = this.QueryString(options), }.Uri; } internal override void AddHeadersToRequest(HttpRequestMessage request, ClientOptions options) { - ParamsBase.AddDefaultHeaders(request, options, SecurityOptions.All()); + ParamsBase.AddDefaultHeaders(request, options); foreach (var item in this.RawHeaderData) { ParamsBase.AddHeaderElementToRequest(request, item.Key, item.Value); diff --git a/src/XTwitterScraper/Models/X/Communities/CommunityRetrieveModeratorsParams.cs b/src/XTwitterScraper/Models/X/Communities/CommunityRetrieveModeratorsParams.cs index a19b852..43b622c 100644 --- a/src/XTwitterScraper/Models/X/Communities/CommunityRetrieveModeratorsParams.cs +++ b/src/XTwitterScraper/Models/X/Communities/CommunityRetrieveModeratorsParams.cs @@ -9,7 +9,7 @@ namespace XTwitterScraper.Models.X.Communities; /// -/// Get community moderators +/// List moderators of a community /// /// NOTE: Do not inherit from this type outside the SDK unless you're okay with /// breaking changes in non-major versions. We may add new methods in the future that @@ -125,13 +125,13 @@ public override Uri Url(ClientOptions options) + string.Format("/x/communities/{0}/moderators", this.ID) ) { - Query = this.QueryString(options, SecurityOptions.All()), + Query = this.QueryString(options), }.Uri; } internal override void AddHeadersToRequest(HttpRequestMessage request, ClientOptions options) { - ParamsBase.AddDefaultHeaders(request, options, SecurityOptions.All()); + ParamsBase.AddDefaultHeaders(request, options); foreach (var item in this.RawHeaderData) { ParamsBase.AddHeaderElementToRequest(request, item.Key, item.Value); diff --git a/src/XTwitterScraper/Models/X/Communities/CommunityRetrieveSearchParams.cs b/src/XTwitterScraper/Models/X/Communities/CommunityRetrieveSearchParams.cs index e39738c..013e0f8 100644 --- a/src/XTwitterScraper/Models/X/Communities/CommunityRetrieveSearchParams.cs +++ b/src/XTwitterScraper/Models/X/Communities/CommunityRetrieveSearchParams.cs @@ -9,7 +9,7 @@ namespace XTwitterScraper.Models.X.Communities; /// -/// Search tweets across communities +/// Search for communities by keyword /// /// NOTE: Do not inherit from this type outside the SDK unless you're okay with /// breaking changes in non-major versions. We may add new methods in the future that @@ -145,13 +145,13 @@ public override Uri Url(ClientOptions options) { return new UriBuilder(options.BaseUrl.ToString().TrimEnd('/') + "/x/communities/search") { - Query = this.QueryString(options, SecurityOptions.All()), + Query = this.QueryString(options), }.Uri; } internal override void AddHeadersToRequest(HttpRequestMessage request, ClientOptions options) { - ParamsBase.AddDefaultHeaders(request, options, SecurityOptions.All()); + ParamsBase.AddDefaultHeaders(request, options); foreach (var item in this.RawHeaderData) { ParamsBase.AddHeaderElementToRequest(request, item.Key, item.Value); diff --git a/src/XTwitterScraper/Models/X/Communities/Join/JoinCreateParams.cs b/src/XTwitterScraper/Models/X/Communities/Join/JoinCreateParams.cs index 2c4f3a7..5d0b58b 100644 --- a/src/XTwitterScraper/Models/X/Communities/Join/JoinCreateParams.cs +++ b/src/XTwitterScraper/Models/X/Communities/Join/JoinCreateParams.cs @@ -132,7 +132,7 @@ public override Uri Url(ClientOptions options) + string.Format("/x/communities/{0}/join", this.ID) ) { - Query = this.QueryString(options, SecurityOptions.All()), + Query = this.QueryString(options), }.Uri; } @@ -147,7 +147,7 @@ public override Uri Url(ClientOptions options) internal override void AddHeadersToRequest(HttpRequestMessage request, ClientOptions options) { - ParamsBase.AddDefaultHeaders(request, options, SecurityOptions.All()); + ParamsBase.AddDefaultHeaders(request, options); foreach (var item in this.RawHeaderData) { ParamsBase.AddHeaderElementToRequest(request, item.Key, item.Value); diff --git a/src/XTwitterScraper/Models/X/Communities/Join/JoinDeleteAllParams.cs b/src/XTwitterScraper/Models/X/Communities/Join/JoinDeleteAllParams.cs index ff2d3ca..f2f688c 100644 --- a/src/XTwitterScraper/Models/X/Communities/Join/JoinDeleteAllParams.cs +++ b/src/XTwitterScraper/Models/X/Communities/Join/JoinDeleteAllParams.cs @@ -132,7 +132,7 @@ public override Uri Url(ClientOptions options) + string.Format("/x/communities/{0}/join", this.ID) ) { - Query = this.QueryString(options, SecurityOptions.All()), + Query = this.QueryString(options), }.Uri; } @@ -147,7 +147,7 @@ public override Uri Url(ClientOptions options) internal override void AddHeadersToRequest(HttpRequestMessage request, ClientOptions options) { - ParamsBase.AddDefaultHeaders(request, options, SecurityOptions.All()); + ParamsBase.AddDefaultHeaders(request, options); foreach (var item in this.RawHeaderData) { ParamsBase.AddHeaderElementToRequest(request, item.Key, item.Value); diff --git a/src/XTwitterScraper/Models/X/Communities/Tweets/TweetListByCommunityParams.cs b/src/XTwitterScraper/Models/X/Communities/Tweets/TweetListByCommunityParams.cs index 8412a35..64f6afb 100644 --- a/src/XTwitterScraper/Models/X/Communities/Tweets/TweetListByCommunityParams.cs +++ b/src/XTwitterScraper/Models/X/Communities/Tweets/TweetListByCommunityParams.cs @@ -9,7 +9,7 @@ namespace XTwitterScraper.Models.X.Communities.Tweets; /// -/// Get community tweets +/// List tweets posted in a community /// /// NOTE: Do not inherit from this type outside the SDK unless you're okay with /// breaking changes in non-major versions. We may add new methods in the future that @@ -123,13 +123,13 @@ public override Uri Url(ClientOptions options) + string.Format("/x/communities/{0}/tweets", this.ID) ) { - Query = this.QueryString(options, SecurityOptions.All()), + Query = this.QueryString(options), }.Uri; } internal override void AddHeadersToRequest(HttpRequestMessage request, ClientOptions options) { - ParamsBase.AddDefaultHeaders(request, options, SecurityOptions.All()); + ParamsBase.AddDefaultHeaders(request, options); foreach (var item in this.RawHeaderData) { ParamsBase.AddHeaderElementToRequest(request, item.Key, item.Value); diff --git a/src/XTwitterScraper/Models/X/Communities/Tweets/TweetListParams.cs b/src/XTwitterScraper/Models/X/Communities/Tweets/TweetListParams.cs index e2f6695..3dc3c2e 100644 --- a/src/XTwitterScraper/Models/X/Communities/Tweets/TweetListParams.cs +++ b/src/XTwitterScraper/Models/X/Communities/Tweets/TweetListParams.cs @@ -9,7 +9,7 @@ namespace XTwitterScraper.Models.X.Communities.Tweets; /// -/// Search tweets across all communities +/// List tweets across all communities /// /// NOTE: Do not inherit from this type outside the SDK unless you're okay with /// breaking changes in non-major versions. We may add new methods in the future that @@ -143,13 +143,13 @@ public override Uri Url(ClientOptions options) { return new UriBuilder(options.BaseUrl.ToString().TrimEnd('/') + "/x/communities/tweets") { - Query = this.QueryString(options, SecurityOptions.All()), + Query = this.QueryString(options), }.Uri; } internal override void AddHeadersToRequest(HttpRequestMessage request, ClientOptions options) { - ParamsBase.AddDefaultHeaders(request, options, SecurityOptions.All()); + ParamsBase.AddDefaultHeaders(request, options); foreach (var item in this.RawHeaderData) { ParamsBase.AddHeaderElementToRequest(request, item.Key, item.Value); diff --git a/src/XTwitterScraper/Models/X/Dm/DmRetrieveHistoryParams.cs b/src/XTwitterScraper/Models/X/Dm/DmRetrieveHistoryParams.cs index 3ff7c6a..a17fdce 100644 --- a/src/XTwitterScraper/Models/X/Dm/DmRetrieveHistoryParams.cs +++ b/src/XTwitterScraper/Models/X/Dm/DmRetrieveHistoryParams.cs @@ -144,13 +144,13 @@ public override Uri Url(ClientOptions options) + string.Format("/x/dm/{0}/history", this.UserID) ) { - Query = this.QueryString(options, SecurityOptions.All()), + Query = this.QueryString(options), }.Uri; } internal override void AddHeadersToRequest(HttpRequestMessage request, ClientOptions options) { - ParamsBase.AddDefaultHeaders(request, options, SecurityOptions.All()); + ParamsBase.AddDefaultHeaders(request, options); foreach (var item in this.RawHeaderData) { ParamsBase.AddHeaderElementToRequest(request, item.Key, item.Value); diff --git a/src/XTwitterScraper/Models/X/Dm/DmSendParams.cs b/src/XTwitterScraper/Models/X/Dm/DmSendParams.cs index 9776e89..93dd813 100644 --- a/src/XTwitterScraper/Models/X/Dm/DmSendParams.cs +++ b/src/XTwitterScraper/Models/X/Dm/DmSendParams.cs @@ -181,7 +181,7 @@ public override Uri Url(ClientOptions options) options.BaseUrl.ToString().TrimEnd('/') + string.Format("/x/dm/{0}", this.UserID) ) { - Query = this.QueryString(options, SecurityOptions.All()), + Query = this.QueryString(options), }.Uri; } @@ -196,7 +196,7 @@ public override Uri Url(ClientOptions options) internal override void AddHeadersToRequest(HttpRequestMessage request, ClientOptions options) { - ParamsBase.AddDefaultHeaders(request, options, SecurityOptions.All()); + ParamsBase.AddDefaultHeaders(request, options); foreach (var item in this.RawHeaderData) { ParamsBase.AddHeaderElementToRequest(request, item.Key, item.Value); diff --git a/src/XTwitterScraper/Models/X/Followers/FollowerCheckParams.cs b/src/XTwitterScraper/Models/X/Followers/FollowerCheckParams.cs index 0b7bae3..339f4be 100644 --- a/src/XTwitterScraper/Models/X/Followers/FollowerCheckParams.cs +++ b/src/XTwitterScraper/Models/X/Followers/FollowerCheckParams.cs @@ -9,7 +9,7 @@ namespace XTwitterScraper.Models.X.Followers; /// -/// Check follow relationship +/// Check if one user follows another /// /// NOTE: Do not inherit from this type outside the SDK unless you're okay with /// breaking changes in non-major versions. We may add new methods in the future that @@ -114,13 +114,13 @@ public override Uri Url(ClientOptions options) { return new UriBuilder(options.BaseUrl.ToString().TrimEnd('/') + "/x/followers/check") { - Query = this.QueryString(options, SecurityOptions.All()), + Query = this.QueryString(options), }.Uri; } internal override void AddHeadersToRequest(HttpRequestMessage request, ClientOptions options) { - ParamsBase.AddDefaultHeaders(request, options, SecurityOptions.All()); + ParamsBase.AddDefaultHeaders(request, options); foreach (var item in this.RawHeaderData) { ParamsBase.AddHeaderElementToRequest(request, item.Key, item.Value); diff --git a/src/XTwitterScraper/Models/X/Lists/ListRetrieveFollowersParams.cs b/src/XTwitterScraper/Models/X/Lists/ListRetrieveFollowersParams.cs index a7945b7..9e619f3 100644 --- a/src/XTwitterScraper/Models/X/Lists/ListRetrieveFollowersParams.cs +++ b/src/XTwitterScraper/Models/X/Lists/ListRetrieveFollowersParams.cs @@ -9,7 +9,7 @@ namespace XTwitterScraper.Models.X.Lists; /// -/// Get list followers +/// List followers of an X List /// /// NOTE: Do not inherit from this type outside the SDK unless you're okay with /// breaking changes in non-major versions. We may add new methods in the future that @@ -123,13 +123,13 @@ public override Uri Url(ClientOptions options) + string.Format("/x/lists/{0}/followers", this.ID) ) { - Query = this.QueryString(options, SecurityOptions.All()), + Query = this.QueryString(options), }.Uri; } internal override void AddHeadersToRequest(HttpRequestMessage request, ClientOptions options) { - ParamsBase.AddDefaultHeaders(request, options, SecurityOptions.All()); + ParamsBase.AddDefaultHeaders(request, options); foreach (var item in this.RawHeaderData) { ParamsBase.AddHeaderElementToRequest(request, item.Key, item.Value); diff --git a/src/XTwitterScraper/Models/X/Lists/ListRetrieveMembersParams.cs b/src/XTwitterScraper/Models/X/Lists/ListRetrieveMembersParams.cs index 9833d90..21c5b73 100644 --- a/src/XTwitterScraper/Models/X/Lists/ListRetrieveMembersParams.cs +++ b/src/XTwitterScraper/Models/X/Lists/ListRetrieveMembersParams.cs @@ -9,7 +9,7 @@ namespace XTwitterScraper.Models.X.Lists; /// -/// Get list members +/// List members of an X List /// /// NOTE: Do not inherit from this type outside the SDK unless you're okay with /// breaking changes in non-major versions. We may add new methods in the future that @@ -122,13 +122,13 @@ public override Uri Url(ClientOptions options) options.BaseUrl.ToString().TrimEnd('/') + string.Format("/x/lists/{0}/members", this.ID) ) { - Query = this.QueryString(options, SecurityOptions.All()), + Query = this.QueryString(options), }.Uri; } internal override void AddHeadersToRequest(HttpRequestMessage request, ClientOptions options) { - ParamsBase.AddDefaultHeaders(request, options, SecurityOptions.All()); + ParamsBase.AddDefaultHeaders(request, options); foreach (var item in this.RawHeaderData) { ParamsBase.AddHeaderElementToRequest(request, item.Key, item.Value); diff --git a/src/XTwitterScraper/Models/X/Lists/ListRetrieveTweetsParams.cs b/src/XTwitterScraper/Models/X/Lists/ListRetrieveTweetsParams.cs index 3dd01c8..0495f38 100644 --- a/src/XTwitterScraper/Models/X/Lists/ListRetrieveTweetsParams.cs +++ b/src/XTwitterScraper/Models/X/Lists/ListRetrieveTweetsParams.cs @@ -9,7 +9,7 @@ namespace XTwitterScraper.Models.X.Lists; /// -/// Get list tweets +/// List tweets from an X List /// /// NOTE: Do not inherit from this type outside the SDK unless you're okay with /// breaking changes in non-major versions. We may add new methods in the future that @@ -185,13 +185,13 @@ public override Uri Url(ClientOptions options) options.BaseUrl.ToString().TrimEnd('/') + string.Format("/x/lists/{0}/tweets", this.ID) ) { - Query = this.QueryString(options, SecurityOptions.All()), + Query = this.QueryString(options), }.Uri; } internal override void AddHeadersToRequest(HttpRequestMessage request, ClientOptions options) { - ParamsBase.AddDefaultHeaders(request, options, SecurityOptions.All()); + ParamsBase.AddDefaultHeaders(request, options); foreach (var item in this.RawHeaderData) { ParamsBase.AddHeaderElementToRequest(request, item.Key, item.Value); diff --git a/src/XTwitterScraper/Models/X/Media/MediaDownloadParams.cs b/src/XTwitterScraper/Models/X/Media/MediaDownloadParams.cs index 09ae206..ee272da 100644 --- a/src/XTwitterScraper/Models/X/Media/MediaDownloadParams.cs +++ b/src/XTwitterScraper/Models/X/Media/MediaDownloadParams.cs @@ -11,7 +11,7 @@ namespace XTwitterScraper.Models.X.Media; /// -/// Download tweet media +/// Download images & videos from tweets /// /// NOTE: Do not inherit from this type outside the SDK unless you're okay with /// breaking changes in non-major versions. We may add new methods in the future that @@ -152,7 +152,7 @@ public override Uri Url(ClientOptions options) { return new UriBuilder(options.BaseUrl.ToString().TrimEnd('/') + "/x/media/download") { - Query = this.QueryString(options, SecurityOptions.All()), + Query = this.QueryString(options), }.Uri; } @@ -167,7 +167,7 @@ public override Uri Url(ClientOptions options) internal override void AddHeadersToRequest(HttpRequestMessage request, ClientOptions options) { - ParamsBase.AddDefaultHeaders(request, options, SecurityOptions.All()); + ParamsBase.AddDefaultHeaders(request, options); foreach (var item in this.RawHeaderData) { ParamsBase.AddHeaderElementToRequest(request, item.Key, item.Value); diff --git a/src/XTwitterScraper/Models/X/Media/MediaUploadParams.cs b/src/XTwitterScraper/Models/X/Media/MediaUploadParams.cs index 82060da..46dda1e 100644 --- a/src/XTwitterScraper/Models/X/Media/MediaUploadParams.cs +++ b/src/XTwitterScraper/Models/X/Media/MediaUploadParams.cs @@ -149,7 +149,7 @@ public override Uri Url(ClientOptions options) { return new UriBuilder(options.BaseUrl.ToString().TrimEnd('/') + "/x/media") { - Query = this.QueryString(options, SecurityOptions.All()), + Query = this.QueryString(options), }.Uri; } @@ -160,7 +160,7 @@ public override Uri Url(ClientOptions options) internal override void AddHeadersToRequest(HttpRequestMessage request, ClientOptions options) { - ParamsBase.AddDefaultHeaders(request, options, SecurityOptions.All()); + ParamsBase.AddDefaultHeaders(request, options); foreach (var item in this.RawHeaderData) { ParamsBase.AddHeaderElementToRequest(request, item.Key, item.Value); diff --git a/src/XTwitterScraper/Models/X/Profile/ProfileUpdateAvatarParams.cs b/src/XTwitterScraper/Models/X/Profile/ProfileUpdateAvatarParams.cs index bfc8d4f..bb5f7b1 100644 --- a/src/XTwitterScraper/Models/X/Profile/ProfileUpdateAvatarParams.cs +++ b/src/XTwitterScraper/Models/X/Profile/ProfileUpdateAvatarParams.cs @@ -131,7 +131,7 @@ public override Uri Url(ClientOptions options) { return new UriBuilder(options.BaseUrl.ToString().TrimEnd('/') + "/x/profile/avatar") { - Query = this.QueryString(options, SecurityOptions.All()), + Query = this.QueryString(options), }.Uri; } @@ -142,7 +142,7 @@ public override Uri Url(ClientOptions options) internal override void AddHeadersToRequest(HttpRequestMessage request, ClientOptions options) { - ParamsBase.AddDefaultHeaders(request, options, SecurityOptions.All()); + ParamsBase.AddDefaultHeaders(request, options); foreach (var item in this.RawHeaderData) { ParamsBase.AddHeaderElementToRequest(request, item.Key, item.Value); diff --git a/src/XTwitterScraper/Models/X/Profile/ProfileUpdateBannerParams.cs b/src/XTwitterScraper/Models/X/Profile/ProfileUpdateBannerParams.cs index 412a2af..07ac14d 100644 --- a/src/XTwitterScraper/Models/X/Profile/ProfileUpdateBannerParams.cs +++ b/src/XTwitterScraper/Models/X/Profile/ProfileUpdateBannerParams.cs @@ -131,7 +131,7 @@ public override Uri Url(ClientOptions options) { return new UriBuilder(options.BaseUrl.ToString().TrimEnd('/') + "/x/profile/banner") { - Query = this.QueryString(options, SecurityOptions.All()), + Query = this.QueryString(options), }.Uri; } @@ -142,7 +142,7 @@ public override Uri Url(ClientOptions options) internal override void AddHeadersToRequest(HttpRequestMessage request, ClientOptions options) { - ParamsBase.AddDefaultHeaders(request, options, SecurityOptions.All()); + ParamsBase.AddDefaultHeaders(request, options); foreach (var item in this.RawHeaderData) { ParamsBase.AddHeaderElementToRequest(request, item.Key, item.Value); diff --git a/src/XTwitterScraper/Models/X/Profile/ProfileUpdateParams.cs b/src/XTwitterScraper/Models/X/Profile/ProfileUpdateParams.cs index e3bf959..9a0796d 100644 --- a/src/XTwitterScraper/Models/X/Profile/ProfileUpdateParams.cs +++ b/src/XTwitterScraper/Models/X/Profile/ProfileUpdateParams.cs @@ -200,7 +200,7 @@ public override Uri Url(ClientOptions options) { return new UriBuilder(options.BaseUrl.ToString().TrimEnd('/') + "/x/profile") { - Query = this.QueryString(options, SecurityOptions.All()), + Query = this.QueryString(options), }.Uri; } @@ -215,7 +215,7 @@ public override Uri Url(ClientOptions options) internal override void AddHeadersToRequest(HttpRequestMessage request, ClientOptions options) { - ParamsBase.AddDefaultHeaders(request, options, SecurityOptions.All()); + ParamsBase.AddDefaultHeaders(request, options); foreach (var item in this.RawHeaderData) { ParamsBase.AddHeaderElementToRequest(request, item.Key, item.Value); diff --git a/src/XTwitterScraper/Models/X/Tweets/Like/LikeCreateParams.cs b/src/XTwitterScraper/Models/X/Tweets/Like/LikeCreateParams.cs index 76ca63a..b260f8a 100644 --- a/src/XTwitterScraper/Models/X/Tweets/Like/LikeCreateParams.cs +++ b/src/XTwitterScraper/Models/X/Tweets/Like/LikeCreateParams.cs @@ -131,7 +131,7 @@ public override Uri Url(ClientOptions options) options.BaseUrl.ToString().TrimEnd('/') + string.Format("/x/tweets/{0}/like", this.ID) ) { - Query = this.QueryString(options, SecurityOptions.All()), + Query = this.QueryString(options), }.Uri; } @@ -146,7 +146,7 @@ public override Uri Url(ClientOptions options) internal override void AddHeadersToRequest(HttpRequestMessage request, ClientOptions options) { - ParamsBase.AddDefaultHeaders(request, options, SecurityOptions.All()); + ParamsBase.AddDefaultHeaders(request, options); foreach (var item in this.RawHeaderData) { ParamsBase.AddHeaderElementToRequest(request, item.Key, item.Value); diff --git a/src/XTwitterScraper/Models/X/Tweets/Like/LikeDeleteParams.cs b/src/XTwitterScraper/Models/X/Tweets/Like/LikeDeleteParams.cs index 76ce7f8..22fe83b 100644 --- a/src/XTwitterScraper/Models/X/Tweets/Like/LikeDeleteParams.cs +++ b/src/XTwitterScraper/Models/X/Tweets/Like/LikeDeleteParams.cs @@ -131,7 +131,7 @@ public override Uri Url(ClientOptions options) options.BaseUrl.ToString().TrimEnd('/') + string.Format("/x/tweets/{0}/like", this.ID) ) { - Query = this.QueryString(options, SecurityOptions.All()), + Query = this.QueryString(options), }.Uri; } @@ -146,7 +146,7 @@ public override Uri Url(ClientOptions options) internal override void AddHeadersToRequest(HttpRequestMessage request, ClientOptions options) { - ParamsBase.AddDefaultHeaders(request, options, SecurityOptions.All()); + ParamsBase.AddDefaultHeaders(request, options); foreach (var item in this.RawHeaderData) { ParamsBase.AddHeaderElementToRequest(request, item.Key, item.Value); diff --git a/src/XTwitterScraper/Models/X/Tweets/Retweet/RetweetCreateParams.cs b/src/XTwitterScraper/Models/X/Tweets/Retweet/RetweetCreateParams.cs index 190de3d..2771df2 100644 --- a/src/XTwitterScraper/Models/X/Tweets/Retweet/RetweetCreateParams.cs +++ b/src/XTwitterScraper/Models/X/Tweets/Retweet/RetweetCreateParams.cs @@ -132,7 +132,7 @@ public override Uri Url(ClientOptions options) + string.Format("/x/tweets/{0}/retweet", this.ID) ) { - Query = this.QueryString(options, SecurityOptions.All()), + Query = this.QueryString(options), }.Uri; } @@ -147,7 +147,7 @@ public override Uri Url(ClientOptions options) internal override void AddHeadersToRequest(HttpRequestMessage request, ClientOptions options) { - ParamsBase.AddDefaultHeaders(request, options, SecurityOptions.All()); + ParamsBase.AddDefaultHeaders(request, options); foreach (var item in this.RawHeaderData) { ParamsBase.AddHeaderElementToRequest(request, item.Key, item.Value); diff --git a/src/XTwitterScraper/Models/X/Tweets/Retweet/RetweetDeleteParams.cs b/src/XTwitterScraper/Models/X/Tweets/Retweet/RetweetDeleteParams.cs index dd3eea4..3699786 100644 --- a/src/XTwitterScraper/Models/X/Tweets/Retweet/RetweetDeleteParams.cs +++ b/src/XTwitterScraper/Models/X/Tweets/Retweet/RetweetDeleteParams.cs @@ -132,7 +132,7 @@ public override Uri Url(ClientOptions options) + string.Format("/x/tweets/{0}/retweet", this.ID) ) { - Query = this.QueryString(options, SecurityOptions.All()), + Query = this.QueryString(options), }.Uri; } @@ -147,7 +147,7 @@ public override Uri Url(ClientOptions options) internal override void AddHeadersToRequest(HttpRequestMessage request, ClientOptions options) { - ParamsBase.AddDefaultHeaders(request, options, SecurityOptions.All()); + ParamsBase.AddDefaultHeaders(request, options); foreach (var item in this.RawHeaderData) { ParamsBase.AddHeaderElementToRequest(request, item.Key, item.Value); diff --git a/src/XTwitterScraper/Models/X/Tweets/TweetCreateParams.cs b/src/XTwitterScraper/Models/X/Tweets/TweetCreateParams.cs index 75326df..734db2d 100644 --- a/src/XTwitterScraper/Models/X/Tweets/TweetCreateParams.cs +++ b/src/XTwitterScraper/Models/X/Tweets/TweetCreateParams.cs @@ -38,16 +38,6 @@ public required string Account init { this._rawBodyData.Set("account", value); } } - public required string Text - { - get - { - this._rawBodyData.Freeze(); - return this._rawBodyData.GetNotNullClass("text"); - } - init { this._rawBodyData.Set("text", value); } - } - public string? AttachmentUrl { get @@ -102,6 +92,33 @@ public bool? IsNoteTweet } } + /// + /// Array of media URLs to attach (mutually exclusive with media_ids) + /// + public IReadOnlyList? Media + { + get + { + this._rawBodyData.Freeze(); + return this._rawBodyData.GetNullableStruct>("media"); + } + init + { + if (value == null) + { + return; + } + + this._rawBodyData.Set?>( + "media", + value == null ? null : ImmutableArray.ToImmutableArray(value) + ); + } + } + + /// + /// Array of media IDs to attach (mutually exclusive with media) + /// public IReadOnlyList? MediaIds { get @@ -141,6 +158,27 @@ public string? ReplyToTweetID } } + /// + /// Tweet text (optional when media is provided) + /// + public string? Text + { + get + { + this._rawBodyData.Freeze(); + return this._rawBodyData.GetNullableClass("text"); + } + init + { + if (value == null) + { + return; + } + + this._rawBodyData.Set("text", value); + } + } + public TweetCreateParams() { } #pragma warning disable CS8618 @@ -223,7 +261,7 @@ public override Uri Url(ClientOptions options) { return new UriBuilder(options.BaseUrl.ToString().TrimEnd('/') + "/x/tweets") { - Query = this.QueryString(options, SecurityOptions.All()), + Query = this.QueryString(options), }.Uri; } @@ -238,7 +276,7 @@ public override Uri Url(ClientOptions options) internal override void AddHeadersToRequest(HttpRequestMessage request, ClientOptions options) { - ParamsBase.AddDefaultHeaders(request, options, SecurityOptions.All()); + ParamsBase.AddDefaultHeaders(request, options); foreach (var item in this.RawHeaderData) { ParamsBase.AddHeaderElementToRequest(request, item.Key, item.Value); diff --git a/src/XTwitterScraper/Models/X/Tweets/TweetDeleteParams.cs b/src/XTwitterScraper/Models/X/Tweets/TweetDeleteParams.cs index c053f1e..341ff6b 100644 --- a/src/XTwitterScraper/Models/X/Tweets/TweetDeleteParams.cs +++ b/src/XTwitterScraper/Models/X/Tweets/TweetDeleteParams.cs @@ -131,7 +131,7 @@ public override Uri Url(ClientOptions options) options.BaseUrl.ToString().TrimEnd('/') + string.Format("/x/tweets/{0}", this.ID) ) { - Query = this.QueryString(options, SecurityOptions.All()), + Query = this.QueryString(options), }.Uri; } @@ -146,7 +146,7 @@ public override Uri Url(ClientOptions options) internal override void AddHeadersToRequest(HttpRequestMessage request, ClientOptions options) { - ParamsBase.AddDefaultHeaders(request, options, SecurityOptions.All()); + ParamsBase.AddDefaultHeaders(request, options); foreach (var item in this.RawHeaderData) { ParamsBase.AddHeaderElementToRequest(request, item.Key, item.Value); diff --git a/src/XTwitterScraper/Models/X/Tweets/TweetGetFavoritersParams.cs b/src/XTwitterScraper/Models/X/Tweets/TweetGetFavoritersParams.cs index 39ee7f0..c88296c 100644 --- a/src/XTwitterScraper/Models/X/Tweets/TweetGetFavoritersParams.cs +++ b/src/XTwitterScraper/Models/X/Tweets/TweetGetFavoritersParams.cs @@ -9,7 +9,7 @@ namespace XTwitterScraper.Models.X.Tweets; /// -/// Get users who liked a tweet +/// List users who liked a tweet /// /// NOTE: Do not inherit from this type outside the SDK unless you're okay with /// breaking changes in non-major versions. We may add new methods in the future that @@ -123,13 +123,13 @@ public override Uri Url(ClientOptions options) + string.Format("/x/tweets/{0}/favoriters", this.ID) ) { - Query = this.QueryString(options, SecurityOptions.All()), + Query = this.QueryString(options), }.Uri; } internal override void AddHeadersToRequest(HttpRequestMessage request, ClientOptions options) { - ParamsBase.AddDefaultHeaders(request, options, SecurityOptions.All()); + ParamsBase.AddDefaultHeaders(request, options); foreach (var item in this.RawHeaderData) { ParamsBase.AddHeaderElementToRequest(request, item.Key, item.Value); diff --git a/src/XTwitterScraper/Models/X/Tweets/TweetGetQuotesParams.cs b/src/XTwitterScraper/Models/X/Tweets/TweetGetQuotesParams.cs index 80937bd..c910c25 100644 --- a/src/XTwitterScraper/Models/X/Tweets/TweetGetQuotesParams.cs +++ b/src/XTwitterScraper/Models/X/Tweets/TweetGetQuotesParams.cs @@ -9,7 +9,7 @@ namespace XTwitterScraper.Models.X.Tweets; /// -/// Get quote tweets of a tweet +/// List quote tweets of a tweet /// /// NOTE: Do not inherit from this type outside the SDK unless you're okay with /// breaking changes in non-major versions. We may add new methods in the future that @@ -185,13 +185,13 @@ public override Uri Url(ClientOptions options) options.BaseUrl.ToString().TrimEnd('/') + string.Format("/x/tweets/{0}/quotes", this.ID) ) { - Query = this.QueryString(options, SecurityOptions.All()), + Query = this.QueryString(options), }.Uri; } internal override void AddHeadersToRequest(HttpRequestMessage request, ClientOptions options) { - ParamsBase.AddDefaultHeaders(request, options, SecurityOptions.All()); + ParamsBase.AddDefaultHeaders(request, options); foreach (var item in this.RawHeaderData) { ParamsBase.AddHeaderElementToRequest(request, item.Key, item.Value); diff --git a/src/XTwitterScraper/Models/X/Tweets/TweetGetRepliesParams.cs b/src/XTwitterScraper/Models/X/Tweets/TweetGetRepliesParams.cs index e1253a6..2b01be8 100644 --- a/src/XTwitterScraper/Models/X/Tweets/TweetGetRepliesParams.cs +++ b/src/XTwitterScraper/Models/X/Tweets/TweetGetRepliesParams.cs @@ -9,7 +9,7 @@ namespace XTwitterScraper.Models.X.Tweets; /// -/// Get replies to a tweet +/// List replies to a tweet /// /// NOTE: Do not inherit from this type outside the SDK unless you're okay with /// breaking changes in non-major versions. We may add new methods in the future that @@ -165,13 +165,13 @@ public override Uri Url(ClientOptions options) + string.Format("/x/tweets/{0}/replies", this.ID) ) { - Query = this.QueryString(options, SecurityOptions.All()), + Query = this.QueryString(options), }.Uri; } internal override void AddHeadersToRequest(HttpRequestMessage request, ClientOptions options) { - ParamsBase.AddDefaultHeaders(request, options, SecurityOptions.All()); + ParamsBase.AddDefaultHeaders(request, options); foreach (var item in this.RawHeaderData) { ParamsBase.AddHeaderElementToRequest(request, item.Key, item.Value); diff --git a/src/XTwitterScraper/Models/X/Tweets/TweetGetRetweetersParams.cs b/src/XTwitterScraper/Models/X/Tweets/TweetGetRetweetersParams.cs index ae2d508..3958ccd 100644 --- a/src/XTwitterScraper/Models/X/Tweets/TweetGetRetweetersParams.cs +++ b/src/XTwitterScraper/Models/X/Tweets/TweetGetRetweetersParams.cs @@ -9,7 +9,7 @@ namespace XTwitterScraper.Models.X.Tweets; /// -/// Get users who retweeted a tweet +/// List users who retweeted a tweet /// /// NOTE: Do not inherit from this type outside the SDK unless you're okay with /// breaking changes in non-major versions. We may add new methods in the future that @@ -123,13 +123,13 @@ public override Uri Url(ClientOptions options) + string.Format("/x/tweets/{0}/retweeters", this.ID) ) { - Query = this.QueryString(options, SecurityOptions.All()), + Query = this.QueryString(options), }.Uri; } internal override void AddHeadersToRequest(HttpRequestMessage request, ClientOptions options) { - ParamsBase.AddDefaultHeaders(request, options, SecurityOptions.All()); + ParamsBase.AddDefaultHeaders(request, options); foreach (var item in this.RawHeaderData) { ParamsBase.AddHeaderElementToRequest(request, item.Key, item.Value); diff --git a/src/XTwitterScraper/Models/X/Tweets/TweetGetThreadParams.cs b/src/XTwitterScraper/Models/X/Tweets/TweetGetThreadParams.cs index b023943..f783399 100644 --- a/src/XTwitterScraper/Models/X/Tweets/TweetGetThreadParams.cs +++ b/src/XTwitterScraper/Models/X/Tweets/TweetGetThreadParams.cs @@ -9,7 +9,7 @@ namespace XTwitterScraper.Models.X.Tweets; /// -/// Get thread context for a tweet +/// Get full conversation thread for a tweet /// /// NOTE: Do not inherit from this type outside the SDK unless you're okay with /// breaking changes in non-major versions. We may add new methods in the future that @@ -122,13 +122,13 @@ public override Uri Url(ClientOptions options) options.BaseUrl.ToString().TrimEnd('/') + string.Format("/x/tweets/{0}/thread", this.ID) ) { - Query = this.QueryString(options, SecurityOptions.All()), + Query = this.QueryString(options), }.Uri; } internal override void AddHeadersToRequest(HttpRequestMessage request, ClientOptions options) { - ParamsBase.AddDefaultHeaders(request, options, SecurityOptions.All()); + ParamsBase.AddDefaultHeaders(request, options); foreach (var item in this.RawHeaderData) { ParamsBase.AddHeaderElementToRequest(request, item.Key, item.Value); diff --git a/src/XTwitterScraper/Models/X/Tweets/TweetListParams.cs b/src/XTwitterScraper/Models/X/Tweets/TweetListParams.cs index 9cabf0e..6d8964b 100644 --- a/src/XTwitterScraper/Models/X/Tweets/TweetListParams.cs +++ b/src/XTwitterScraper/Models/X/Tweets/TweetListParams.cs @@ -101,13 +101,13 @@ public override Uri Url(ClientOptions options) { return new UriBuilder(options.BaseUrl.ToString().TrimEnd('/') + "/x/tweets") { - Query = this.QueryString(options, SecurityOptions.All()), + Query = this.QueryString(options), }.Uri; } internal override void AddHeadersToRequest(HttpRequestMessage request, ClientOptions options) { - ParamsBase.AddDefaultHeaders(request, options, SecurityOptions.All()); + ParamsBase.AddDefaultHeaders(request, options); foreach (var item in this.RawHeaderData) { ParamsBase.AddHeaderElementToRequest(request, item.Key, item.Value); diff --git a/src/XTwitterScraper/Models/X/Tweets/TweetRetrieveParams.cs b/src/XTwitterScraper/Models/X/Tweets/TweetRetrieveParams.cs index 219217a..05d15de 100644 --- a/src/XTwitterScraper/Models/X/Tweets/TweetRetrieveParams.cs +++ b/src/XTwitterScraper/Models/X/Tweets/TweetRetrieveParams.cs @@ -9,7 +9,7 @@ namespace XTwitterScraper.Models.X.Tweets; /// -/// Look up tweet +/// Get tweet with full text, author, metrics & media /// /// NOTE: Do not inherit from this type outside the SDK unless you're okay with /// breaking changes in non-major versions. We may add new methods in the future that @@ -101,13 +101,13 @@ public override Uri Url(ClientOptions options) options.BaseUrl.ToString().TrimEnd('/') + string.Format("/x/tweets/{0}", this.ID) ) { - Query = this.QueryString(options, SecurityOptions.All()), + Query = this.QueryString(options), }.Uri; } internal override void AddHeadersToRequest(HttpRequestMessage request, ClientOptions options) { - ParamsBase.AddDefaultHeaders(request, options, SecurityOptions.All()); + ParamsBase.AddDefaultHeaders(request, options); foreach (var item in this.RawHeaderData) { ParamsBase.AddHeaderElementToRequest(request, item.Key, item.Value); diff --git a/src/XTwitterScraper/Models/X/Tweets/TweetSearchParams.cs b/src/XTwitterScraper/Models/X/Tweets/TweetSearchParams.cs index bca5f6d..41baabe 100644 --- a/src/XTwitterScraper/Models/X/Tweets/TweetSearchParams.cs +++ b/src/XTwitterScraper/Models/X/Tweets/TweetSearchParams.cs @@ -11,7 +11,7 @@ namespace XTwitterScraper.Models.X.Tweets; /// -/// Search tweets +/// Search tweets with X query operators & pagination /// /// NOTE: Do not inherit from this type outside the SDK unless you're okay with /// breaking changes in non-major versions. We may add new methods in the future that @@ -208,13 +208,13 @@ public virtual bool Equals(TweetSearchParams? other) { return new System::UriBuilder(options.BaseUrl.ToString().TrimEnd('/') + "/x/tweets/search") { - Query = this.QueryString(options, SecurityOptions.All()), + Query = this.QueryString(options), }.Uri; } internal override void AddHeadersToRequest(HttpRequestMessage request, ClientOptions options) { - ParamsBase.AddDefaultHeaders(request, options, SecurityOptions.All()); + ParamsBase.AddDefaultHeaders(request, options); foreach (var item in this.RawHeaderData) { ParamsBase.AddHeaderElementToRequest(request, item.Key, item.Value); diff --git a/src/XTwitterScraper/Models/X/Users/Follow/FollowCreateParams.cs b/src/XTwitterScraper/Models/X/Users/Follow/FollowCreateParams.cs index 9bb564c..ee31d76 100644 --- a/src/XTwitterScraper/Models/X/Users/Follow/FollowCreateParams.cs +++ b/src/XTwitterScraper/Models/X/Users/Follow/FollowCreateParams.cs @@ -131,7 +131,7 @@ public override Uri Url(ClientOptions options) options.BaseUrl.ToString().TrimEnd('/') + string.Format("/x/users/{0}/follow", this.ID) ) { - Query = this.QueryString(options, SecurityOptions.All()), + Query = this.QueryString(options), }.Uri; } @@ -146,7 +146,7 @@ public override Uri Url(ClientOptions options) internal override void AddHeadersToRequest(HttpRequestMessage request, ClientOptions options) { - ParamsBase.AddDefaultHeaders(request, options, SecurityOptions.All()); + ParamsBase.AddDefaultHeaders(request, options); foreach (var item in this.RawHeaderData) { ParamsBase.AddHeaderElementToRequest(request, item.Key, item.Value); diff --git a/src/XTwitterScraper/Models/X/Users/Follow/FollowDeleteAllParams.cs b/src/XTwitterScraper/Models/X/Users/Follow/FollowDeleteAllParams.cs index df6abe6..6b23895 100644 --- a/src/XTwitterScraper/Models/X/Users/Follow/FollowDeleteAllParams.cs +++ b/src/XTwitterScraper/Models/X/Users/Follow/FollowDeleteAllParams.cs @@ -131,7 +131,7 @@ public override Uri Url(ClientOptions options) options.BaseUrl.ToString().TrimEnd('/') + string.Format("/x/users/{0}/follow", this.ID) ) { - Query = this.QueryString(options, SecurityOptions.All()), + Query = this.QueryString(options), }.Uri; } @@ -146,7 +146,7 @@ public override Uri Url(ClientOptions options) internal override void AddHeadersToRequest(HttpRequestMessage request, ClientOptions options) { - ParamsBase.AddDefaultHeaders(request, options, SecurityOptions.All()); + ParamsBase.AddDefaultHeaders(request, options); foreach (var item in this.RawHeaderData) { ParamsBase.AddHeaderElementToRequest(request, item.Key, item.Value); diff --git a/src/XTwitterScraper/Models/X/Users/UserRetrieveBatchParams.cs b/src/XTwitterScraper/Models/X/Users/UserRetrieveBatchParams.cs index ded717d..76ca644 100644 --- a/src/XTwitterScraper/Models/X/Users/UserRetrieveBatchParams.cs +++ b/src/XTwitterScraper/Models/X/Users/UserRetrieveBatchParams.cs @@ -9,7 +9,7 @@ namespace XTwitterScraper.Models.X.Users; /// -/// Get multiple users by IDs +/// Look up multiple users by IDs in one call /// /// NOTE: Do not inherit from this type outside the SDK unless you're okay with /// breaking changes in non-major versions. We may add new methods in the future that @@ -101,13 +101,13 @@ public override Uri Url(ClientOptions options) { return new UriBuilder(options.BaseUrl.ToString().TrimEnd('/') + "/x/users/batch") { - Query = this.QueryString(options, SecurityOptions.All()), + Query = this.QueryString(options), }.Uri; } internal override void AddHeadersToRequest(HttpRequestMessage request, ClientOptions options) { - ParamsBase.AddDefaultHeaders(request, options, SecurityOptions.All()); + ParamsBase.AddDefaultHeaders(request, options); foreach (var item in this.RawHeaderData) { ParamsBase.AddHeaderElementToRequest(request, item.Key, item.Value); diff --git a/src/XTwitterScraper/Models/X/Users/UserRetrieveFollowersParams.cs b/src/XTwitterScraper/Models/X/Users/UserRetrieveFollowersParams.cs index 099370d..c0af58b 100644 --- a/src/XTwitterScraper/Models/X/Users/UserRetrieveFollowersParams.cs +++ b/src/XTwitterScraper/Models/X/Users/UserRetrieveFollowersParams.cs @@ -9,7 +9,7 @@ namespace XTwitterScraper.Models.X.Users; /// -/// Get user followers +/// List followers of a user /// /// NOTE: Do not inherit from this type outside the SDK unless you're okay with /// breaking changes in non-major versions. We may add new methods in the future that @@ -144,13 +144,13 @@ public override Uri Url(ClientOptions options) + string.Format("/x/users/{0}/followers", this.ID) ) { - Query = this.QueryString(options, SecurityOptions.All()), + Query = this.QueryString(options), }.Uri; } internal override void AddHeadersToRequest(HttpRequestMessage request, ClientOptions options) { - ParamsBase.AddDefaultHeaders(request, options, SecurityOptions.All()); + ParamsBase.AddDefaultHeaders(request, options); foreach (var item in this.RawHeaderData) { ParamsBase.AddHeaderElementToRequest(request, item.Key, item.Value); diff --git a/src/XTwitterScraper/Models/X/Users/UserRetrieveFollowersYouKnowParams.cs b/src/XTwitterScraper/Models/X/Users/UserRetrieveFollowersYouKnowParams.cs index c5478ca..02c2d27 100644 --- a/src/XTwitterScraper/Models/X/Users/UserRetrieveFollowersYouKnowParams.cs +++ b/src/XTwitterScraper/Models/X/Users/UserRetrieveFollowersYouKnowParams.cs @@ -9,7 +9,7 @@ namespace XTwitterScraper.Models.X.Users; /// -/// Get followers you know for a user +/// List mutual followers between you and a user /// /// NOTE: Do not inherit from this type outside the SDK unless you're okay with /// breaking changes in non-major versions. We may add new methods in the future that @@ -125,13 +125,13 @@ public override Uri Url(ClientOptions options) + string.Format("/x/users/{0}/followers-you-know", this.ID) ) { - Query = this.QueryString(options, SecurityOptions.All()), + Query = this.QueryString(options), }.Uri; } internal override void AddHeadersToRequest(HttpRequestMessage request, ClientOptions options) { - ParamsBase.AddDefaultHeaders(request, options, SecurityOptions.All()); + ParamsBase.AddDefaultHeaders(request, options); foreach (var item in this.RawHeaderData) { ParamsBase.AddHeaderElementToRequest(request, item.Key, item.Value); diff --git a/src/XTwitterScraper/Models/X/Users/UserRetrieveFollowingParams.cs b/src/XTwitterScraper/Models/X/Users/UserRetrieveFollowingParams.cs index 5d59e01..0fcc3b6 100644 --- a/src/XTwitterScraper/Models/X/Users/UserRetrieveFollowingParams.cs +++ b/src/XTwitterScraper/Models/X/Users/UserRetrieveFollowingParams.cs @@ -9,7 +9,7 @@ namespace XTwitterScraper.Models.X.Users; /// -/// Get users this user follows +/// List accounts a user follows /// /// NOTE: Do not inherit from this type outside the SDK unless you're okay with /// breaking changes in non-major versions. We may add new methods in the future that @@ -144,13 +144,13 @@ public override Uri Url(ClientOptions options) + string.Format("/x/users/{0}/following", this.ID) ) { - Query = this.QueryString(options, SecurityOptions.All()), + Query = this.QueryString(options), }.Uri; } internal override void AddHeadersToRequest(HttpRequestMessage request, ClientOptions options) { - ParamsBase.AddDefaultHeaders(request, options, SecurityOptions.All()); + ParamsBase.AddDefaultHeaders(request, options); foreach (var item in this.RawHeaderData) { ParamsBase.AddHeaderElementToRequest(request, item.Key, item.Value); diff --git a/src/XTwitterScraper/Models/X/Users/UserRetrieveLikesParams.cs b/src/XTwitterScraper/Models/X/Users/UserRetrieveLikesParams.cs index ef28442..21bb571 100644 --- a/src/XTwitterScraper/Models/X/Users/UserRetrieveLikesParams.cs +++ b/src/XTwitterScraper/Models/X/Users/UserRetrieveLikesParams.cs @@ -9,7 +9,7 @@ namespace XTwitterScraper.Models.X.Users; /// -/// Get tweets liked by a user +/// List tweets liked by a user /// /// NOTE: Do not inherit from this type outside the SDK unless you're okay with /// breaking changes in non-major versions. We may add new methods in the future that @@ -122,13 +122,13 @@ public override Uri Url(ClientOptions options) options.BaseUrl.ToString().TrimEnd('/') + string.Format("/x/users/{0}/likes", this.ID) ) { - Query = this.QueryString(options, SecurityOptions.All()), + Query = this.QueryString(options), }.Uri; } internal override void AddHeadersToRequest(HttpRequestMessage request, ClientOptions options) { - ParamsBase.AddDefaultHeaders(request, options, SecurityOptions.All()); + ParamsBase.AddDefaultHeaders(request, options); foreach (var item in this.RawHeaderData) { ParamsBase.AddHeaderElementToRequest(request, item.Key, item.Value); diff --git a/src/XTwitterScraper/Models/X/Users/UserRetrieveMediaParams.cs b/src/XTwitterScraper/Models/X/Users/UserRetrieveMediaParams.cs index 72b5868..5016dc2 100644 --- a/src/XTwitterScraper/Models/X/Users/UserRetrieveMediaParams.cs +++ b/src/XTwitterScraper/Models/X/Users/UserRetrieveMediaParams.cs @@ -9,7 +9,7 @@ namespace XTwitterScraper.Models.X.Users; /// -/// Get media tweets by a user +/// List media tweets posted by a user /// /// NOTE: Do not inherit from this type outside the SDK unless you're okay with /// breaking changes in non-major versions. We may add new methods in the future that @@ -122,13 +122,13 @@ public override Uri Url(ClientOptions options) options.BaseUrl.ToString().TrimEnd('/') + string.Format("/x/users/{0}/media", this.ID) ) { - Query = this.QueryString(options, SecurityOptions.All()), + Query = this.QueryString(options), }.Uri; } internal override void AddHeadersToRequest(HttpRequestMessage request, ClientOptions options) { - ParamsBase.AddDefaultHeaders(request, options, SecurityOptions.All()); + ParamsBase.AddDefaultHeaders(request, options); foreach (var item in this.RawHeaderData) { ParamsBase.AddHeaderElementToRequest(request, item.Key, item.Value); diff --git a/src/XTwitterScraper/Models/X/Users/UserRetrieveMentionsParams.cs b/src/XTwitterScraper/Models/X/Users/UserRetrieveMentionsParams.cs index b69de09..c31a23d 100644 --- a/src/XTwitterScraper/Models/X/Users/UserRetrieveMentionsParams.cs +++ b/src/XTwitterScraper/Models/X/Users/UserRetrieveMentionsParams.cs @@ -9,7 +9,7 @@ namespace XTwitterScraper.Models.X.Users; /// -/// Get tweets mentioning a user +/// List tweets mentioning a user /// /// NOTE: Do not inherit from this type outside the SDK unless you're okay with /// breaking changes in non-major versions. We may add new methods in the future that @@ -165,13 +165,13 @@ public override Uri Url(ClientOptions options) + string.Format("/x/users/{0}/mentions", this.ID) ) { - Query = this.QueryString(options, SecurityOptions.All()), + Query = this.QueryString(options), }.Uri; } internal override void AddHeadersToRequest(HttpRequestMessage request, ClientOptions options) { - ParamsBase.AddDefaultHeaders(request, options, SecurityOptions.All()); + ParamsBase.AddDefaultHeaders(request, options); foreach (var item in this.RawHeaderData) { ParamsBase.AddHeaderElementToRequest(request, item.Key, item.Value); diff --git a/src/XTwitterScraper/Models/X/Users/UserRetrieveParams.cs b/src/XTwitterScraper/Models/X/Users/UserRetrieveParams.cs index a2eab67..e141ba9 100644 --- a/src/XTwitterScraper/Models/X/Users/UserRetrieveParams.cs +++ b/src/XTwitterScraper/Models/X/Users/UserRetrieveParams.cs @@ -9,7 +9,7 @@ namespace XTwitterScraper.Models.X.Users; /// -/// Look up X user +/// Get user profile with follower counts & verification /// /// NOTE: Do not inherit from this type outside the SDK unless you're okay with /// breaking changes in non-major versions. We may add new methods in the future that @@ -101,13 +101,13 @@ public override Uri Url(ClientOptions options) options.BaseUrl.ToString().TrimEnd('/') + string.Format("/x/users/{0}", this.ID) ) { - Query = this.QueryString(options, SecurityOptions.All()), + Query = this.QueryString(options), }.Uri; } internal override void AddHeadersToRequest(HttpRequestMessage request, ClientOptions options) { - ParamsBase.AddDefaultHeaders(request, options, SecurityOptions.All()); + ParamsBase.AddDefaultHeaders(request, options); foreach (var item in this.RawHeaderData) { ParamsBase.AddHeaderElementToRequest(request, item.Key, item.Value); diff --git a/src/XTwitterScraper/Models/X/Users/UserRetrieveSearchParams.cs b/src/XTwitterScraper/Models/X/Users/UserRetrieveSearchParams.cs index 9723382..67a7c6a 100644 --- a/src/XTwitterScraper/Models/X/Users/UserRetrieveSearchParams.cs +++ b/src/XTwitterScraper/Models/X/Users/UserRetrieveSearchParams.cs @@ -122,13 +122,13 @@ public override Uri Url(ClientOptions options) { return new UriBuilder(options.BaseUrl.ToString().TrimEnd('/') + "/x/users/search") { - Query = this.QueryString(options, SecurityOptions.All()), + Query = this.QueryString(options), }.Uri; } internal override void AddHeadersToRequest(HttpRequestMessage request, ClientOptions options) { - ParamsBase.AddDefaultHeaders(request, options, SecurityOptions.All()); + ParamsBase.AddDefaultHeaders(request, options); foreach (var item in this.RawHeaderData) { ParamsBase.AddHeaderElementToRequest(request, item.Key, item.Value); diff --git a/src/XTwitterScraper/Models/X/Users/UserRetrieveTweetsParams.cs b/src/XTwitterScraper/Models/X/Users/UserRetrieveTweetsParams.cs index b4e501f..10b56ef 100644 --- a/src/XTwitterScraper/Models/X/Users/UserRetrieveTweetsParams.cs +++ b/src/XTwitterScraper/Models/X/Users/UserRetrieveTweetsParams.cs @@ -9,7 +9,7 @@ namespace XTwitterScraper.Models.X.Users; /// -/// Get recent tweets by a user +/// List recent tweets posted by a user /// /// NOTE: Do not inherit from this type outside the SDK unless you're okay with /// breaking changes in non-major versions. We may add new methods in the future that @@ -164,13 +164,13 @@ public override Uri Url(ClientOptions options) options.BaseUrl.ToString().TrimEnd('/') + string.Format("/x/users/{0}/tweets", this.ID) ) { - Query = this.QueryString(options, SecurityOptions.All()), + Query = this.QueryString(options), }.Uri; } internal override void AddHeadersToRequest(HttpRequestMessage request, ClientOptions options) { - ParamsBase.AddDefaultHeaders(request, options, SecurityOptions.All()); + ParamsBase.AddDefaultHeaders(request, options); foreach (var item in this.RawHeaderData) { ParamsBase.AddHeaderElementToRequest(request, item.Key, item.Value); diff --git a/src/XTwitterScraper/Models/X/Users/UserRetrieveVerifiedFollowersParams.cs b/src/XTwitterScraper/Models/X/Users/UserRetrieveVerifiedFollowersParams.cs index 7505df9..39b9ce6 100644 --- a/src/XTwitterScraper/Models/X/Users/UserRetrieveVerifiedFollowersParams.cs +++ b/src/XTwitterScraper/Models/X/Users/UserRetrieveVerifiedFollowersParams.cs @@ -9,7 +9,7 @@ namespace XTwitterScraper.Models.X.Users; /// -/// Get verified followers +/// List verified followers of a user /// /// NOTE: Do not inherit from this type outside the SDK unless you're okay with /// breaking changes in non-major versions. We may add new methods in the future that @@ -125,13 +125,13 @@ public override Uri Url(ClientOptions options) + string.Format("/x/users/{0}/verified-followers", this.ID) ) { - Query = this.QueryString(options, SecurityOptions.All()), + Query = this.QueryString(options), }.Uri; } internal override void AddHeadersToRequest(HttpRequestMessage request, ClientOptions options) { - ParamsBase.AddDefaultHeaders(request, options, SecurityOptions.All()); + ParamsBase.AddDefaultHeaders(request, options); foreach (var item in this.RawHeaderData) { ParamsBase.AddHeaderElementToRequest(request, item.Key, item.Value); diff --git a/src/XTwitterScraper/Models/X/XGetArticleParams.cs b/src/XTwitterScraper/Models/X/XGetArticleParams.cs index 236bf25..ca20cc4 100644 --- a/src/XTwitterScraper/Models/X/XGetArticleParams.cs +++ b/src/XTwitterScraper/Models/X/XGetArticleParams.cs @@ -101,13 +101,13 @@ public override Uri Url(ClientOptions options) options.BaseUrl.ToString().TrimEnd('/') + string.Format("/x/articles/{0}", this.TweetID) ) { - Query = this.QueryString(options, SecurityOptions.All()), + Query = this.QueryString(options), }.Uri; } internal override void AddHeadersToRequest(HttpRequestMessage request, ClientOptions options) { - ParamsBase.AddDefaultHeaders(request, options, SecurityOptions.All()); + ParamsBase.AddDefaultHeaders(request, options); foreach (var item in this.RawHeaderData) { ParamsBase.AddHeaderElementToRequest(request, item.Key, item.Value); diff --git a/src/XTwitterScraper/Models/X/XGetHomeTimelineParams.cs b/src/XTwitterScraper/Models/X/XGetHomeTimelineParams.cs index ea81b1a..3d94a8c 100644 --- a/src/XTwitterScraper/Models/X/XGetHomeTimelineParams.cs +++ b/src/XTwitterScraper/Models/X/XGetHomeTimelineParams.cs @@ -130,13 +130,13 @@ public override Uri Url(ClientOptions options) { return new UriBuilder(options.BaseUrl.ToString().TrimEnd('/') + "/x/timeline") { - Query = this.QueryString(options, SecurityOptions.All()), + Query = this.QueryString(options), }.Uri; } internal override void AddHeadersToRequest(HttpRequestMessage request, ClientOptions options) { - ParamsBase.AddDefaultHeaders(request, options, SecurityOptions.All()); + ParamsBase.AddDefaultHeaders(request, options); foreach (var item in this.RawHeaderData) { ParamsBase.AddHeaderElementToRequest(request, item.Key, item.Value); diff --git a/src/XTwitterScraper/Models/X/XGetNotificationsParams.cs b/src/XTwitterScraper/Models/X/XGetNotificationsParams.cs index dbb4e1e..d8d2d97 100644 --- a/src/XTwitterScraper/Models/X/XGetNotificationsParams.cs +++ b/src/XTwitterScraper/Models/X/XGetNotificationsParams.cs @@ -134,13 +134,13 @@ public virtual bool Equals(XGetNotificationsParams? other) { return new System::UriBuilder(options.BaseUrl.ToString().TrimEnd('/') + "/x/notifications") { - Query = this.QueryString(options, SecurityOptions.All()), + Query = this.QueryString(options), }.Uri; } internal override void AddHeadersToRequest(HttpRequestMessage request, ClientOptions options) { - ParamsBase.AddDefaultHeaders(request, options, SecurityOptions.All()); + ParamsBase.AddDefaultHeaders(request, options); foreach (var item in this.RawHeaderData) { ParamsBase.AddHeaderElementToRequest(request, item.Key, item.Value); diff --git a/src/XTwitterScraper/Models/X/XGetTrendsParams.cs b/src/XTwitterScraper/Models/X/XGetTrendsParams.cs index f5097ef..251395c 100644 --- a/src/XTwitterScraper/Models/X/XGetTrendsParams.cs +++ b/src/XTwitterScraper/Models/X/XGetTrendsParams.cs @@ -9,7 +9,7 @@ namespace XTwitterScraper.Models.X; /// -/// Get trending topics +/// Get trending hashtags & topics from X by region /// /// NOTE: Do not inherit from this type outside the SDK unless you're okay with /// breaking changes in non-major versions. We may add new methods in the future that @@ -17,6 +17,48 @@ namespace XTwitterScraper.Models.X; /// public record class XGetTrendsParams : ParamsBase { + /// + /// Number of trending topics to return (1-50, default 30) + /// + public long? Count + { + get + { + this._rawQueryData.Freeze(); + return this._rawQueryData.GetNullableStruct("count"); + } + init + { + if (value == null) + { + return; + } + + this._rawQueryData.Set("count", value); + } + } + + /// + /// Region WOEID (1=Worldwide, 23424977=US, 23424975=UK, 23424969=Turkey) + /// + public long? Woeid + { + get + { + this._rawQueryData.Freeze(); + return this._rawQueryData.GetNullableStruct("woeid"); + } + init + { + if (value == null) + { + return; + } + + this._rawQueryData.Set("woeid", value); + } + } + public XGetTrendsParams() { } #pragma warning disable CS8618 @@ -88,13 +130,13 @@ public override Uri Url(ClientOptions options) { return new UriBuilder(options.BaseUrl.ToString().TrimEnd('/') + "/x/trends") { - Query = this.QueryString(options, SecurityOptions.All()), + Query = this.QueryString(options), }.Uri; } internal override void AddHeadersToRequest(HttpRequestMessage request, ClientOptions options) { - ParamsBase.AddDefaultHeaders(request, options, SecurityOptions.All()); + ParamsBase.AddDefaultHeaders(request, options); foreach (var item in this.RawHeaderData) { ParamsBase.AddHeaderElementToRequest(request, item.Key, item.Value); diff --git a/src/XTwitterScraper/Services/Bot/IPlatformLinkService.cs b/src/XTwitterScraper/Services/Bot/IPlatformLinkService.cs deleted file mode 100644 index b8e63e4..0000000 --- a/src/XTwitterScraper/Services/Bot/IPlatformLinkService.cs +++ /dev/null @@ -1,39 +0,0 @@ -using System; -using XTwitterScraper.Core; - -namespace XTwitterScraper.Services.Bot; - -/// -/// NOTE: Do not inherit from this type outside the SDK unless you're okay with breaking -/// changes in non-major versions. We may add new methods in the future that cause -/// existing derived classes to break. -/// -public interface IPlatformLinkService -{ - /// - /// Returns a view of this service that provides access to raw HTTP responses - /// for each method. - /// - IPlatformLinkServiceWithRawResponse WithRawResponse { get; } - - /// - /// Returns a view of this service with the given option modifications applied. - /// - /// The original service is not modified. - /// - IPlatformLinkService WithOptions(Func modifier); -} - -/// -/// A view of that provides access to raw -/// HTTP responses for each method. -/// -public interface IPlatformLinkServiceWithRawResponse -{ - /// - /// Returns a view of this service with the given option modifications applied. - /// - /// The original service is not modified. - /// - IPlatformLinkServiceWithRawResponse WithOptions(Func modifier); -} diff --git a/src/XTwitterScraper/Services/Bot/PlatformLinkService.cs b/src/XTwitterScraper/Services/Bot/PlatformLinkService.cs deleted file mode 100644 index 19b159f..0000000 --- a/src/XTwitterScraper/Services/Bot/PlatformLinkService.cs +++ /dev/null @@ -1,52 +0,0 @@ -using System; -using XTwitterScraper.Core; - -namespace XTwitterScraper.Services.Bot; - -/// -public sealed class PlatformLinkService : IPlatformLinkService -{ - readonly Lazy _withRawResponse; - - /// - public IPlatformLinkServiceWithRawResponse WithRawResponse - { - get { return _withRawResponse.Value; } - } - - readonly IXTwitterScraperClient _client; - - /// - public IPlatformLinkService WithOptions(Func modifier) - { - return new PlatformLinkService(this._client.WithOptions(modifier)); - } - - public PlatformLinkService(IXTwitterScraperClient client) - { - _client = client; - - _withRawResponse = new(() => - new PlatformLinkServiceWithRawResponse(client.WithRawResponse) - ); - } -} - -/// -public sealed class PlatformLinkServiceWithRawResponse : IPlatformLinkServiceWithRawResponse -{ - readonly IXTwitterScraperClientWithRawResponse _client; - - /// - public IPlatformLinkServiceWithRawResponse WithOptions( - Func modifier - ) - { - return new PlatformLinkServiceWithRawResponse(this._client.WithOptions(modifier)); - } - - public PlatformLinkServiceWithRawResponse(IXTwitterScraperClientWithRawResponse client) - { - _client = client; - } -} diff --git a/src/XTwitterScraper/Services/BotService.cs b/src/XTwitterScraper/Services/BotService.cs deleted file mode 100644 index f9e3b84..0000000 --- a/src/XTwitterScraper/Services/BotService.cs +++ /dev/null @@ -1,64 +0,0 @@ -using System; -using XTwitterScraper.Core; -using XTwitterScraper.Services.Bot; - -namespace XTwitterScraper.Services; - -/// -public sealed class BotService : IBotService -{ - readonly Lazy _withRawResponse; - - /// - public IBotServiceWithRawResponse WithRawResponse - { - get { return _withRawResponse.Value; } - } - - readonly IXTwitterScraperClient _client; - - /// - public IBotService WithOptions(Func modifier) - { - return new BotService(this._client.WithOptions(modifier)); - } - - public BotService(IXTwitterScraperClient client) - { - _client = client; - - _withRawResponse = new(() => new BotServiceWithRawResponse(client.WithRawResponse)); - _platformLinks = new(() => new PlatformLinkService(client)); - } - - readonly Lazy _platformLinks; - public IPlatformLinkService PlatformLinks - { - get { return _platformLinks.Value; } - } -} - -/// -public sealed class BotServiceWithRawResponse : IBotServiceWithRawResponse -{ - readonly IXTwitterScraperClientWithRawResponse _client; - - /// - public IBotServiceWithRawResponse WithOptions(Func modifier) - { - return new BotServiceWithRawResponse(this._client.WithOptions(modifier)); - } - - public BotServiceWithRawResponse(IXTwitterScraperClientWithRawResponse client) - { - _client = client; - - _platformLinks = new(() => new PlatformLinkServiceWithRawResponse(client)); - } - - readonly Lazy _platformLinks; - public IPlatformLinkServiceWithRawResponse PlatformLinks - { - get { return _platformLinks.Value; } - } -} diff --git a/src/XTwitterScraper/Services/IAccountService.cs b/src/XTwitterScraper/Services/IAccountService.cs index b243a48..e463254 100644 --- a/src/XTwitterScraper/Services/IAccountService.cs +++ b/src/XTwitterScraper/Services/IAccountService.cs @@ -7,7 +7,7 @@ namespace XTwitterScraper.Services; /// -/// Account info & settings +/// Account info and settings /// /// NOTE: Do not inherit from this type outside the SDK unless you're okay with /// breaking changes in non-major versions. We may add new methods in the future that diff --git a/src/XTwitterScraper/Services/IBotService.cs b/src/XTwitterScraper/Services/IBotService.cs deleted file mode 100644 index 9843b18..0000000 --- a/src/XTwitterScraper/Services/IBotService.cs +++ /dev/null @@ -1,44 +0,0 @@ -using System; -using XTwitterScraper.Core; -using XTwitterScraper.Services.Bot; - -namespace XTwitterScraper.Services; - -/// -/// NOTE: Do not inherit from this type outside the SDK unless you're okay with breaking -/// changes in non-major versions. We may add new methods in the future that cause -/// existing derived classes to break. -/// -public interface IBotService -{ - /// - /// Returns a view of this service that provides access to raw HTTP responses - /// for each method. - /// - IBotServiceWithRawResponse WithRawResponse { get; } - - /// - /// Returns a view of this service with the given option modifications applied. - /// - /// The original service is not modified. - /// - IBotService WithOptions(Func modifier); - - IPlatformLinkService PlatformLinks { get; } -} - -/// -/// A view of that provides access to raw -/// HTTP responses for each method. -/// -public interface IBotServiceWithRawResponse -{ - /// - /// Returns a view of this service with the given option modifications applied. - /// - /// The original service is not modified. - /// - IBotServiceWithRawResponse WithOptions(Func modifier); - - IPlatformLinkServiceWithRawResponse PlatformLinks { get; } -} diff --git a/src/XTwitterScraper/Services/IComposeService.cs b/src/XTwitterScraper/Services/IComposeService.cs index 4cb0ad4..7542552 100644 --- a/src/XTwitterScraper/Services/IComposeService.cs +++ b/src/XTwitterScraper/Services/IComposeService.cs @@ -7,7 +7,7 @@ namespace XTwitterScraper.Services; /// -/// Tweet composition, drafts, writing styles & radar +/// AI tweet composition, drafts, writing styles, and radar /// /// NOTE: Do not inherit from this type outside the SDK unless you're okay with /// breaking changes in non-major versions. We may add new methods in the future that diff --git a/src/XTwitterScraper/Services/ICreditService.cs b/src/XTwitterScraper/Services/ICreditService.cs index dd40d79..b89b941 100644 --- a/src/XTwitterScraper/Services/ICreditService.cs +++ b/src/XTwitterScraper/Services/ICreditService.cs @@ -7,7 +7,7 @@ namespace XTwitterScraper.Services; /// -/// Subscription & billing +/// Subscription, billing, and credits /// /// NOTE: Do not inherit from this type outside the SDK unless you're okay with /// breaking changes in non-major versions. We may add new methods in the future that diff --git a/src/XTwitterScraper/Services/IDraftService.cs b/src/XTwitterScraper/Services/IDraftService.cs index e02b059..5be294a 100644 --- a/src/XTwitterScraper/Services/IDraftService.cs +++ b/src/XTwitterScraper/Services/IDraftService.cs @@ -7,7 +7,7 @@ namespace XTwitterScraper.Services; /// -/// Tweet composition, drafts, writing styles & radar +/// AI tweet composition, drafts, writing styles, and radar /// /// NOTE: Do not inherit from this type outside the SDK unless you're okay with /// breaking changes in non-major versions. We may add new methods in the future that diff --git a/src/XTwitterScraper/Services/IIntegrationService.cs b/src/XTwitterScraper/Services/IIntegrationService.cs deleted file mode 100644 index 6ac06c5..0000000 --- a/src/XTwitterScraper/Services/IIntegrationService.cs +++ /dev/null @@ -1,233 +0,0 @@ -using System; -using System.Threading; -using System.Threading.Tasks; -using XTwitterScraper.Core; -using XTwitterScraper.Models.Integrations; - -namespace XTwitterScraper.Services; - -/// -/// Push notification integrations (Telegram) -/// -/// NOTE: Do not inherit from this type outside the SDK unless you're okay with -/// breaking changes in non-major versions. We may add new methods in the future that -/// cause existing derived classes to break. -/// -public interface IIntegrationService -{ - /// - /// Returns a view of this service that provides access to raw HTTP responses - /// for each method. - /// - IIntegrationServiceWithRawResponse WithRawResponse { get; } - - /// - /// Returns a view of this service with the given option modifications applied. - /// - /// The original service is not modified. - /// - IIntegrationService WithOptions(Func modifier); - - /// - /// Create integration - /// - Task Create( - IntegrationCreateParams parameters, - CancellationToken cancellationToken = default - ); - - /// - /// Get integration details - /// - Task Retrieve( - IntegrationRetrieveParams parameters, - CancellationToken cancellationToken = default - ); - - /// - Task Retrieve( - string id, - IntegrationRetrieveParams? parameters = null, - CancellationToken cancellationToken = default - ); - - /// - /// Update integration - /// - Task Update( - IntegrationUpdateParams parameters, - CancellationToken cancellationToken = default - ); - - /// - Task Update( - string id, - IntegrationUpdateParams? parameters = null, - CancellationToken cancellationToken = default - ); - - /// - /// List integrations - /// - Task List( - IntegrationListParams? parameters = null, - CancellationToken cancellationToken = default - ); - - /// - /// Delete integration - /// - Task Delete( - IntegrationDeleteParams parameters, - CancellationToken cancellationToken = default - ); - - /// - Task Delete( - string id, - IntegrationDeleteParams? parameters = null, - CancellationToken cancellationToken = default - ); - - /// - /// List integration delivery history - /// - Task ListDeliveries( - IntegrationListDeliveriesParams parameters, - CancellationToken cancellationToken = default - ); - - /// - Task ListDeliveries( - string id, - IntegrationListDeliveriesParams? parameters = null, - CancellationToken cancellationToken = default - ); - - /// - /// Send test delivery - /// - Task SendTest( - IntegrationSendTestParams parameters, - CancellationToken cancellationToken = default - ); - - /// - Task SendTest( - string id, - IntegrationSendTestParams? parameters = null, - CancellationToken cancellationToken = default - ); -} - -/// -/// A view of that provides access to raw -/// HTTP responses for each method. -/// -public interface IIntegrationServiceWithRawResponse -{ - /// - /// Returns a view of this service with the given option modifications applied. - /// - /// The original service is not modified. - /// - IIntegrationServiceWithRawResponse WithOptions(Func modifier); - - /// - /// Returns a raw HTTP response for post /integrations, but is otherwise the - /// same as . - /// - Task> Create( - IntegrationCreateParams parameters, - CancellationToken cancellationToken = default - ); - - /// - /// Returns a raw HTTP response for get /integrations/{id}, but is otherwise the - /// same as . - /// - Task> Retrieve( - IntegrationRetrieveParams parameters, - CancellationToken cancellationToken = default - ); - - /// - Task> Retrieve( - string id, - IntegrationRetrieveParams? parameters = null, - CancellationToken cancellationToken = default - ); - - /// - /// Returns a raw HTTP response for patch /integrations/{id}, but is otherwise the - /// same as . - /// - Task> Update( - IntegrationUpdateParams parameters, - CancellationToken cancellationToken = default - ); - - /// - Task> Update( - string id, - IntegrationUpdateParams? parameters = null, - CancellationToken cancellationToken = default - ); - - /// - /// Returns a raw HTTP response for get /integrations, but is otherwise the - /// same as . - /// - Task> List( - IntegrationListParams? parameters = null, - CancellationToken cancellationToken = default - ); - - /// - /// Returns a raw HTTP response for delete /integrations/{id}, but is otherwise the - /// same as . - /// - Task> Delete( - IntegrationDeleteParams parameters, - CancellationToken cancellationToken = default - ); - - /// - Task> Delete( - string id, - IntegrationDeleteParams? parameters = null, - CancellationToken cancellationToken = default - ); - - /// - /// Returns a raw HTTP response for get /integrations/{id}/deliveries, but is otherwise the - /// same as . - /// - Task> ListDeliveries( - IntegrationListDeliveriesParams parameters, - CancellationToken cancellationToken = default - ); - - /// - Task> ListDeliveries( - string id, - IntegrationListDeliveriesParams? parameters = null, - CancellationToken cancellationToken = default - ); - - /// - /// Returns a raw HTTP response for post /integrations/{id}/test, but is otherwise the - /// same as . - /// - Task> SendTest( - IntegrationSendTestParams parameters, - CancellationToken cancellationToken = default - ); - - /// - Task> SendTest( - string id, - IntegrationSendTestParams? parameters = null, - CancellationToken cancellationToken = default - ); -} diff --git a/src/XTwitterScraper/Services/IRadarService.cs b/src/XTwitterScraper/Services/IRadarService.cs index 755bbf5..aab4dc6 100644 --- a/src/XTwitterScraper/Services/IRadarService.cs +++ b/src/XTwitterScraper/Services/IRadarService.cs @@ -7,7 +7,7 @@ namespace XTwitterScraper.Services; /// -/// Tweet composition, drafts, writing styles & radar +/// AI tweet composition, drafts, writing styles, and radar /// /// NOTE: Do not inherit from this type outside the SDK unless you're okay with /// breaking changes in non-major versions. We may add new methods in the future that diff --git a/src/XTwitterScraper/Services/IStyleService.cs b/src/XTwitterScraper/Services/IStyleService.cs index f82ee12..f3495a9 100644 --- a/src/XTwitterScraper/Services/IStyleService.cs +++ b/src/XTwitterScraper/Services/IStyleService.cs @@ -7,7 +7,7 @@ namespace XTwitterScraper.Services; /// -/// Tweet composition, drafts, writing styles & radar +/// AI tweet composition, drafts, writing styles, and radar /// /// NOTE: Do not inherit from this type outside the SDK unless you're okay with /// breaking changes in non-major versions. We may add new methods in the future that diff --git a/src/XTwitterScraper/Services/ISubscribeService.cs b/src/XTwitterScraper/Services/ISubscribeService.cs index 7f9a3ad..97e320d 100644 --- a/src/XTwitterScraper/Services/ISubscribeService.cs +++ b/src/XTwitterScraper/Services/ISubscribeService.cs @@ -7,7 +7,7 @@ namespace XTwitterScraper.Services; /// -/// Subscription & billing +/// Subscription, billing, and credits /// /// NOTE: Do not inherit from this type outside the SDK unless you're okay with /// breaking changes in non-major versions. We may add new methods in the future that diff --git a/src/XTwitterScraper/Services/ITrendService.cs b/src/XTwitterScraper/Services/ITrendService.cs index 96b15e3..b4436c8 100644 --- a/src/XTwitterScraper/Services/ITrendService.cs +++ b/src/XTwitterScraper/Services/ITrendService.cs @@ -7,7 +7,7 @@ namespace XTwitterScraper.Services; /// -/// Trending topics by region +/// Trending topics and hashtags by region /// /// NOTE: Do not inherit from this type outside the SDK unless you're okay with /// breaking changes in non-major versions. We may add new methods in the future that @@ -29,7 +29,7 @@ public interface ITrendService ITrendService WithOptions(Func modifier); /// - /// Get regional trending topics + /// Get trending hashtags & topics by region (alias) /// Task List( TrendListParams? parameters = null, diff --git a/src/XTwitterScraper/Services/IWebhookService.cs b/src/XTwitterScraper/Services/IWebhookService.cs index 8fcb495..33b2149 100644 --- a/src/XTwitterScraper/Services/IWebhookService.cs +++ b/src/XTwitterScraper/Services/IWebhookService.cs @@ -7,7 +7,7 @@ namespace XTwitterScraper.Services; /// -/// Webhook endpoint management & delivery +/// Webhook endpoint management and delivery /// /// NOTE: Do not inherit from this type outside the SDK unless you're okay with /// breaking changes in non-major versions. We may add new methods in the future that diff --git a/src/XTwitterScraper/Services/IXService.cs b/src/XTwitterScraper/Services/IXService.cs index df622b0..f6ffc5d 100644 --- a/src/XTwitterScraper/Services/IXService.cs +++ b/src/XTwitterScraper/Services/IXService.cs @@ -9,11 +9,9 @@ namespace XTwitterScraper.Services; /// -/// X data lookups (subscription required) -/// -/// NOTE: Do not inherit from this type outside the SDK unless you're okay with -/// breaking changes in non-major versions. We may add new methods in the future that -/// cause existing derived classes to break. +/// NOTE: Do not inherit from this type outside the SDK unless you're okay with breaking +/// changes in non-major versions. We may add new methods in the future that cause +/// existing derived classes to break. /// public interface IXService { @@ -82,7 +80,7 @@ Task GetNotifications( ); /// - /// Get trending topics + /// Get trending hashtags & topics from X by region /// Task GetTrends( XGetTrendsParams? parameters = null, diff --git a/src/XTwitterScraper/Services/IntegrationService.cs b/src/XTwitterScraper/Services/IntegrationService.cs deleted file mode 100644 index 9ee6a7f..0000000 --- a/src/XTwitterScraper/Services/IntegrationService.cs +++ /dev/null @@ -1,482 +0,0 @@ -using System; -using System.Net.Http; -using System.Threading; -using System.Threading.Tasks; -using XTwitterScraper.Core; -using XTwitterScraper.Exceptions; -using XTwitterScraper.Models.Integrations; - -namespace XTwitterScraper.Services; - -/// -public sealed class IntegrationService : IIntegrationService -{ - readonly Lazy _withRawResponse; - - /// - public IIntegrationServiceWithRawResponse WithRawResponse - { - get { return _withRawResponse.Value; } - } - - readonly IXTwitterScraperClient _client; - - /// - public IIntegrationService WithOptions(Func modifier) - { - return new IntegrationService(this._client.WithOptions(modifier)); - } - - public IntegrationService(IXTwitterScraperClient client) - { - _client = client; - - _withRawResponse = new(() => new IntegrationServiceWithRawResponse(client.WithRawResponse)); - } - - /// - public async Task Create( - IntegrationCreateParams parameters, - CancellationToken cancellationToken = default - ) - { - using var response = await this - .WithRawResponse.Create(parameters, cancellationToken) - .ConfigureAwait(false); - return await response.Deserialize(cancellationToken).ConfigureAwait(false); - } - - /// - public async Task Retrieve( - IntegrationRetrieveParams parameters, - CancellationToken cancellationToken = default - ) - { - using var response = await this - .WithRawResponse.Retrieve(parameters, cancellationToken) - .ConfigureAwait(false); - return await response.Deserialize(cancellationToken).ConfigureAwait(false); - } - - /// - public Task Retrieve( - string id, - IntegrationRetrieveParams? parameters = null, - CancellationToken cancellationToken = default - ) - { - parameters ??= new(); - - return this.Retrieve(parameters with { ID = id }, cancellationToken); - } - - /// - public async Task Update( - IntegrationUpdateParams parameters, - CancellationToken cancellationToken = default - ) - { - using var response = await this - .WithRawResponse.Update(parameters, cancellationToken) - .ConfigureAwait(false); - return await response.Deserialize(cancellationToken).ConfigureAwait(false); - } - - /// - public Task Update( - string id, - IntegrationUpdateParams? parameters = null, - CancellationToken cancellationToken = default - ) - { - parameters ??= new(); - - return this.Update(parameters with { ID = id }, cancellationToken); - } - - /// - public async Task List( - IntegrationListParams? parameters = null, - CancellationToken cancellationToken = default - ) - { - using var response = await this - .WithRawResponse.List(parameters, cancellationToken) - .ConfigureAwait(false); - return await response.Deserialize(cancellationToken).ConfigureAwait(false); - } - - /// - public async Task Delete( - IntegrationDeleteParams parameters, - CancellationToken cancellationToken = default - ) - { - using var response = await this - .WithRawResponse.Delete(parameters, cancellationToken) - .ConfigureAwait(false); - return await response.Deserialize(cancellationToken).ConfigureAwait(false); - } - - /// - public Task Delete( - string id, - IntegrationDeleteParams? parameters = null, - CancellationToken cancellationToken = default - ) - { - parameters ??= new(); - - return this.Delete(parameters with { ID = id }, cancellationToken); - } - - /// - public async Task ListDeliveries( - IntegrationListDeliveriesParams parameters, - CancellationToken cancellationToken = default - ) - { - using var response = await this - .WithRawResponse.ListDeliveries(parameters, cancellationToken) - .ConfigureAwait(false); - return await response.Deserialize(cancellationToken).ConfigureAwait(false); - } - - /// - public Task ListDeliveries( - string id, - IntegrationListDeliveriesParams? parameters = null, - CancellationToken cancellationToken = default - ) - { - parameters ??= new(); - - return this.ListDeliveries(parameters with { ID = id }, cancellationToken); - } - - /// - public async Task SendTest( - IntegrationSendTestParams parameters, - CancellationToken cancellationToken = default - ) - { - using var response = await this - .WithRawResponse.SendTest(parameters, cancellationToken) - .ConfigureAwait(false); - return await response.Deserialize(cancellationToken).ConfigureAwait(false); - } - - /// - public Task SendTest( - string id, - IntegrationSendTestParams? parameters = null, - CancellationToken cancellationToken = default - ) - { - parameters ??= new(); - - return this.SendTest(parameters with { ID = id }, cancellationToken); - } -} - -/// -public sealed class IntegrationServiceWithRawResponse : IIntegrationServiceWithRawResponse -{ - readonly IXTwitterScraperClientWithRawResponse _client; - - /// - public IIntegrationServiceWithRawResponse WithOptions( - Func modifier - ) - { - return new IntegrationServiceWithRawResponse(this._client.WithOptions(modifier)); - } - - public IntegrationServiceWithRawResponse(IXTwitterScraperClientWithRawResponse client) - { - _client = client; - } - - /// - public async Task> Create( - IntegrationCreateParams parameters, - CancellationToken cancellationToken = default - ) - { - HttpRequest request = new() - { - Method = HttpMethod.Post, - Params = parameters, - }; - var response = await this._client.Execute(request, cancellationToken).ConfigureAwait(false); - return new( - response, - async (token) => - { - var integration = await response - .Deserialize(token) - .ConfigureAwait(false); - if (this._client.ResponseValidation) - { - integration.Validate(); - } - return integration; - } - ); - } - - /// - public async Task> Retrieve( - IntegrationRetrieveParams parameters, - CancellationToken cancellationToken = default - ) - { - if (parameters.ID == null) - { - throw new XTwitterScraperInvalidDataException("'parameters.ID' cannot be null"); - } - - HttpRequest request = new() - { - Method = HttpMethod.Get, - Params = parameters, - }; - var response = await this._client.Execute(request, cancellationToken).ConfigureAwait(false); - return new( - response, - async (token) => - { - var integration = await response - .Deserialize(token) - .ConfigureAwait(false); - if (this._client.ResponseValidation) - { - integration.Validate(); - } - return integration; - } - ); - } - - /// - public Task> Retrieve( - string id, - IntegrationRetrieveParams? parameters = null, - CancellationToken cancellationToken = default - ) - { - parameters ??= new(); - - return this.Retrieve(parameters with { ID = id }, cancellationToken); - } - - /// - public async Task> Update( - IntegrationUpdateParams parameters, - CancellationToken cancellationToken = default - ) - { - if (parameters.ID == null) - { - throw new XTwitterScraperInvalidDataException("'parameters.ID' cannot be null"); - } - - HttpRequest request = new() - { - Method = XTwitterScraperClientWithRawResponse.PatchMethod, - Params = parameters, - }; - var response = await this._client.Execute(request, cancellationToken).ConfigureAwait(false); - return new( - response, - async (token) => - { - var integration = await response - .Deserialize(token) - .ConfigureAwait(false); - if (this._client.ResponseValidation) - { - integration.Validate(); - } - return integration; - } - ); - } - - /// - public Task> Update( - string id, - IntegrationUpdateParams? parameters = null, - CancellationToken cancellationToken = default - ) - { - parameters ??= new(); - - return this.Update(parameters with { ID = id }, cancellationToken); - } - - /// - public async Task> List( - IntegrationListParams? parameters = null, - CancellationToken cancellationToken = default - ) - { - parameters ??= new(); - - HttpRequest request = new() - { - Method = HttpMethod.Get, - Params = parameters, - }; - var response = await this._client.Execute(request, cancellationToken).ConfigureAwait(false); - return new( - response, - async (token) => - { - var integrations = await response - .Deserialize(token) - .ConfigureAwait(false); - if (this._client.ResponseValidation) - { - integrations.Validate(); - } - return integrations; - } - ); - } - - /// - public async Task> Delete( - IntegrationDeleteParams parameters, - CancellationToken cancellationToken = default - ) - { - if (parameters.ID == null) - { - throw new XTwitterScraperInvalidDataException("'parameters.ID' cannot be null"); - } - - HttpRequest request = new() - { - Method = HttpMethod.Delete, - Params = parameters, - }; - var response = await this._client.Execute(request, cancellationToken).ConfigureAwait(false); - return new( - response, - async (token) => - { - var integration = await response - .Deserialize(token) - .ConfigureAwait(false); - if (this._client.ResponseValidation) - { - integration.Validate(); - } - return integration; - } - ); - } - - /// - public Task> Delete( - string id, - IntegrationDeleteParams? parameters = null, - CancellationToken cancellationToken = default - ) - { - parameters ??= new(); - - return this.Delete(parameters with { ID = id }, cancellationToken); - } - - /// - public async Task> ListDeliveries( - IntegrationListDeliveriesParams parameters, - CancellationToken cancellationToken = default - ) - { - if (parameters.ID == null) - { - throw new XTwitterScraperInvalidDataException("'parameters.ID' cannot be null"); - } - - HttpRequest request = new() - { - Method = HttpMethod.Get, - Params = parameters, - }; - var response = await this._client.Execute(request, cancellationToken).ConfigureAwait(false); - return new( - response, - async (token) => - { - var deserializedResponse = await response - .Deserialize(token) - .ConfigureAwait(false); - if (this._client.ResponseValidation) - { - deserializedResponse.Validate(); - } - return deserializedResponse; - } - ); - } - - /// - public Task> ListDeliveries( - string id, - IntegrationListDeliveriesParams? parameters = null, - CancellationToken cancellationToken = default - ) - { - parameters ??= new(); - - return this.ListDeliveries(parameters with { ID = id }, cancellationToken); - } - - /// - public async Task> SendTest( - IntegrationSendTestParams parameters, - CancellationToken cancellationToken = default - ) - { - if (parameters.ID == null) - { - throw new XTwitterScraperInvalidDataException("'parameters.ID' cannot be null"); - } - - HttpRequest request = new() - { - Method = HttpMethod.Post, - Params = parameters, - }; - var response = await this._client.Execute(request, cancellationToken).ConfigureAwait(false); - return new( - response, - async (token) => - { - var deserializedResponse = await response - .Deserialize(token) - .ConfigureAwait(false); - if (this._client.ResponseValidation) - { - deserializedResponse.Validate(); - } - return deserializedResponse; - } - ); - } - - /// - public Task> SendTest( - string id, - IntegrationSendTestParams? parameters = null, - CancellationToken cancellationToken = default - ) - { - parameters ??= new(); - - return this.SendTest(parameters with { ID = id }, cancellationToken); - } -} diff --git a/src/XTwitterScraper/Services/X/Communities/ITweetService.cs b/src/XTwitterScraper/Services/X/Communities/ITweetService.cs index ef6bd2f..4547b91 100644 --- a/src/XTwitterScraper/Services/X/Communities/ITweetService.cs +++ b/src/XTwitterScraper/Services/X/Communities/ITweetService.cs @@ -8,7 +8,7 @@ namespace XTwitterScraper.Services.X.Communities; /// -/// X data lookups (subscription required) +/// X Community info, members, and tweets /// /// NOTE: Do not inherit from this type outside the SDK unless you're okay with /// breaking changes in non-major versions. We may add new methods in the future that @@ -30,7 +30,7 @@ public interface ITweetService ITweetService WithOptions(Func modifier); /// - /// Search tweets across all communities + /// List tweets across all communities /// Task List( TweetListParams parameters, @@ -38,7 +38,7 @@ Task List( ); /// - /// Get community tweets + /// List tweets posted in a community /// Task ListByCommunity( TweetListByCommunityParams parameters, diff --git a/src/XTwitterScraper/Services/X/IBookmarkService.cs b/src/XTwitterScraper/Services/X/IBookmarkService.cs index 09e7932..273040a 100644 --- a/src/XTwitterScraper/Services/X/IBookmarkService.cs +++ b/src/XTwitterScraper/Services/X/IBookmarkService.cs @@ -8,7 +8,7 @@ namespace XTwitterScraper.Services.X; /// -/// X data lookups (subscription required) +/// Look up, search, and analyze individual tweets /// /// NOTE: Do not inherit from this type outside the SDK unless you're okay with /// breaking changes in non-major versions. We may add new methods in the future that diff --git a/src/XTwitterScraper/Services/X/ICommunityService.cs b/src/XTwitterScraper/Services/X/ICommunityService.cs index c29eb60..2448633 100644 --- a/src/XTwitterScraper/Services/X/ICommunityService.cs +++ b/src/XTwitterScraper/Services/X/ICommunityService.cs @@ -56,7 +56,7 @@ Task Delete( ); /// - /// Get community details + /// Get community name, description & member count /// Task RetrieveInfo( CommunityRetrieveInfoParams parameters, @@ -71,7 +71,7 @@ Task RetrieveInfo( ); /// - /// Get community members + /// List members of a community /// Task RetrieveMembers( CommunityRetrieveMembersParams parameters, @@ -86,7 +86,7 @@ Task RetrieveMembers( ); /// - /// Get community moderators + /// List moderators of a community /// Task RetrieveModerators( CommunityRetrieveModeratorsParams parameters, @@ -101,7 +101,7 @@ Task RetrieveModerators( ); /// - /// Search tweets across communities + /// Search for communities by keyword /// Task RetrieveSearch( CommunityRetrieveSearchParams parameters, diff --git a/src/XTwitterScraper/Services/X/IFollowerService.cs b/src/XTwitterScraper/Services/X/IFollowerService.cs index 049d816..34f648a 100644 --- a/src/XTwitterScraper/Services/X/IFollowerService.cs +++ b/src/XTwitterScraper/Services/X/IFollowerService.cs @@ -7,7 +7,7 @@ namespace XTwitterScraper.Services.X; /// -/// X data lookups (subscription required) +/// Look up, search, and explore user profiles and relationships /// /// NOTE: Do not inherit from this type outside the SDK unless you're okay with /// breaking changes in non-major versions. We may add new methods in the future that @@ -29,7 +29,7 @@ public interface IFollowerService IFollowerService WithOptions(Func modifier); /// - /// Check follow relationship + /// Check if one user follows another /// Task Check( FollowerCheckParams parameters, diff --git a/src/XTwitterScraper/Services/X/IListService.cs b/src/XTwitterScraper/Services/X/IListService.cs index f1533ab..4406ed6 100644 --- a/src/XTwitterScraper/Services/X/IListService.cs +++ b/src/XTwitterScraper/Services/X/IListService.cs @@ -8,7 +8,7 @@ namespace XTwitterScraper.Services.X; /// -/// X data lookups (subscription required) +/// X List followers, members, and tweets /// /// NOTE: Do not inherit from this type outside the SDK unless you're okay with /// breaking changes in non-major versions. We may add new methods in the future that @@ -30,7 +30,7 @@ public interface IListService IListService WithOptions(Func modifier); /// - /// Get list followers + /// List followers of an X List /// Task RetrieveFollowers( ListRetrieveFollowersParams parameters, @@ -45,7 +45,7 @@ Task RetrieveFollowers( ); /// - /// Get list members + /// List members of an X List /// Task RetrieveMembers( ListRetrieveMembersParams parameters, @@ -60,7 +60,7 @@ Task RetrieveMembers( ); /// - /// Get list tweets + /// List tweets from an X List /// Task RetrieveTweets( ListRetrieveTweetsParams parameters, diff --git a/src/XTwitterScraper/Services/X/IMediaService.cs b/src/XTwitterScraper/Services/X/IMediaService.cs index 55b734b..15a1281 100644 --- a/src/XTwitterScraper/Services/X/IMediaService.cs +++ b/src/XTwitterScraper/Services/X/IMediaService.cs @@ -7,7 +7,7 @@ namespace XTwitterScraper.Services.X; /// -/// Media upload & download +/// Media upload and download /// /// NOTE: Do not inherit from this type outside the SDK unless you're okay with /// breaking changes in non-major versions. We may add new methods in the future that @@ -29,7 +29,7 @@ public interface IMediaService IMediaService WithOptions(Func modifier); /// - /// Download tweet media + /// Download images & videos from tweets /// Task Download( MediaDownloadParams? parameters = null, diff --git a/src/XTwitterScraper/Services/X/ITweetService.cs b/src/XTwitterScraper/Services/X/ITweetService.cs index 4a7e639..642253a 100644 --- a/src/XTwitterScraper/Services/X/ITweetService.cs +++ b/src/XTwitterScraper/Services/X/ITweetService.cs @@ -41,7 +41,7 @@ Task Create( ); /// - /// Look up tweet + /// Get tweet with full text, author, metrics & media /// Task Retrieve( TweetRetrieveParams parameters, @@ -79,7 +79,7 @@ Task Delete( ); /// - /// Get users who liked a tweet + /// List users who liked a tweet /// Task GetFavoriters( TweetGetFavoritersParams parameters, @@ -94,7 +94,7 @@ Task GetFavoriters( ); /// - /// Get quote tweets of a tweet + /// List quote tweets of a tweet /// Task GetQuotes( TweetGetQuotesParams parameters, @@ -109,7 +109,7 @@ Task GetQuotes( ); /// - /// Get replies to a tweet + /// List replies to a tweet /// Task GetReplies( TweetGetRepliesParams parameters, @@ -124,7 +124,7 @@ Task GetReplies( ); /// - /// Get users who retweeted a tweet + /// List users who retweeted a tweet /// Task GetRetweeters( TweetGetRetweetersParams parameters, @@ -139,7 +139,7 @@ Task GetRetweeters( ); /// - /// Get thread context for a tweet + /// Get full conversation thread for a tweet /// Task GetThread( TweetGetThreadParams parameters, @@ -154,7 +154,7 @@ Task GetThread( ); /// - /// Search tweets + /// Search tweets with X query operators & pagination /// Task Search( TweetSearchParams parameters, diff --git a/src/XTwitterScraper/Services/X/IUserService.cs b/src/XTwitterScraper/Services/X/IUserService.cs index 0c0ece9..310a2a6 100644 --- a/src/XTwitterScraper/Services/X/IUserService.cs +++ b/src/XTwitterScraper/Services/X/IUserService.cs @@ -9,7 +9,7 @@ namespace XTwitterScraper.Services.X; /// -/// X data lookups (subscription required) +/// Look up, search, and explore user profiles and relationships /// /// NOTE: Do not inherit from this type outside the SDK unless you're okay with /// breaking changes in non-major versions. We may add new methods in the future that @@ -33,7 +33,7 @@ public interface IUserService IFollowService Follow { get; } /// - /// Look up X user + /// Get user profile with follower counts & verification /// Task Retrieve( UserRetrieveParams parameters, @@ -48,7 +48,7 @@ Task Retrieve( ); /// - /// Get multiple users by IDs + /// Look up multiple users by IDs in one call /// Task RetrieveBatch( UserRetrieveBatchParams parameters, @@ -56,7 +56,7 @@ Task RetrieveBatch( ); /// - /// Get user followers + /// List followers of a user /// Task RetrieveFollowers( UserRetrieveFollowersParams parameters, @@ -71,7 +71,7 @@ Task RetrieveFollowers( ); /// - /// Get followers you know for a user + /// List mutual followers between you and a user /// Task RetrieveFollowersYouKnow( UserRetrieveFollowersYouKnowParams parameters, @@ -86,7 +86,7 @@ Task RetrieveFollowersYouKnow( ); /// - /// Get users this user follows + /// List accounts a user follows /// Task RetrieveFollowing( UserRetrieveFollowingParams parameters, @@ -101,7 +101,7 @@ Task RetrieveFollowing( ); /// - /// Get tweets liked by a user + /// List tweets liked by a user /// Task RetrieveLikes( UserRetrieveLikesParams parameters, @@ -116,7 +116,7 @@ Task RetrieveLikes( ); /// - /// Get media tweets by a user + /// List media tweets posted by a user /// Task RetrieveMedia( UserRetrieveMediaParams parameters, @@ -131,7 +131,7 @@ Task RetrieveMedia( ); /// - /// Get tweets mentioning a user + /// List tweets mentioning a user /// Task RetrieveMentions( UserRetrieveMentionsParams parameters, @@ -154,7 +154,7 @@ Task RetrieveSearch( ); /// - /// Get recent tweets by a user + /// List recent tweets posted by a user /// Task RetrieveTweets( UserRetrieveTweetsParams parameters, @@ -169,7 +169,7 @@ Task RetrieveTweets( ); /// - /// Get verified followers + /// List verified followers of a user /// Task RetrieveVerifiedFollowers( UserRetrieveVerifiedFollowersParams parameters, diff --git a/src/XTwitterScraper/XTwitterScraper.csproj b/src/XTwitterScraper/XTwitterScraper.csproj index 3738abf..e2e9e8b 100644 --- a/src/XTwitterScraper/XTwitterScraper.csproj +++ b/src/XTwitterScraper/XTwitterScraper.csproj @@ -3,7 +3,7 @@ X Twitter Scraper C# XTwitterScraper - 0.3.0 + 0.4.0 The official .NET library for the X Twitter Scraper API. Library README.md diff --git a/src/XTwitterScraper/XTwitterScraperClient.cs b/src/XTwitterScraper/XTwitterScraperClient.cs index 9eedefa..458c0c8 100644 --- a/src/XTwitterScraper/XTwitterScraperClient.cs +++ b/src/XTwitterScraper/XTwitterScraperClient.cs @@ -151,12 +151,6 @@ public IWebhookService Webhooks get { return _webhooks.Value; } } - readonly Lazy _integrations; - public IIntegrationService Integrations - { - get { return _integrations.Value; } - } - readonly Lazy _x; public IXService X { @@ -169,12 +163,6 @@ public ITrendService Trends get { return _trends.Value; } } - readonly Lazy _bot; - public IBotService Bot - { - get { return _bot.Value; } - } - readonly Lazy _support; public ISupportService Support { @@ -206,10 +194,8 @@ public XTwitterScraperClient() _extractions = new(() => new ExtractionService(this)); _draws = new(() => new DrawService(this)); _webhooks = new(() => new WebhookService(this)); - _integrations = new(() => new IntegrationService(this)); _x = new(() => new XService(this)); _trends = new(() => new TrendService(this)); - _bot = new(() => new BotService(this)); _support = new(() => new SupportService(this)); _credits = new(() => new CreditService(this)); } @@ -368,12 +354,6 @@ public IWebhookServiceWithRawResponse Webhooks get { return _webhooks.Value; } } - readonly Lazy _integrations; - public IIntegrationServiceWithRawResponse Integrations - { - get { return _integrations.Value; } - } - readonly Lazy _x; public IXServiceWithRawResponse X { @@ -386,12 +366,6 @@ public ITrendServiceWithRawResponse Trends get { return _trends.Value; } } - readonly Lazy _bot; - public IBotServiceWithRawResponse Bot - { - get { return _bot.Value; } - } - readonly Lazy _support; public ISupportServiceWithRawResponse Support { @@ -614,10 +588,8 @@ public XTwitterScraperClientWithRawResponse() _extractions = new(() => new ExtractionServiceWithRawResponse(this)); _draws = new(() => new DrawServiceWithRawResponse(this)); _webhooks = new(() => new WebhookServiceWithRawResponse(this)); - _integrations = new(() => new IntegrationServiceWithRawResponse(this)); _x = new(() => new XServiceWithRawResponse(this)); _trends = new(() => new TrendServiceWithRawResponse(this)); - _bot = new(() => new BotServiceWithRawResponse(this)); _support = new(() => new SupportServiceWithRawResponse(this)); _credits = new(() => new CreditServiceWithRawResponse(this)); }