diff --git a/.config/dotnet-tools.json b/.config/dotnet-tools.json new file mode 100644 index 00000000..b9f69412 --- /dev/null +++ b/.config/dotnet-tools.json @@ -0,0 +1,13 @@ +{ + "version": 1, + "isRoot": true, + "tools": { + "csharpier": { + "version": "1.0.1", + "commands": [ + "csharpier" + ], + "rollForward": false + } + } +} \ No newline at end of file diff --git a/.editorconfig b/.editorconfig index 31f2b2a1..4287b5b4 100644 --- a/.editorconfig +++ b/.editorconfig @@ -1,229 +1,26 @@ -[*.cs] +root = true -# SA1600: Elements should be documented -dotnet_diagnostic.SA1600.severity = none +# All files +[*] +indent_style = space -# SA1117: Parameters should be on same line or separate lines -dotnet_diagnostic.SA1117.severity = none - -# SA1614: Element parameter documentation should have text -dotnet_diagnostic.SA1614.severity = none - -# SA1606: Element documentation should have summary text -dotnet_diagnostic.SA1606.severity = none - -# SA1402: File may only contain a single type -dotnet_diagnostic.SA1402.severity = none +# Xml files +[*.xml] +indent_size = 2 +# C# files [*.cs] -#### Naming styles #### - -# Naming rules - -dotnet_naming_rule.interface_should_be_begins_with_i.severity = warning -dotnet_naming_rule.interface_should_be_begins_with_i.symbols = interface -dotnet_naming_rule.interface_should_be_begins_with_i.style = begins_with_i - -dotnet_naming_rule.types_should_be_pascal_case.severity = warning -dotnet_naming_rule.types_should_be_pascal_case.symbols = types -dotnet_naming_rule.types_should_be_pascal_case.style = pascal_case - -dotnet_naming_rule.non_field_members_should_be_pascal_case.severity = warning -dotnet_naming_rule.non_field_members_should_be_pascal_case.symbols = non_field_members -dotnet_naming_rule.non_field_members_should_be_pascal_case.style = pascal_case - -# Symbol specifications - -dotnet_naming_symbols.interface.applicable_kinds = interface -dotnet_naming_symbols.interface.applicable_accessibilities = public, internal, private, protected, protected_internal, private_protected -dotnet_naming_symbols.interface.required_modifiers = - -dotnet_naming_symbols.types.applicable_kinds = class, struct, interface, enum -dotnet_naming_symbols.types.applicable_accessibilities = public, internal, private, protected, protected_internal, private_protected -dotnet_naming_symbols.types.required_modifiers = - -dotnet_naming_symbols.non_field_members.applicable_kinds = property, event, method -dotnet_naming_symbols.non_field_members.applicable_accessibilities = public, internal, private, protected, protected_internal, private_protected -dotnet_naming_symbols.non_field_members.required_modifiers = - -# Naming styles - -dotnet_naming_style.begins_with_i.required_prefix = I -dotnet_naming_style.begins_with_i.required_suffix = -dotnet_naming_style.begins_with_i.word_separator = -dotnet_naming_style.begins_with_i.capitalization = pascal_case - -dotnet_naming_style.pascal_case.required_prefix = -dotnet_naming_style.pascal_case.required_suffix = -dotnet_naming_style.pascal_case.word_separator = -dotnet_naming_style.pascal_case.capitalization = pascal_case - -dotnet_naming_style.pascal_case.required_prefix = -dotnet_naming_style.pascal_case.required_suffix = -dotnet_naming_style.pascal_case.word_separator = -dotnet_naming_style.pascal_case.capitalization = pascal_case -csharp_using_directive_placement = outside_namespace:silent -csharp_prefer_simple_using_statement = true:suggestion -csharp_prefer_braces = true:silent -csharp_style_namespace_declarations = block_scoped:silent -csharp_style_prefer_method_group_conversion = true:silent -csharp_style_expression_bodied_methods = false:silent -csharp_style_expression_bodied_constructors = false:silent -csharp_style_expression_bodied_operators = false:silent -csharp_style_expression_bodied_properties = true:silent -csharp_style_expression_bodied_indexers = true:silent -csharp_style_expression_bodied_accessors = true:silent -csharp_style_expression_bodied_lambdas = true:silent -csharp_style_expression_bodied_local_functions = false:silent -csharp_indent_labels = one_less_than_current -csharp_space_around_binary_operators = before_and_after -csharp_style_throw_expression = true:suggestion -csharp_style_prefer_null_check_over_type_check = true:suggestion -csharp_prefer_simple_default_expression = true:suggestion -csharp_style_prefer_local_over_anonymous_function = true:suggestion -csharp_style_prefer_index_operator = true:suggestion -csharp_style_prefer_range_operator = true:suggestion -csharp_style_implicit_object_creation_when_type_is_apparent = true:suggestion -csharp_style_prefer_tuple_swap = true:suggestion -csharp_style_inlined_variable_declaration = true:suggestion -csharp_style_deconstructed_variable_declaration = true:suggestion -csharp_style_unused_value_assignment_preference = discard_variable:suggestion -csharp_style_unused_value_expression_statement_preference = discard_variable:silent -csharp_prefer_static_local_function = true:suggestion -csharp_style_allow_embedded_statements_on_same_line_experimental = true:silent -csharp_style_allow_blank_lines_between_consecutive_braces_experimental = true:silent -csharp_style_allow_blank_line_after_colon_in_constructor_initializer_experimental = true:silent -csharp_style_conditional_delegate_call = true:suggestion -csharp_style_prefer_parameter_null_checking = true:suggestion -csharp_style_prefer_switch_expression = true:suggestion -csharp_style_prefer_pattern_matching = true:silent -csharp_style_pattern_matching_over_is_with_cast_check = true:suggestion -csharp_style_pattern_matching_over_as_with_null_check = true:suggestion -csharp_style_prefer_not_pattern = true:suggestion -csharp_style_prefer_extended_property_pattern = true:suggestion -csharp_style_var_for_built_in_types = false:none -csharp_style_var_when_type_is_apparent = false:none -csharp_style_var_elsewhere = false:none - -# CS8632: The annotation for nullable reference types should only be used in code within a '#nullable' annotations context. -dotnet_diagnostic.CS8632.severity = none - -# SA1310: Field names should not contain underscore -dotnet_diagnostic.SA1310.severity = none - -# IDE0051: Remove unused private members -dotnet_diagnostic.IDE0051.severity = none - -# SA1300: Element should begin with upper-case letter -dotnet_diagnostic.SA1300.severity = none - -# IDE1006: Naming Styles -dotnet_diagnostic.IDE1006.severity = none - -# SA1307: Accessible fields should begin with upper-case letter -dotnet_diagnostic.SA1307.severity = none -# SA1202: Elements should be ordered by access -dotnet_diagnostic.SA1202.severity = none +#### Core EditorConfig Options #### -# SA1201: Elements should appear in the correct order -dotnet_diagnostic.SA1201.severity = none - -# SA1306: Field names should begin with lower-case letter -dotnet_diagnostic.SA1306.severity = none - -# IDE0008: Use explicit type -dotnet_diagnostic.IDE0008.severity = none - -# SA1116: Split parameters should start on line after declaration -dotnet_diagnostic.SA1116.severity = none - -[*.vb] -#### Naming styles #### - -# Naming rules - -dotnet_naming_rule.interface_should_be_begins_with_i.severity = suggestion -dotnet_naming_rule.interface_should_be_begins_with_i.symbols = interface -dotnet_naming_rule.interface_should_be_begins_with_i.style = begins_with_i - -dotnet_naming_rule.types_should_be_pascal_case.severity = suggestion -dotnet_naming_rule.types_should_be_pascal_case.symbols = types -dotnet_naming_rule.types_should_be_pascal_case.style = pascal_case - -dotnet_naming_rule.non_field_members_should_be_pascal_case.severity = suggestion -dotnet_naming_rule.non_field_members_should_be_pascal_case.symbols = non_field_members -dotnet_naming_rule.non_field_members_should_be_pascal_case.style = pascal_case - -# Symbol specifications - -dotnet_naming_symbols.interface.applicable_kinds = interface -dotnet_naming_symbols.interface.applicable_accessibilities = public, friend, private, protected, protected_friend, private_protected -dotnet_naming_symbols.interface.required_modifiers = - -dotnet_naming_symbols.types.applicable_kinds = class, struct, interface, enum -dotnet_naming_symbols.types.applicable_accessibilities = public, friend, private, protected, protected_friend, private_protected -dotnet_naming_symbols.types.required_modifiers = - -dotnet_naming_symbols.non_field_members.applicable_kinds = property, event, method -dotnet_naming_symbols.non_field_members.applicable_accessibilities = public, friend, private, protected, protected_friend, private_protected -dotnet_naming_symbols.non_field_members.required_modifiers = - -# Naming styles - -dotnet_naming_style.begins_with_i.required_prefix = I -dotnet_naming_style.begins_with_i.required_suffix = -dotnet_naming_style.begins_with_i.word_separator = -dotnet_naming_style.begins_with_i.capitalization = pascal_case - -dotnet_naming_style.pascal_case.required_prefix = -dotnet_naming_style.pascal_case.required_suffix = -dotnet_naming_style.pascal_case.word_separator = -dotnet_naming_style.pascal_case.capitalization = pascal_case - -dotnet_naming_style.pascal_case.required_prefix = -dotnet_naming_style.pascal_case.required_suffix = -dotnet_naming_style.pascal_case.word_separator = -dotnet_naming_style.pascal_case.capitalization = pascal_case - -[*.{cs,vb}] -dotnet_style_operator_placement_when_wrapping = beginning_of_line -tab_width = 4 +# Indentation and spacing indent_size = 4 -end_of_line = crlf +tab_width = 4 -# Default severity for analyzer diagnostics with category 'StyleCop.CSharp.DocumentationRules' -dotnet_analyzer_diagnostic.category-StyleCop.CSharp.DocumentationRules.severity = none -dotnet_style_coalesce_expression = true:suggestion -dotnet_style_null_propagation = true:suggestion -dotnet_style_prefer_is_null_check_over_reference_equality_method = true:suggestion -dotnet_style_prefer_auto_properties = true:none -dotnet_style_object_initializer = true:suggestion -dotnet_style_collection_initializer = true:suggestion -dotnet_style_prefer_simplified_boolean_expressions = true:suggestion -dotnet_style_prefer_conditional_expression_over_assignment = true:silent -dotnet_style_prefer_conditional_expression_over_return = true:silent -dotnet_style_explicit_tuple_names = true:suggestion -dotnet_style_prefer_inferred_tuple_names = true:suggestion -dotnet_style_prefer_inferred_anonymous_type_member_names = true:suggestion -dotnet_style_prefer_compound_assignment = true:suggestion -dotnet_style_prefer_simplified_interpolation = true:suggestion -dotnet_style_namespace_match_folder = true:suggestion -dotnet_style_readonly_field = true:suggestion -dotnet_style_predefined_type_for_locals_parameters_members = true:silent -dotnet_style_predefined_type_for_member_access = true:silent -dotnet_style_require_accessibility_modifiers = for_non_interface_members:silent -dotnet_style_allow_multiple_blank_lines_experimental = true:silent -dotnet_style_allow_statement_immediately_after_block_experimental = true:silent -dotnet_code_quality_unused_parameters = all:suggestion -dotnet_style_parentheses_in_arithmetic_binary_operators = always_for_clarity:silent -dotnet_style_parentheses_in_other_binary_operators = always_for_clarity:silent -dotnet_style_parentheses_in_relational_binary_operators = always_for_clarity:silent -dotnet_style_parentheses_in_other_operators = never_if_unnecessary:silent -dotnet_style_qualification_for_field = false:silent -dotnet_style_qualification_for_property = false:silent -dotnet_style_qualification_for_method = false:silent -dotnet_style_qualification_for_event = false:silent +# New line preferences +end_of_line = crlf +insert_final_newline = true -# IDE0032: Use auto property -dotnet_diagnostic.IDE0032.severity = none +dotnet_diagnostic.IDE0060.severity = none # Caused by resource with no methods and no subresources +dotnet_diagnostic.IDE1006.severity = none # Some names may not match up with C# conventions +dotnet_diagnostic.IDE0290.severity = none # Don't prefer primary constructors diff --git a/.gitattributes b/.gitattributes deleted file mode 100644 index 1ff0c423..00000000 --- a/.gitattributes +++ /dev/null @@ -1,63 +0,0 @@ -############################################################################### -# Set default behavior to automatically normalize line endings. -############################################################################### -* text=auto - -############################################################################### -# Set default behavior for command prompt diff. -# -# This is need for earlier builds of msysgit that does not have it on by -# default for csharp files. -# Note: This is only used by command line -############################################################################### -#*.cs diff=csharp - -############################################################################### -# Set the merge driver for project and solution files -# -# Merging from the command prompt will add diff markers to the files if there -# are conflicts (Merging from VS is not affected by the settings below, in VS -# the diff markers are never inserted). Diff markers may cause the following -# file extensions to fail to load in VS. An alternative would be to treat -# these files as binary and thus will always conflict and require user -# intervention with every merge. To do so, just uncomment the entries below -############################################################################### -#*.sln merge=binary -#*.csproj merge=binary -#*.vbproj merge=binary -#*.vcxproj merge=binary -#*.vcproj merge=binary -#*.dbproj merge=binary -#*.fsproj merge=binary -#*.lsproj merge=binary -#*.wixproj merge=binary -#*.modelproj merge=binary -#*.sqlproj merge=binary -#*.wwaproj merge=binary - -############################################################################### -# behavior for image files -# -# image files are treated as binary by default. -############################################################################### -#*.jpg binary -#*.png binary -#*.gif binary - -############################################################################### -# diff behavior for common document formats -# -# Convert binary document formats to text before diffing them. This feature -# is only available from the command line. Turn it on by uncommenting the -# entries below. -############################################################################### -#*.doc diff=astextplain -#*.DOC diff=astextplain -#*.docx diff=astextplain -#*.DOCX diff=astextplain -#*.dot diff=astextplain -#*.DOT diff=astextplain -#*.pdf diff=astextplain -#*.PDF diff=astextplain -#*.rtf diff=astextplain -#*.RTF diff=astextplain diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 00000000..34f30288 --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,63 @@ +name: CI +on: + push: + branches-ignore: + - 'generated' + - 'codegen/**' + - 'integrated/**' + - 'stl-preview-head/**' + - 'stl-preview-base/**' + pull_request: + branches-ignore: + - 'stl-preview-head/**' + - 'stl-preview-base/**' + +jobs: + lint: + timeout-minutes: 10 + name: lint + runs-on: ${{ github.repository == 'stainless-sdks/imagekit-csharp' && 'depot-ubuntu-24.04' || 'ubuntu-latest' }} + if: github.event_name == 'push' || github.event.pull_request.head.repo.fork + + steps: + - uses: actions/checkout@v4 + + - name: Set up .NET + uses: actions/setup-dotnet@v3 + with: + dotnet-version: '8.0.x' + + - name: Run lints + run: ./scripts/lint + build: + timeout-minutes: 10 + name: build + runs-on: ${{ github.repository == 'stainless-sdks/imagekit-csharp' && 'depot-ubuntu-24.04' || 'ubuntu-latest' }} + if: github.event_name == 'push' || github.event.pull_request.head.repo.fork + + steps: + - uses: actions/checkout@v4 + + - name: Set up .NET + uses: actions/setup-dotnet@v3 + with: + dotnet-version: '8.0.x' + + - name: Build SDK + run: ./scripts/build + + test: + timeout-minutes: 10 + name: test + runs-on: ${{ github.repository == 'stainless-sdks/imagekit-csharp' && 'depot-ubuntu-24.04' || 'ubuntu-latest' }} + if: github.event_name == 'push' || github.event.pull_request.head.repo.fork + steps: + - uses: actions/checkout@v4 + + - name: Set up .NET + uses: actions/setup-dotnet@v3 + with: + dotnet-version: '8.0.x' + + - name: Run tests + run: ./scripts/test diff --git a/.github/workflows/dotnet-core.yml b/.github/workflows/dotnet-core.yml deleted file mode 100644 index 794d8934..00000000 --- a/.github/workflows/dotnet-core.yml +++ /dev/null @@ -1,83 +0,0 @@ -name: CI Pipeline - -on: - push: - branches: [ master ] - pull_request: - branches: [ master ] - release: - types: - - published -env: - # Disable the .NET logo in the console output. - DOTNET_NOLOGO: true - # Stop wasting time caching packages - DOTNET_SKIP_FIRST_TIME_EXPERIENCE: true - # Disable sending usage data to Microsoft - DOTNET_CLI_TELEMETRY_OPTOUT: true - GITHUB_FEED: https://nuget.pkg.github.com/cloudmeteor/index.json - GITHUB_USER: cloudmeteor - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - NUGET_FEED: https://api.nuget.org/v3/index.json - NUGET_KEY: ${{ secrets.NUGET_APIKEY }} - ATTRIBUTE_NAME: nupkg - NUGET_OUTPUT_PATH: nuget-package - Solution_Name: Imagekit.sln - -jobs: - build: - name: Build and test - - runs-on: ubuntu-latest - - steps: - - uses: actions/checkout@master - - - name: Setup .NET - uses: actions/setup-dotnet@v1 - with: - dotnet-version: | - 2.1.x - 3.1.x - 5.0.x - 6.0.x - 7.0.x - 8.0.x - - name: Build Release - run: dotnet build Imagekit.sln -c Release /p:ContinuousIntegrationBuild=true - - # run: dotnet test --no-build Imagekit.UnitTests/Imagekit.UnitTests.csproj -c Release - - name: Run test suite - run: dotnet test Imagekit.UnitTests/Imagekit.UnitTests.csproj --verbosity minimal /p:CollectCoverage=true /p:CoverletOutputFormat=opencover - - - name: Upload Coverage to Codecov - uses: codecov/codecov-action@v1 - with: - file: ./Imagekit.UnitTests/coverage.net6.0.opencover.xml - - - name: Pack - run: dotnet pack Imagekit.sln -c Release --no-build --output ${{ env.NUGET_OUTPUT_PATH }} - - - name: 'Upload Artifact' - uses: actions/upload-artifact@v3 - with: - name: ${{ env.ATTRIBUTE_NAME }} - path: ${{ env.NUGET_OUTPUT_PATH }} - - Publish: - needs: build - if: (github.event_name == 'release') || (github.ref == 'refs/tags/*') - runs-on: ubuntu-latest - steps: - - name: Download all workflow run artifacts - uses: actions/download-artifact@v3 - with: - name: ${{ env.ATTRIBUTE_NAME }} - - - name: Setup .NET - uses: actions/setup-dotnet@v1 - with: - dotnet-version: 6.0.x - - - name: Publish NuGet packages to NuGet - run: dotnet nuget push "*.nupkg" -k ${{ secrets.NUGET_APIKEY }} --source ${{ env.NUGET_FEED }} --no-symbols true --skip-duplicate diff --git a/.gitignore b/.gitignore index b3a7da81..cd42ee34 100644 --- a/.gitignore +++ b/.gitignore @@ -1,266 +1,2 @@ -## Ignore Visual Studio temporary files, build results, and -## files generated by popular Visual Studio add-ons. - -# User-specific files -*.suo -*.user -*.userosscache -*.sln.docstates - -# User-specific files (MonoDevelop/Xamarin Studio) -*.userprefs - -# Build results -[Dd]ebug/ -[Dd]ebugPublic/ -[Rr]elease/ -[Rr]eleases/ -x64/ -x86/ -bld/ -[Bb]in/ -[Oo]bj/ -[Ll]og/ - -# Visual Studio 2015 cache/options directory -.vs/ -# Uncomment if you have tasks that create the project's static files in wwwroot -#wwwroot/ - -# MSTest test Results -[Tt]est[Rr]esult*/ -[Bb]uild[Ll]og.* - -# NUNIT -*.VisualState.xml -TestResult.xml - -# Build Results of an ATL Project -[Dd]ebugPS/ -[Rr]eleasePS/ -dlldata.c - -# DNX -project.lock.json -project.fragment.lock.json -artifacts/ - -*_i.c -*_p.c -*_i.h -*.ilk -*.meta -*.obj -*.pch -*.pdb -*.pgc -*.pgd -*.rsp -*.sbr -*.tlb -*.tli -*.tlh -*.tmp -*.tmp_proj -*.log -*.vspscc -*.vssscc -.builds -*.pidb -*.svclog -*.scc - -# Chutzpah Test files -_Chutzpah* - -# Visual C++ cache files -ipch/ -*.aps -*.ncb -*.opendb -*.opensdf -*.sdf -*.cachefile -*.VC.db -*.VC.VC.opendb - -# Visual Studio profiler -*.psess -*.vsp -*.vspx -*.sap - -# TFS 2012 Local Workspace -$tf/ - -# Guidance Automation Toolkit -*.gpState - -# ReSharper is a .NET coding add-in -_ReSharper*/ -*.[Rr]e[Ss]harper -*.DotSettings.user - -# JustCode is a .NET coding add-in -.JustCode - -# TeamCity is a build add-in -_TeamCity* - -# Code Coverage -*.dotCover -coverage.cobertura.xml -coverage.info -CoverageReport - - -# NCrunch -_NCrunch_* -.*crunch*.local.xml -nCrunchTemp_* - -# MightyMoose -*.mm.* -AutoTest.Net/ - -# Web workbench (sass) -.sass-cache/ - -# Installshield output folder -[Ee]xpress/ - -# DocProject is a documentation generator add-in -DocProject/buildhelp/ -DocProject/Help/*.HxT -DocProject/Help/*.HxC -DocProject/Help/*.hhc -DocProject/Help/*.hhk -DocProject/Help/*.hhp -DocProject/Help/Html2 -DocProject/Help/html - -# Click-Once directory -publish/ - -# Publish Web Output -*.[Pp]ublish.xml -*.azurePubxml -# TODO: Comment the next line if you want to checkin your web deploy settings -# but database connection strings (with potential passwords) will be unencrypted -#*.pubxml -*.publishproj - -# Microsoft Azure Web App publish settings. Comment the next line if you want to -# checkin your Azure Web App publish settings, but sensitive information contained -# in these scripts will be unencrypted -PublishScripts/ - -# NuGet Packages -*.nupkg -# The packages folder can be ignored because of Package Restore -**/packages/* -# except build/, which is used as an MSBuild target. -!**/packages/build/ -# Uncomment if necessary however generally it will be regenerated when needed -#!**/packages/repositories.config -# NuGet v3's project.json files produces more ignoreable files -*.nuget.props -*.nuget.targets - -# Microsoft Azure Build Output -csx/ -*.build.csdef - -# Microsoft Azure Emulator -ecf/ -rcf/ - -# Windows Store app package directories and files -AppPackages/ -BundleArtifacts/ -Package.StoreAssociation.xml -_pkginfo.txt - -# Visual Studio cache files -# files ending in .cache can be ignored -*.[Cc]ache -# but keep track of directories ending in .cache -!*.[Cc]ache/ - -# Others -ClientBin/ -~$* -*~ -*.dbmdl -*.dbproj.schemaview -*.jfm -*.pfx -*.publishsettings -node_modules/ -orleans.codegen.cs - -# Since there are multiple workflows, uncomment next line to ignore bower_components -# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622) -#bower_components/ - -# RIA/Silverlight projects -Generated_Code/ - -# Backup & report files from converting an old project file -# to a newer Visual Studio version. Backup files are not needed, -# because we have git ;-) -_UpgradeReport_Files/ -Backup*/ -UpgradeLog*.XML -UpgradeLog*.htm - -# SQL Server files -*.mdf -*.ldf - -# Business Intelligence projects -*.rdl.data -*.bim.layout -*.bim_*.settings - -# Microsoft Fakes -FakesAssemblies/ - -# GhostDoc plugin setting file -*.GhostDoc.xml - -# Node.js Tools for Visual Studio -.ntvs_analysis.dat - -# Visual Studio 6 build log -*.plg - -# Visual Studio 6 workspace options file -*.opt - -# Visual Studio LightSwitch build output -**/*.HTMLClient/GeneratedArtifacts -**/*.DesktopClient/GeneratedArtifacts -**/*.DesktopClient/ModelManifest.xml -**/*.Server/GeneratedArtifacts -**/*.Server/ModelManifest.xml -_Pvt_Extensions - -# Paket dependency manager -.paket/paket.exe -paket-files/ - -# FAKE - F# Make -.fake/ - -# JetBrains Rider -.idea/ -*.sln.iml - -# CodeRush -.cr/ - -# Python Tools for Visual Studio (PTVS) -__pycache__/ -*.pyc -.DS_Store \ No newline at end of file +bin/ +obj/ diff --git a/.release-please-manifest.json b/.release-please-manifest.json new file mode 100644 index 00000000..c7159c1a --- /dev/null +++ b/.release-please-manifest.json @@ -0,0 +1,3 @@ +{ + ".": "0.0.2" +} \ No newline at end of file diff --git a/.stats.yml b/.stats.yml new file mode 100644 index 00000000..5d25590d --- /dev/null +++ b/.stats.yml @@ -0,0 +1,4 @@ +configured_endpoints: 42 +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/imagekit-inc%2Fimagekit-3d7da4b8ef2ed30aa32c4fb3e98e498e67402e91aaa5fd4c628fc080bfe82ea1.yml +openapi_spec_hash: aaa50fcbccec6f2cf1165f34bc6ac886 +config_hash: 9f8a678d9d4d06daec522e8deb49e3ad diff --git a/.vscode/tasks.json b/.vscode/tasks.json deleted file mode 100644 index 180d9fb6..00000000 --- a/.vscode/tasks.json +++ /dev/null @@ -1,123 +0,0 @@ -{ - "version": "2.0.0", - "tasks": [ - { - "label": "build", - "command": "dotnet", - "type": "process", - "args": [ - "build", - "${workspaceFolder}/Imagekit.UnitTests/Imagekit.UnitTests.csproj", - "/property:GenerateFullPaths=true", - "/consoleloggerparameters:NoSummary" - ], - "problemMatcher": "$msCompile" - }, - { - "label": "build", - "command": "dotnet", - "type": "shell", - "args": [ - "build", - "${workspaceRoot}/Imagekit/Imagekit.csproj", - "-f", - "netstandard2.1" - ], - "group": { - "kind": "build", - "isDefault": true - }, - "presentation": { - "panel": "shared", - "clear": true - }, - "problemMatcher": { - "base": "$msCompile", - "fileLocation": [ - "relative", - "${workspaceFolder}" - ] - } - }, - { - "label": "test", - "group": { - "kind": "test", - "isDefault": true - }, - "type": "process", - "command": "dotnet", - "args": [ - "test", - "${workspaceRoot}/Imagekit.UnitTests/Imagekit.UnitTests.csproj", - "--logger", - "html", - "/p:Configuration=Debug", - "/p:CollectCoverage=true", - "/p:CoverletOutputFormat=cobertura%2clcov", - "/p:Exclude=[*Tests]*" - ], - "presentation": { - "echo": true, - "reveal": "always", - "focus": true, - "panel": "shared", - "showReuseMessage": true, - "clear": true - } - }, - { - "label": "generate test coverage report", - "group": "none", - "command": "dotnet", - "type": "shell", - "args": [ - "reportgenerator", - "\"-reports:${workspaceRoot}/Imagekit.UnitTests/coverage.cobertura.xml\"", - "\"-targetdir:${workspaceRoot}/Imagekit.UnitTests/CoverageReport\"", - "-reportTypes:htmlInline" - ], - "options": { - "cwd": "${workspaceFolder}/Imagekit.UnitTests" - }, - "dependsOn": [ - "test" - ], - "presentation": { - "echo": true, - "reveal": "always", - "focus": true, - "panel": "shared", - "showReuseMessage": true, - "clear": false - }, - "problemMatcher": [] - }, - { - "label": "open test coverage report", - "group": "none", - "osx": { - "command": "open" - }, - "windows": { - "command": "start" - }, - "type": "shell", - "args": [ - "${workspaceRoot}/Imagekit.UnitTests/CoverageReport/index.htm" - ], - "problemMatcher": [], - "dependsOn": [ - "generate test coverage report" - ], - "presentation": { - "echo": true, - "reveal": "always", - "focus": true, - "panel": "shared", - "showReuseMessage": true, - "clear": true - } - } - ] -} \ No newline at end of file diff --git a/CHANGELOG.md b/CHANGELOG.md index 25fd627e..ac358ef4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,74 +1,10 @@ # Changelog -All notable changes to this project will be documented in this file. -The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), -and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## 0.0.2 (2025-09-01) -## [5.0.0] +Full Changelog: [v0.0.1...v0.0.2](https://github.com/imagekit-developer/imagekit-dotnet/compare/v0.0.1...v0.0.2) -### Breaking changes +### Chores -**Overlay syntax update** -* In version 5.0.0, we've removed the old overlay syntax parameters for transformations, such as `oi`, `ot`, `obg`, and [more](https://docs.imagekit.io/features/image-transformations/overlay). These parameters are deprecated and will start returning errors when used in URLs. Please migrate to the new layers syntax that supports overlay nesting, provides better positional control, and allows more transformations at the layer level. You can start with [examples](https://docs.imagekit.io/features/image-transformations/overlay-using-layers#examples) to learn quickly. -* You can migrate to the new layers syntax using the `raw` transformation parameter. - -### Added -- Parameters `EffectShadow` and `EffectGradient` for url generation. -- Upload options - - `transformation` for applying `pre` and `post` transformations. - - `checks` to perform server-side validations before file uploads. - - `isPublished` determines whether the file should be uploaded as published. -- Update parameter - - `publish` to configure the publication status of a file and its versions. - -## [4.0.1] -### Fixed -- https://github.com/imagekit-developer/imagekit-dotnet/issues/50 - -## [4.0.0] -### Fixed -- https://github.com/imagekit-developer/imagekit-dotnet/issues/37 -- https://github.com/imagekit-developer/imagekit-dotnet/issues/41 -- https://github.com/imagekit-developer/imagekit-dotnet/issues/40 -- https://github.com/imagekit-developer/imagekit-dotnet/issues/38 -- https://github.com/imagekit-developer/imagekit-dotnet/issues/34 - -## [3.1.6] - 2021-07-21 -### Fixed -- Bug Fix - -## [3.1.5] - 2021-06-05 -### Changed -- Sort, searchQuery options added for ListAPI -- API reponse fields updated - -## [3.1.4] - 2021-04-12 -### Fixed -- Core package install bug fix - -## [3.1.3] - 2020-11-05 -### Fixed -- Delete Api bug fix - -## [3.1.2] - 2020-11-04 -### Fixed -- Upload Api fix - -## [3.1.1] - 2020-09-11 -### Changed -- Fix issue where tags were not set in some cases when uploading a file -- Allow more ways to set tags when updating file details - -## [3.1.0] - 2020-09-03 -### Added -- Async methods for all asynchronous calls -- `ClientImagekit` that supports client upload without the private key -- Support for .NET Standard 2.1 -- `ImagekitResponse.FileId` -- Some XML documentation - -### Changed -- The `Imagekit.Imagekit` class is deprecated; use `ServerImagekit` instead -- Fix issue where `isPrivateFile` was not included on upload -- Fix issue where type of `Gps.GPSLatitude`, `Gps.GPSLongitude`, and `GPSTimeStamp` was incorrect -- Some of the `ArgumentException`s are now `ArgumentNullException` and set the `ParamName` property of the exception. This is not a binary breaking change as `ArgumentNullException` inherits from `ArgumentException`, but if you are specifically looking for the `ArgumentException` type exactly, you may see a runtime issue, although this is very unlikely. +* sync repo ([22d3567](https://github.com/imagekit-developer/imagekit-dotnet/commit/22d3567b5fdf988260a9c62f791c391c759e04b1)) +* update SDK settings ([64c1feb](https://github.com/imagekit-developer/imagekit-dotnet/commit/64c1feb98cc33c0ae56760cd9045b64c92269a16)) diff --git a/ImageKitSample/Program.cs b/ImageKitSample/Program.cs deleted file mode 100644 index 093bb84e..00000000 --- a/ImageKitSample/Program.cs +++ /dev/null @@ -1,482 +0,0 @@ -// -// Copyright (c) PlaceholderCompany. All rights reserved. -// - -namespace ImagekitSample -{ - using System; - using System.Collections; - using System.Collections.Generic; - using System.Net; - using Imagekit; - using Imagekit.Models; - using Imagekit.Models.Response; - using Imagekit.Sdk; - using Newtonsoft.Json.Linq; - using static Imagekit.Models.CustomMetaDataFieldSchemaObject; - - internal class Program - { - static void Main(string[] args) - { - - // Create Instance of ImageKit - ImagekitClient imagekit = new ImagekitClient("your_public_key", "your_private_key", "https://ik.imagekit.io/your_imagekit_id/endpoint"); - #region URL Generation - - - // Generating URLs - - string path = "/default_image.jpg"; - Transformation trans = new Transformation() - .Width(400) - .Height(300) - .AspectRatio("4-3") - .Quality(40) - .Crop("force").CropMode("extract"). - Focus("left"). - Format("jpeg"). - Background("A94D34"). - Border("5-A94D34"). - Rotation(90). - Blur(10). - Named("some_name"). - Progressive(true). - Lossless(true). - Trim(5). - Metadata(true). - ColorProfile(true). - DefaultImage("folder/file_name.jpg/"). //trailing slash case - Dpr(3). - EffectSharpen(10). - EffectUsm("2-2-0.8-0.024"). - EffectContrast(true). - EffectGray(). - EffectShadow(). - EffectGradient(). - Original(). - Raw("h-200,w-300,l-image,i-logo.png,l-end"); - - string imageUrl = imagekit.Url(trans).Path(path).TransformationPosition("query").Generate(); - - Console.WriteLine("Generated image URL - {0}", imageUrl); - - ///// Generating Signed URL - var imgUrl1 = "https://ik.imagekit.io/demo/default-image.jpg"; - string[] queryParams = { "b=query", "a=value" }; - try - { - var signedUrl = imagekit.Url(new Transformation().Width(400).Height(300)) - .Src(imgUrl1) - .QueryParameters(queryParams) - .ExpireSeconds(600) - .Signed() - .Generate(); - Console.WriteLine("Signed Url for first image transformed with height: 300, width: 400: - {0}", signedUrl); - } - catch (Exception ex) - { - Console.WriteLine(ex.Message); - } - #endregion - - #region Upload BY URI| Bytes | Base64 - - // Upload By URI - FileCreateRequest request = new FileCreateRequest - { - file = "http://www.google.com/images/logos/ps_logo2.png", - fileName = "file_name.jpg" - }; - Result resp1 = imagekit.Upload(request); - - // Upload by bytes - var webClient = new WebClient(); - byte[] bytes = webClient.DownloadData("http://www.google.com/images/logos/ps_logo2.png"); - - FileCreateRequest ob = new FileCreateRequest - { - file = bytes, - fileName = "file_name1.jpg" - }; - List tags = new List - { - "Software", - "Developer", - "Engineer" - }; - ob.tags = tags; - - string customCoordinates = "10,10,20,20"; - ob.customCoordinates = customCoordinates; - List responseFields = new List - { - "isPrivateFile", - "tags", - "customCoordinates" - }; - ob.responseFields = responseFields; - List ext = new List(); - BackGroundImage bck1 = new BackGroundImage - { - name = "remove-bg", - options = new options() - { add_shadow = true, semitransparency = false, bg_image_url = "http://www.google.com/images/logos/ps_logo2.png" } - }; - AutoTags autoTags = new AutoTags - { - name = "google-auto-tagging", - maxTags = 5, - minConfidence = 95 - }; - TransformationObject transformationObject = new TransformationObject - { - type = "transformation", - value = "w-100" - }; - List postTransformations = new List(); - postTransformations.Add(transformationObject); - UploadTransformation uploadTransformation = new UploadTransformation - { - pre = "l-text,i-Imagekit,fs-50,l-end", - post = postTransformations, - }; - ext.Add(bck1); - ext.Add(autoTags); - ob.extensions = ext; - ob.webhookUrl = "https://webhook.site/c78d617f_33bc_40d9_9e61_608999721e2e"; - ob.useUniqueFileName = true; - ob.folder = "dummy_folder"; - ob.isPrivateFile = false; - ob.overwriteFile = true; - ob.overwriteAITags = true; - ob.overwriteTags = true; - ob.overwriteCustomMetadata = true; - ob.transformation= uploadTransformation; - Result resp2 = imagekit.Upload(ob); - - // Get Base64 - byte[] bytes1 = webClient.DownloadData("http://www.google.com/images/logos/ps_logo2.png"); - - byte[] imageArray = bytes1; - string base64ImageRepresentation = Convert.ToBase64String(imageArray); - - // Upload by Base64 - FileCreateRequest ob2 = new FileCreateRequest - { - file = base64ImageRepresentation, - fileName = Guid.NewGuid().ToString() - }; - Result resp = imagekit.Upload(ob2); - #endregion - - #region UpdateFile - - //Update File Request - FileUpdateRequest updateob = new FileUpdateRequest - { - fileId = "fileId", - }; - List updatetags = new List - { - "Software", - "Developer", - "Engineer" - }; - updateob.tags = updatetags; - - string updatecustomCoordinates = "10,10,20,20"; - updateob.customCoordinates = updatecustomCoordinates; - List updateresponseFields = new List - { - "isPrivateFile", - "tags", - "customCoordinates" - }; - - List extModel = new List(); - BackGroundImage bck = new BackGroundImage - { - name = "remove-bg", - options = new options() { add_shadow = true, semitransparency = false, bg_color = "green" } - }; - extModel.Add(bck); - updateob.extensions = extModel; - updateob.webhookUrl = "https://webhook.site/c78d617f_33bc_40d9_9e61_608999721e2e"; - - Result updateresp = imagekit.UpdateFileDetail(updateob); - - #endregion - - #region File Management - - // List and search files - GetFileListRequest model = new GetFileListRequest - { - Name = "file_name.jpg", - Type = "file", - Limit = 10, - Skip = 0, - Sort = "ASC_CREATED", - SearchQuery = "createdAt >= \"7d\"", - FileType = "image", - Tags = new string[] { "sale", "summer" }, - Path = "/" - }; - ResultList res = imagekit.GetFileListRequest(model); - - // Get File Details - Result res1 = imagekit.GetFileDetail("file_Id"); - - // Delete File by FileId - ResultDelete res2 = imagekit.DeleteFile("file_Id"); - - // Bulk Delete - List ob3 = new List(); - ob3.Add("fileId_1"); - ob3.Add("fileId_2"); - ResultFileDelete resultFileDelete = imagekit.BulkDeleteFiles(ob3); - - // Copy File - CopyFileRequest cpyRequest = new CopyFileRequest - { - sourceFilePath = "path_1", - destinationPath = "path_2" - }; - ResultNoContent resultNoContent = imagekit.CopyFile(cpyRequest); - - // MoveFile - MoveFileRequest moveFile = new MoveFileRequest - { - sourceFilePath = "path_1", - destinationPath = "path_2" - }; - ResultNoContent resultNoContentMoveFile = imagekit.MoveFile(moveFile); - - // RenameFile - RenameFileRequest renameFileRequest = new RenameFileRequest - { - filePath = "path_1", - newFileName = "file_name", - purgeCache = false - }; - ResultRenameFile resultRenameFile = imagekit.RenameFile(renameFileRequest); - - #endregion - - #region Tags - TagsRequest tagsRequest = new TagsRequest - { - tags = new List - { - "tag_1", - "tag_2" - }, - fileIds = new List - { - "fileId_1", - }, - }; - ResultTags resultTags = imagekit.AddTags(tagsRequest); - - TagsRequest removeTagsRequest = new TagsRequest - { - tags = new List - { - "tag_1", - "tag_2" - }, - fileIds = new List - { - "fileId_1", - }, - }; - ResultTags removeTags = imagekit.RemoveTags(removeTagsRequest); - - AITagsRequest removeAITagsRequest = new AITagsRequest - { - AITags = new List - { - "tag_1", - "tag_2" - }, - fileIds = new List - { - "fileId_1", - }, - }; - ResultTags removeAITags = imagekit.RemoveAITags(removeAITagsRequest); - - #endregion - - #region FileVersionRequest - DeleteFileVersionRequest delRequest = new DeleteFileVersionRequest - { - fileId = "file_Id", - versionId = "version_Id" - }; - ResultNoContent resultNoContent1 = imagekit.DeleteFileVersion(delRequest); - - // RestoreFileVersion - Result result = imagekit.RestoreFileVersion("file_Id", "version_Id"); - - // GetFileVersions - ResultFileVersions resultFileVersions = imagekit.GetFileVersions("file_Id"); - - // GetFileVersionDetails - ResultFileVersionDetails resultFileVersionDetails = imagekit.GetFileVersionDetails("file_Id", "version_Id"); - - #endregion - - #region ManageFolder - - CreateFolderRequest createFolderRequest = new CreateFolderRequest - { - folderName = "folder_name", - parentFolderPath = "source/folder/path" - }; - ResultEmptyBlock resultEmptyBlock = imagekit.CreateFolder(createFolderRequest); - - // DeleteFolderRequest - DeleteFolderRequest deleteFolderRequest = new DeleteFolderRequest - { - folderPath = "source/folder/path/folder_name", - }; - ResultNoContent resultNoContent2 = imagekit.DeleteFolder(deleteFolderRequest); - - // CopyFolder - CopyFolderRequest cpyFolderRequest = new CopyFolderRequest - { - sourceFolderPath = "path_1", - destinationPath = "path_2", - includeFileVersions = true - }; - - ResultOfFolderActions resultOfFolderActions = imagekit.CopyFolder(cpyFolderRequest); - - // MoveFolder - MoveFolderRequest moveFolderRequest = new MoveFolderRequest - { - sourceFolderPath = "path_1", - destinationPath = "path_2" - }; - - ResultOfFolderActions resultOfFolderActions1 = imagekit.MoveFolder(moveFolderRequest); - - #endregion - - #region GetBulkJobStatus - ResultBulkJobStatus resultBulkJobStatus = imagekit.GetBulkJobStatus("job_Id"); - - #endregion - - #region Purge - - ResultCache resultCache = imagekit.PurgeCache("url"); - - ResultCacheStatus resultCacheStatus = imagekit.PurgeStatus("request_Id"); - - #endregion - - #region Metadata - ResultMetaData resultMetaData = imagekit.GetFileMetadata("file_Id"); - - ResultMetaData resultMetaData1 = imagekit.GetRemoteFileMetadata("https://ik.imagekit.io/demo/medium_cafe_B1iTdD0C.jpg"); - - // CustomMetaDataFields - ResultCustomMetaDataFieldList resultCustomMetaDataFieldList = imagekit.GetCustomMetaDataFields(true); - - // CreateCustomMetaDataFields - CustomMetaDataFieldCreateRequest requestModelDate = new CustomMetaDataFieldCreateRequest - { - name = "custom_meta_Date", - label = "TestmetaDat" - }; - CustomMetaDataFieldSchemaObject schemaDate = new CustomMetaDataFieldSchemaObject - { - type = CustomMetaDataTypeEnum.Date.ToString(), - minValue = "2022-11-30T10:11:10+00:00", - maxValue = "2022-12-30T10:11:10+00:00", - isValueRequired = true, - defaultValue = "2022-12-30T10:11:10+00:00" - }; - - requestModelDate.schema = schemaDate; - ResultCustomMetaDataField resultCustomMetaDataFieldDate = imagekit.CreateCustomMetaDataFields(requestModelDate); - - - CustomMetaDataFieldCreateRequest requestModel = new CustomMetaDataFieldCreateRequest - { - name = "custom_meta_1", - label = "Testmeta" - }; - CustomMetaDataFieldSchemaObject schema = new CustomMetaDataFieldSchemaObject - { - type = CustomMetaDataTypeEnum.Number.ToString(), - minValue = 2000, - maxValue = 3000, - isValueRequired = true, - defaultValue = 2500 - }; - - requestModel.schema = schema; - ResultCustomMetaDataField resultCustomMetaDataField1 = imagekit.CreateCustomMetaDataFields(requestModel); - - CustomMetaDataFieldCreateRequest requestModel1 = new CustomMetaDataFieldCreateRequest - { - name = "custom_meta_2", - label = "Testmeta" - }; - CustomMetaDataFieldSchemaObject schema1 = new CustomMetaDataFieldSchemaObject - { - type = CustomMetaDataTypeEnum.Text.ToString(), - minLength = 1000, - maxLength = 2000, - isValueRequired = true, - defaultValue = "2500" - }; - - requestModel1.schema = schema1; - ResultCustomMetaDataField resultCustomMetaDataField = imagekit.CreateCustomMetaDataFields(requestModel1); - - CustomMetaDataFieldCreateRequest requestModelSelect = new CustomMetaDataFieldCreateRequest - { - name = "custom_meta_Select1", - label = "TestmetaSelect1" - }; - CustomMetaDataFieldSchemaObject schemaSelect = new CustomMetaDataFieldSchemaObject - { - type = CustomMetaDataTypeEnum.SingleSelect.ToString(), - selectOptions = new string[] { "small", "medium", "large" }, - isValueRequired = true, - defaultValue = "medium" - }; - requestModelSelect.schema = schemaSelect; - ResultCustomMetaDataField resultCustomMetaDataFieldSelect = imagekit.CreateCustomMetaDataFields(requestModelSelect); - - - // UpdateCustomMetaDataFields - CustomMetaDataFieldUpdateRequest requestUpdateModel = new CustomMetaDataFieldUpdateRequest - { - Id = "field_Id", - }; - CustomMetaDataFieldSchemaObject updateschema = new CustomMetaDataFieldSchemaObject - { - type = "Number", - minValue = 300, - maxValue = 500 - }; - - requestUpdateModel.schema = updateschema; - ResultCustomMetaDataField resultCustomMetaDataFieldUpdate = imagekit.UpdateCustomMetaDataFields(requestUpdateModel); - - //Delete Custom MetaData - ResultNoContent resultNoContentDel = imagekit.DeleteCustomMetaDataField("field_id"); - - // Get Authentication Token - var authenticationParameters = imagekit.GetAuthenticationParameters("your_token"); - Console.WriteLine("Authentication Parameters: {0}", JToken.FromObject(authenticationParameters).ToString()); - #endregion - } - } -} diff --git a/ImageKitSample/test.jpg b/ImageKitSample/test.jpg deleted file mode 100644 index 79de088c..00000000 Binary files a/ImageKitSample/test.jpg and /dev/null differ diff --git a/Imagekit.UnitTests/FileVersion/FileVersionTestAsync.cs b/Imagekit.UnitTests/FileVersion/FileVersionTestAsync.cs deleted file mode 100644 index 339de562..00000000 --- a/Imagekit.UnitTests/FileVersion/FileVersionTestAsync.cs +++ /dev/null @@ -1,481 +0,0 @@ -using Imagekit.Constant; -using Imagekit.Models; -using Newtonsoft.Json; -using System; -using System.Net; -using System.Net.Http; -using Xunit; - -namespace Imagekit.UnitTests.FileVersion -{ - - public class FileVersionTestAsync - - { - private const string GOOD_PUBLICKEY = "abc"; - private const string GOOD_URLENDPOINT = "https://dasdsad.dad.io/"; - - - - - - [Fact] - public void Missing_Object_FileVersionException() - { - DeleteFileVersionRequest model = null; - var responseObj = TestHelpers.ImagekitResponseFaker.Generate(); - - var httpResponse = new HttpResponseMessage - { - StatusCode = HttpStatusCode.OK, - Content = new StringContent(JsonConvert.SerializeObject(responseObj)) - }; - var httpClient = TestHelpers.GetTestHttpClient(httpResponse); - var restClient = new RestClient(GOOD_PUBLICKEY, GOOD_URLENDPOINT, httpClient); - var ex = Assert.ThrowsAsync(async () => await restClient.DeleteFileVersionAsync(model)); - Assert.Equal(ErrorMessages.InvalidDelVerValue, ex.Result.Message); - } - [Fact] - public void Missing_fileId_FileVersionException() - { - DeleteFileVersionRequest model = new DeleteFileVersionRequest - { - versionId = "abc" - }; - var responseObj = TestHelpers.ImagekitResponseFaker.Generate(); - - var httpResponse = new HttpResponseMessage - { - StatusCode = HttpStatusCode.OK, - Content = new StringContent(JsonConvert.SerializeObject(responseObj)) - }; - var httpClient = TestHelpers.GetTestHttpClient(httpResponse); - var restClient = new RestClient(GOOD_PUBLICKEY, GOOD_URLENDPOINT, httpClient); - var ex = Assert.ThrowsAsync(async () => await restClient.DeleteFileVersionAsync(model)); - Assert.Equal(ErrorMessages.InvalidFieldIdDelVerValue, ex.Result.Message); - } - - [Fact] - public void Missing_versionId_FileVersionException() - { - DeleteFileVersionRequest model = new DeleteFileVersionRequest - { - versionId = "", - fileId = "sas" - }; - var responseObj = TestHelpers.ImagekitResponseFaker.Generate(); - - var httpResponse = new HttpResponseMessage - { - StatusCode = HttpStatusCode.OK, - Content = new StringContent(JsonConvert.SerializeObject(responseObj)) - }; - var httpClient = TestHelpers.GetTestHttpClient(httpResponse); - var restClient = new RestClient(GOOD_PUBLICKEY, GOOD_URLENDPOINT, httpClient); - var ex = Assert.ThrowsAsync(async () => await restClient.DeleteFileVersionAsync(model)); - Assert.Equal(ErrorMessages.InvalidversionIdDelVerValue, ex.Result.Message); - } - - [Fact] - public void CopyFile_Default() - { - CopyFileRequest model = new CopyFileRequest - { - sourceFilePath = "Tst3", - destinationPath = "Tst3", - includeFileVersions = true - }; - var responseObj = TestHelpers.ImagekitResponseFaker.Generate(); - var httpResponse = new HttpResponseMessage - { - StatusCode = HttpStatusCode.OK, - Content = new StringContent(JsonConvert.SerializeObject(responseObj)) - }; - var httpClient = TestHelpers.GetTestHttpClient(httpResponse); - var restClient = new RestClient(GOOD_PUBLICKEY, GOOD_URLENDPOINT, httpClient); - - var response = restClient.CopyFileAsync(model).Result; - var responseObj1 = JsonConvert.SerializeObject(responseObj); - Assert.Equal(responseObj1, response.Raw); - } - - - [Fact] - public void Missing_Obj_CopyFileException() - { - CopyFileRequest model = null; - var responseObj = TestHelpers.ImagekitResponseFaker.Generate(); - - var httpResponse = new HttpResponseMessage - { - StatusCode = HttpStatusCode.OK, - Content = new StringContent(JsonConvert.SerializeObject(responseObj)) - }; - var httpClient = TestHelpers.GetTestHttpClient(httpResponse); - var restClient = new RestClient(GOOD_PUBLICKEY, GOOD_URLENDPOINT, httpClient); - var ex = Assert.ThrowsAsync(async () => await restClient.CopyFileAsync(model)); - Assert.Equal(ErrorMessages.InvalidCopyValue, ex.Result.Message); - } - - - - [Fact] - public void Missing_Source_CopyFileException() - { - CopyFileRequest model = new CopyFileRequest - { - destinationPath = "abc" - }; - var responseObj = TestHelpers.ImagekitResponseFaker.Generate(); - - var httpResponse = new HttpResponseMessage - { - StatusCode = HttpStatusCode.OK, - Content = new StringContent(JsonConvert.SerializeObject(responseObj)) - }; - var httpClient = TestHelpers.GetTestHttpClient(httpResponse); - var restClient = new RestClient(GOOD_PUBLICKEY, GOOD_URLENDPOINT, httpClient); - var ex = Assert.ThrowsAsync(async () => await restClient.CopyFileAsync(model)); - Assert.Equal(ErrorMessages.InvalidSourceValue, ex.Result.Message); - } - - [Fact] - public void Missing_Destination_CopyFileException() - { - CopyFileRequest model = new CopyFileRequest - { - sourceFilePath = "abc" - }; - var responseObj = TestHelpers.ImagekitResponseFaker.Generate(); - - var httpResponse = new HttpResponseMessage - { - StatusCode = HttpStatusCode.OK, - Content = new StringContent(JsonConvert.SerializeObject(responseObj)) - }; - var httpClient = TestHelpers.GetTestHttpClient(httpResponse); - var restClient = new RestClient(GOOD_PUBLICKEY, GOOD_URLENDPOINT, httpClient); - var ex = Assert.ThrowsAsync(async () => await restClient.CopyFileAsync(model)); - Assert.Equal(ErrorMessages.InvalidDestinationValue, ex.Result.Message); - } - - [Fact] - public void MoveFile_Default() - { - MoveFileRequest model = new MoveFileRequest - { - sourceFilePath = "Tst3", - destinationPath = "Tst3" - }; - - var responseObj = TestHelpers.ImagekitResponseFaker.Generate(); - var httpResponse = new HttpResponseMessage - { - StatusCode = HttpStatusCode.OK, - Content = new StringContent(JsonConvert.SerializeObject(responseObj)) - }; - var httpClient = TestHelpers.GetTestHttpClient(httpResponse); - var restClient = new RestClient(GOOD_PUBLICKEY, GOOD_URLENDPOINT, httpClient); - - var response = restClient.MoveFileAsync(model).Result; - var responseObj1 = JsonConvert.SerializeObject(responseObj); - Assert.Equal(responseObj1, response.Raw); - } - - - [Fact] - public void Missing_Obj_MoveFileException() - { - MoveFileRequest model = null; - var responseObj = TestHelpers.ImagekitResponseFaker.Generate(); - - var httpResponse = new HttpResponseMessage - { - StatusCode = HttpStatusCode.OK, - Content = new StringContent(JsonConvert.SerializeObject(responseObj)) - }; - var httpClient = TestHelpers.GetTestHttpClient(httpResponse); - var restClient = new RestClient(GOOD_PUBLICKEY, GOOD_URLENDPOINT, httpClient); - var ex = Assert.ThrowsAsync(async () => await restClient.MoveFileAsync(model)); - Assert.Equal(ErrorMessages.InvalidCopyValue, ex.Result.Message); - } - - [Fact] - public void Missing_Source_MoveFileException() - { - MoveFileRequest model = new MoveFileRequest - { - destinationPath = "abc" - }; - var responseObj = TestHelpers.ImagekitResponseFaker.Generate(); - - var httpResponse = new HttpResponseMessage - { - StatusCode = HttpStatusCode.OK, - Content = new StringContent(JsonConvert.SerializeObject(responseObj)) - }; - var httpClient = TestHelpers.GetTestHttpClient(httpResponse); - var restClient = new RestClient(GOOD_PUBLICKEY, GOOD_URLENDPOINT, httpClient); - var ex = Assert.ThrowsAsync(async () => await restClient.MoveFileAsync(model)); - Assert.Equal(ErrorMessages.InvalidSourceValue, ex.Result.Message); - } - - [Fact] - public void Missing_Destination_MoveFileException() - { - MoveFileRequest model = new MoveFileRequest - { - sourceFilePath = "abc" - }; - var responseObj = TestHelpers.ImagekitResponseFaker.Generate(); - - var httpResponse = new HttpResponseMessage - { - StatusCode = HttpStatusCode.OK, - Content = new StringContent(JsonConvert.SerializeObject(responseObj)) - }; - var httpClient = TestHelpers.GetTestHttpClient(httpResponse); - var restClient = new RestClient(GOOD_PUBLICKEY, GOOD_URLENDPOINT, httpClient); - var ex = Assert.ThrowsAsync(async () => await restClient.MoveFileAsync(model)); - Assert.Equal(ErrorMessages.InvalidDestinationValue, ex.Result.Message); - } - - [Fact] - public void RenameFile_Default() - { - RenameFileRequest model = new RenameFileRequest - { - filePath = "Tst3", - newFileName = "Tst4", - purgeCache = false - }; - - var responseObj = TestHelpers.ImagekitResponseFaker.Generate(); - var httpResponse = new HttpResponseMessage - { - StatusCode = HttpStatusCode.OK, - Content = new StringContent(JsonConvert.SerializeObject(responseObj)) - }; - var httpClient = TestHelpers.GetTestHttpClient(httpResponse); - var restClient = new RestClient(GOOD_PUBLICKEY, GOOD_URLENDPOINT, httpClient); - - var response = restClient.RenameFileAsync(model).Result; - var responseObj1 = JsonConvert.SerializeObject(responseObj); - Assert.Equal(responseObj1, response.Raw); - } - - - [Fact] - public void Missing_FilePath_RenameFileException() - { - RenameFileRequest model = new RenameFileRequest - { - newFileName = "test" - }; - var responseObj = TestHelpers.ImagekitResponseFaker.Generate(); - - var httpResponse = new HttpResponseMessage - { - StatusCode = HttpStatusCode.OK, - Content = new StringContent(JsonConvert.SerializeObject(responseObj)) - }; - var httpClient = TestHelpers.GetTestHttpClient(httpResponse); - var restClient = new RestClient(GOOD_PUBLICKEY, GOOD_URLENDPOINT, httpClient); - var ex = Assert.ThrowsAsync(async () => await restClient.RenameFileAsync(model)); - Assert.Equal(ErrorMessages.InvalidRenameFilePathValue, ex.Result.Message); - } - [Fact] - public void Missing_NewFileName_RenameFileException() - { - RenameFileRequest model = new RenameFileRequest - { - filePath = "test" - }; - var responseObj = TestHelpers.ImagekitResponseFaker.Generate(); - - var httpResponse = new HttpResponseMessage - { - StatusCode = HttpStatusCode.OK, - Content = new StringContent(JsonConvert.SerializeObject(responseObj)) - }; - var httpClient = TestHelpers.GetTestHttpClient(httpResponse); - var restClient = new RestClient(GOOD_PUBLICKEY, GOOD_URLENDPOINT, httpClient); - var ex = Assert.ThrowsAsync(async () => await restClient.RenameFileAsync(model)); - Assert.Equal(ErrorMessages.InvalidRenameNewFileNameValue, ex.Result.Message); - } - - - - - [Fact] - public void GetFileVersions_Default() - { - var responseObj = TestHelpers.ImagekitResponseFaker.Generate(); - var httpResponse = new HttpResponseMessage - { - StatusCode = HttpStatusCode.OK, - Content = new StringContent(JsonConvert.SerializeObject(responseObj)) - }; - var httpClient = TestHelpers.GetTestHttpClient(httpResponse); - var restClient = new RestClient(GOOD_PUBLICKEY, GOOD_URLENDPOINT, httpClient); - - var response = restClient.GetFileVersionsAsync("abc").Result; - var responseObj1 = JsonConvert.SerializeObject(responseObj); - Assert.Equal(responseObj1, response.Raw); - } - - - - [Fact] - public void MISSING_FILE_ID_FileVersionsException() - { - - var responseObj = TestHelpers.ImagekitResponseFaker.Generate(); - - var httpResponse = new HttpResponseMessage - { - StatusCode = HttpStatusCode.OK, - Content = new StringContent(JsonConvert.SerializeObject(responseObj)) - }; - var httpClient = TestHelpers.GetTestHttpClient(httpResponse); - var restClient = new RestClient(GOOD_PUBLICKEY, GOOD_URLENDPOINT, httpClient); - var ex = Assert.ThrowsAsync(async () => await restClient.GetFileVersionsAsync("")); - Assert.Equal(ErrorMessages.FileIdMissing, ex.Result.Message); - } - [Fact] - public void RestoreFileVersion_Default() - { - var responseObj = TestHelpers.ImagekitResponseFaker.Generate(); - var httpResponse = new HttpResponseMessage - { - StatusCode = HttpStatusCode.OK, - Content = new StringContent(JsonConvert.SerializeObject(responseObj)) - }; - var httpClient = TestHelpers.GetTestHttpClient(httpResponse); - var restClient = new RestClient(GOOD_PUBLICKEY, GOOD_URLENDPOINT, httpClient); - - var response = (Result)restClient.RestoreFileVersionAsync("abc", "1").Result; - var responseObj1 = JsonConvert.SerializeObject(responseObj); - Assert.Equal(responseObj1, response.Raw); - } - - - [Fact] - public void Missing_Restore_File_Exception() - { - - var responseObj = TestHelpers.ImagekitResponseFaker.Generate(); - - var httpResponse = new HttpResponseMessage - { - StatusCode = HttpStatusCode.OK, - Content = new StringContent(JsonConvert.SerializeObject(responseObj)) - }; - var httpClient = TestHelpers.GetTestHttpClient(httpResponse); - var restClient = new RestClient(GOOD_PUBLICKEY, GOOD_URLENDPOINT, httpClient); - var ex = Assert.ThrowsAsync(async () => await restClient.RestoreFileVersionAsync("", "123")); - Assert.Equal(ErrorMessages.InvalidFieldIdDelVerValue, ex.Result.Message); - } - [Fact] - public void Missing_Restore_Version_Exception() - { - - var responseObj = TestHelpers.ImagekitResponseFaker.Generate(); - - var httpResponse = new HttpResponseMessage - { - StatusCode = HttpStatusCode.OK, - Content = new StringContent(JsonConvert.SerializeObject(responseObj)) - }; - var httpClient = TestHelpers.GetTestHttpClient(httpResponse); - var restClient = new RestClient(GOOD_PUBLICKEY, GOOD_URLENDPOINT, httpClient); - var ex = Assert.ThrowsAsync(async () => await restClient.RestoreFileVersionAsync("123", "")); - Assert.Equal(ErrorMessages.InvalidversionIdDelVerValue, ex.Result.Message); - } - - [Fact] - public void Missing_Restore_File_Version_Exception() - { - - var responseObj = TestHelpers.ImagekitResponseFaker.Generate(); - - var httpResponse = new HttpResponseMessage - { - StatusCode = HttpStatusCode.OK, - Content = new StringContent(JsonConvert.SerializeObject(responseObj)) - }; - var httpClient = TestHelpers.GetTestHttpClient(httpResponse); - var restClient = new RestClient(GOOD_PUBLICKEY, GOOD_URLENDPOINT, httpClient); - var ex = Assert.ThrowsAsync(async () => await restClient.RestoreFileVersionAsync("", "")); - Assert.Equal(ErrorMessages.InvalidDelVerValue, ex.Result.Message); - } - [Fact] - public void GetFileVersionDetails_Default() - { - var responseObj = TestHelpers.ImagekitResponseFaker.Generate(); - var httpResponse = new HttpResponseMessage - { - StatusCode = HttpStatusCode.OK, - Content = new StringContent(JsonConvert.SerializeObject(responseObj)) - }; - var httpClient = TestHelpers.GetTestHttpClient(httpResponse); - var restClient = new RestClient(GOOD_PUBLICKEY, GOOD_URLENDPOINT, httpClient); - - var response = restClient.GetFileVersionDetailsAsync("abc", "1").Result; - var responseObj1 = JsonConvert.SerializeObject(responseObj); - Assert.Equal(responseObj1, response.Raw); - } - [Fact] - public void Missing_FileVersionDetailsException() - { - - var responseObj = TestHelpers.ImagekitResponseFaker.Generate(); - - var httpResponse = new HttpResponseMessage - { - StatusCode = HttpStatusCode.OK, - Content = new StringContent(JsonConvert.SerializeObject(responseObj)) - }; - var httpClient = TestHelpers.GetTestHttpClient(httpResponse); - var restClient = new RestClient(GOOD_PUBLICKEY, GOOD_URLENDPOINT, httpClient); - var ex = Assert.ThrowsAsync(async () => await restClient.GetFileVersionDetailsAsync("", "")); - Assert.Equal(ErrorMessages.InvalidDelVerValue, ex.Result.Message); - } - [Fact] - public void Missing_FileDetails_Exception() - { - - var responseObj = TestHelpers.ImagekitResponseFaker.Generate(); - - var httpResponse = new HttpResponseMessage - { - StatusCode = HttpStatusCode.OK, - Content = new StringContent(JsonConvert.SerializeObject(responseObj)) - }; - var httpClient = TestHelpers.GetTestHttpClient(httpResponse); - var restClient = new RestClient(GOOD_PUBLICKEY, GOOD_URLENDPOINT, httpClient); - var ex = Assert.ThrowsAsync(async () => await restClient.RestoreFileVersionAsync("", "123")); - Assert.Equal(ErrorMessages.InvalidFieldIdDelVerValue, ex.Result.Message); - } - [Fact] - public void Missing_VersionDetails_Exception() - { - - var responseObj = TestHelpers.ImagekitResponseFaker.Generate(); - - var httpResponse = new HttpResponseMessage - { - StatusCode = HttpStatusCode.OK, - Content = new StringContent(JsonConvert.SerializeObject(responseObj)) - }; - var httpClient = TestHelpers.GetTestHttpClient(httpResponse); - var restClient = new RestClient(GOOD_PUBLICKEY, GOOD_URLENDPOINT, httpClient); - var ex = Assert.ThrowsAsync(async () => await restClient.RestoreFileVersionAsync("123", "")); - Assert.Equal(ErrorMessages.InvalidversionIdDelVerValue, ex.Result.Message); - } - } -} - - - - diff --git a/Imagekit.UnitTests/FileVersion/FileVersionTestNonAsync.cs b/Imagekit.UnitTests/FileVersion/FileVersionTestNonAsync.cs deleted file mode 100644 index 2e90db7c..00000000 --- a/Imagekit.UnitTests/FileVersion/FileVersionTestNonAsync.cs +++ /dev/null @@ -1,482 +0,0 @@ -using Imagekit.Constant; -using Imagekit.Models; -using Newtonsoft.Json; -using System; -using System.Net; -using System.Net.Http; -using Xunit; - -namespace Imagekit.UnitTests.FileVersion -{ - - public class FileVersionTestNonAsync - - { - private const string GOOD_PUBLICKEY = "abc"; - private const string GOOD_URLENDPOINT = "https://dasdsad.dad.io/"; - - - [Fact] - public void Missing_Object_FileVersionException_NonAsync() - { - DeleteFileVersionRequest model = null; - var responseObj = TestHelpers.ImagekitResponseFaker.Generate(); - - var httpResponse = new HttpResponseMessage - { - StatusCode = HttpStatusCode.OK, - Content = new StringContent(JsonConvert.SerializeObject(responseObj)) - }; - var httpClient = TestHelpers.GetTestHttpClient(httpResponse); - var restClient = new RestClient(GOOD_PUBLICKEY, GOOD_URLENDPOINT, httpClient); - var ex = Assert.Throws(() => restClient.DeleteFileVersion(model)); - Assert.Equal(ErrorMessages.InvalidDelVerValue, ex.Message); - } - [Fact] - public void Missing_fileId_FileVersionException_NonAsync() - { - DeleteFileVersionRequest model = new DeleteFileVersionRequest - { - versionId = "abc" - }; - var responseObj = TestHelpers.ImagekitResponseFaker.Generate(); - - var httpResponse = new HttpResponseMessage - { - StatusCode = HttpStatusCode.OK, - Content = new StringContent(JsonConvert.SerializeObject(responseObj)) - }; - var httpClient = TestHelpers.GetTestHttpClient(httpResponse); - var restClient = new RestClient(GOOD_PUBLICKEY, GOOD_URLENDPOINT, httpClient); - var ex = Assert.Throws(() => restClient.DeleteFileVersion(model)); - Assert.Equal(ErrorMessages.InvalidFieldIdDelVerValue, ex.Message); - } - - [Fact] - public void Missing_versionId_FileVersionException_NonAsync() - { - DeleteFileVersionRequest model = new DeleteFileVersionRequest - { - versionId = "", - fileId = "sas" - }; - var responseObj = TestHelpers.ImagekitResponseFaker.Generate(); - - var httpResponse = new HttpResponseMessage - { - StatusCode = HttpStatusCode.OK, - Content = new StringContent(JsonConvert.SerializeObject(responseObj)) - }; - var httpClient = TestHelpers.GetTestHttpClient(httpResponse); - var restClient = new RestClient(GOOD_PUBLICKEY, GOOD_URLENDPOINT, httpClient); - var ex = Assert.Throws(() => restClient.DeleteFileVersion(model)); - Assert.Equal(ErrorMessages.InvalidversionIdDelVerValue, ex.Message); - } - - [Fact] - public void CopyFile_Default_NonAsync() - { - CopyFileRequest model = new CopyFileRequest - { - sourceFilePath = "Tst3", - destinationPath = "Tst3", - includeFileVersions = true - }; - var responseObj = TestHelpers.ImagekitResponseFaker.Generate(); - var httpResponse = new HttpResponseMessage - { - StatusCode = HttpStatusCode.OK, - Content = new StringContent(JsonConvert.SerializeObject(responseObj)) - }; - var httpClient = TestHelpers.GetTestHttpClient(httpResponse); - var restClient = new RestClient(GOOD_PUBLICKEY, GOOD_URLENDPOINT, httpClient); - - var response = restClient.CopyFile(model); - var responseObj1 = JsonConvert.SerializeObject(responseObj); - Assert.Equal(responseObj1, response.Raw); - } - - - [Fact] - public void Missing_Obj_CopyFileException_NonAsync() - { - CopyFileRequest model = null; - var responseObj = TestHelpers.ImagekitResponseFaker.Generate(); - - var httpResponse = new HttpResponseMessage - { - StatusCode = HttpStatusCode.OK, - Content = new StringContent(JsonConvert.SerializeObject(responseObj)) - }; - var httpClient = TestHelpers.GetTestHttpClient(httpResponse); - var restClient = new RestClient(GOOD_PUBLICKEY, GOOD_URLENDPOINT, httpClient); - var ex = Assert.Throws(() => restClient.CopyFile(model)); - Assert.Equal(ErrorMessages.InvalidCopyValue, ex.Message); - } - - - - [Fact] - public void Missing_Source_CopyFileException_NonAsync() - { - CopyFileRequest model = new CopyFileRequest - { - destinationPath = "abc" - }; - var responseObj = TestHelpers.ImagekitResponseFaker.Generate(); - - var httpResponse = new HttpResponseMessage - { - StatusCode = HttpStatusCode.OK, - Content = new StringContent(JsonConvert.SerializeObject(responseObj)) - }; - var httpClient = TestHelpers.GetTestHttpClient(httpResponse); - var restClient = new RestClient(GOOD_PUBLICKEY, GOOD_URLENDPOINT, httpClient); - var ex = Assert.Throws(() => restClient.CopyFile(model)); - Assert.Equal(ErrorMessages.InvalidSourceValue, ex.Message); - } - - [Fact] - public void Missing_Destination_CopyFileException_NonAsync() - { - CopyFileRequest model = new CopyFileRequest - { - sourceFilePath = "abc" - }; - var responseObj = TestHelpers.ImagekitResponseFaker.Generate(); - - var httpResponse = new HttpResponseMessage - { - StatusCode = HttpStatusCode.OK, - Content = new StringContent(JsonConvert.SerializeObject(responseObj)) - }; - var httpClient = TestHelpers.GetTestHttpClient(httpResponse); - var restClient = new RestClient(GOOD_PUBLICKEY, GOOD_URLENDPOINT, httpClient); - var ex = Assert.Throws(() => restClient.CopyFile(model)); - Assert.Equal(ErrorMessages.InvalidDestinationValue, ex.Message); - } - - [Fact] - public void MoveFile_Default_NonAsync() - { - MoveFileRequest model = new MoveFileRequest - { - sourceFilePath = "Tst3", - destinationPath = "Tst3" - }; - - var responseObj = TestHelpers.ImagekitResponseFaker.Generate(); - var httpResponse = new HttpResponseMessage - { - StatusCode = HttpStatusCode.OK, - Content = new StringContent(JsonConvert.SerializeObject(responseObj)) - }; - var httpClient = TestHelpers.GetTestHttpClient(httpResponse); - var restClient = new RestClient(GOOD_PUBLICKEY, GOOD_URLENDPOINT, httpClient); - - var response = restClient.MoveFile(model); - var responseObj1 = JsonConvert.SerializeObject(responseObj); - Assert.Equal(responseObj1, response.Raw); - } - - - [Fact] - public void Missing_Obj_MoveFileException_NonAsync() - { - MoveFileRequest model = null; - var responseObj = TestHelpers.ImagekitResponseFaker.Generate(); - - var httpResponse = new HttpResponseMessage - { - StatusCode = HttpStatusCode.OK, - Content = new StringContent(JsonConvert.SerializeObject(responseObj)) - }; - var httpClient = TestHelpers.GetTestHttpClient(httpResponse); - var restClient = new RestClient(GOOD_PUBLICKEY, GOOD_URLENDPOINT, httpClient); - var ex = Assert.Throws(() => restClient.MoveFile(model)); - Assert.Equal(ErrorMessages.InvalidCopyValue, ex.Message); - } - - [Fact] - public void Missing_Source_MoveFileException_NonAsync() - { - MoveFileRequest model = new MoveFileRequest - { - destinationPath = "abc" - }; - var responseObj = TestHelpers.ImagekitResponseFaker.Generate(); - - var httpResponse = new HttpResponseMessage - { - StatusCode = HttpStatusCode.OK, - Content = new StringContent(JsonConvert.SerializeObject(responseObj)) - }; - var httpClient = TestHelpers.GetTestHttpClient(httpResponse); - var restClient = new RestClient(GOOD_PUBLICKEY, GOOD_URLENDPOINT, httpClient); - var ex = Assert.Throws(() => restClient.MoveFile(model)); - Assert.Equal(ErrorMessages.InvalidSourceValue, ex.Message); - } - - [Fact] - public void Missing_Destination_MoveFileException_NonAsync() - { - MoveFileRequest model = new MoveFileRequest - { - sourceFilePath = "abc" - }; - var responseObj = TestHelpers.ImagekitResponseFaker.Generate(); - - var httpResponse = new HttpResponseMessage - { - StatusCode = HttpStatusCode.OK, - Content = new StringContent(JsonConvert.SerializeObject(responseObj)) - }; - var httpClient = TestHelpers.GetTestHttpClient(httpResponse); - var restClient = new RestClient(GOOD_PUBLICKEY, GOOD_URLENDPOINT, httpClient); - var ex = Assert.Throws(() => restClient.MoveFile(model)); - Assert.Equal(ErrorMessages.InvalidDestinationValue, ex.Message); - } - - [Fact] - public void RenameFile_Default_NonAsync() - { - RenameFileRequest model = new RenameFileRequest - { - filePath = "Tst3", - newFileName = "Tst4", - purgeCache = false - }; - - var responseObj = TestHelpers.ImagekitResponseFaker.Generate(); - var httpResponse = new HttpResponseMessage - { - StatusCode = HttpStatusCode.OK, - Content = new StringContent(JsonConvert.SerializeObject(responseObj)) - }; - var httpClient = TestHelpers.GetTestHttpClient(httpResponse); - var restClient = new RestClient(GOOD_PUBLICKEY, GOOD_URLENDPOINT, httpClient); - - var response = restClient.RenameFile(model); - var responseObj1 = JsonConvert.SerializeObject(responseObj); - Assert.Equal(responseObj1, response.Raw); - } - - - [Fact] - public void Missing_FilePath_RenameFileException_NonAsync() - { - RenameFileRequest model = new RenameFileRequest - { - newFileName = "test" - }; - var responseObj = TestHelpers.ImagekitResponseFaker.Generate(); - - var httpResponse = new HttpResponseMessage - { - StatusCode = HttpStatusCode.OK, - Content = new StringContent(JsonConvert.SerializeObject(responseObj)) - }; - var httpClient = TestHelpers.GetTestHttpClient(httpResponse); - var restClient = new RestClient(GOOD_PUBLICKEY, GOOD_URLENDPOINT, httpClient); - var ex = Assert.Throws(() => restClient.RenameFile(model)); - Assert.Equal(ErrorMessages.InvalidRenameFilePathValue, ex.Message); - } - [Fact] - public void Missing_NewFileName_RenameFileException_NonAsync() - { - RenameFileRequest model = new RenameFileRequest - { - filePath = "test" - }; - var responseObj = TestHelpers.ImagekitResponseFaker.Generate(); - - var httpResponse = new HttpResponseMessage - { - StatusCode = HttpStatusCode.OK, - Content = new StringContent(JsonConvert.SerializeObject(responseObj)) - }; - var httpClient = TestHelpers.GetTestHttpClient(httpResponse); - var restClient = new RestClient(GOOD_PUBLICKEY, GOOD_URLENDPOINT, httpClient); - var ex = Assert.Throws(() => restClient.RenameFile(model)); - Assert.Equal(ErrorMessages.InvalidRenameNewFileNameValue, ex.Message); - } - - - - - [Fact] - public void GetFileVersions_Default_NonAsync() - { - var responseObj = TestHelpers.ImagekitResponseFaker.Generate(); - var httpResponse = new HttpResponseMessage - { - StatusCode = HttpStatusCode.OK, - Content = new StringContent(JsonConvert.SerializeObject(responseObj)) - }; - var httpClient = TestHelpers.GetTestHttpClient(httpResponse); - var restClient = new RestClient(GOOD_PUBLICKEY, GOOD_URLENDPOINT, httpClient); - - var response = restClient.GetFileVersions("abc"); - var responseObj1 = JsonConvert.SerializeObject(responseObj); - Assert.Equal(responseObj1, response.Raw); - } - - - - [Fact] - public void MISSING_FILE_ID_FileVersionsException_NonAsync() - { - - var responseObj = TestHelpers.ImagekitResponseFaker.Generate(); - - var httpResponse = new HttpResponseMessage - { - StatusCode = HttpStatusCode.OK, - Content = new StringContent(JsonConvert.SerializeObject(responseObj)) - }; - var httpClient = TestHelpers.GetTestHttpClient(httpResponse); - var restClient = new RestClient(GOOD_PUBLICKEY, GOOD_URLENDPOINT, httpClient); - var ex = Assert.Throws(() => restClient.GetFileVersions("")); - Assert.Equal(ErrorMessages.FileIdMissing, ex.Message); - } - [Fact] - public void RestoreFileVersion_Default_NonAsync() - { - var responseObj = TestHelpers.ImagekitResponseFaker.Generate(); - var httpResponse = new HttpResponseMessage - { - StatusCode = HttpStatusCode.OK, - Content = new StringContent(JsonConvert.SerializeObject(responseObj)) - }; - var httpClient = TestHelpers.GetTestHttpClient(httpResponse); - var restClient = new RestClient(GOOD_PUBLICKEY, GOOD_URLENDPOINT, httpClient); - - var response = (Result)restClient.RestoreFileVersion("abc", "1"); - var responseObj1 = JsonConvert.SerializeObject(responseObj); - Assert.Equal(responseObj1, response.Raw); - } - - - [Fact] - public void Missing_Restore_File_Exception_NonAsync() - { - - var responseObj = TestHelpers.ImagekitResponseFaker.Generate(); - - var httpResponse = new HttpResponseMessage - { - StatusCode = HttpStatusCode.OK, - Content = new StringContent(JsonConvert.SerializeObject(responseObj)) - }; - var httpClient = TestHelpers.GetTestHttpClient(httpResponse); - var restClient = new RestClient(GOOD_PUBLICKEY, GOOD_URLENDPOINT, httpClient); - var ex = Assert.Throws(() => restClient.RestoreFileVersion("", "123")); - Assert.Equal(ErrorMessages.InvalidFieldIdDelVerValue, ex.Message); - } - [Fact] - public void Missing_Restore_Version_Exception_NonAsync() - { - - var responseObj = TestHelpers.ImagekitResponseFaker.Generate(); - - var httpResponse = new HttpResponseMessage - { - StatusCode = HttpStatusCode.OK, - Content = new StringContent(JsonConvert.SerializeObject(responseObj)) - }; - var httpClient = TestHelpers.GetTestHttpClient(httpResponse); - var restClient = new RestClient(GOOD_PUBLICKEY, GOOD_URLENDPOINT, httpClient); - var ex = Assert.Throws(() => restClient.RestoreFileVersion("123", "")); - Assert.Equal(ErrorMessages.InvalidversionIdDelVerValue, ex.Message); - } - - [Fact] - public void Missing_Restore_File_Version_Exception_NonAsync() - { - - var responseObj = TestHelpers.ImagekitResponseFaker.Generate(); - - var httpResponse = new HttpResponseMessage - { - StatusCode = HttpStatusCode.OK, - Content = new StringContent(JsonConvert.SerializeObject(responseObj)) - }; - var httpClient = TestHelpers.GetTestHttpClient(httpResponse); - var restClient = new RestClient(GOOD_PUBLICKEY, GOOD_URLENDPOINT, httpClient); - var ex = Assert.Throws(() => restClient.RestoreFileVersion("", "")); - Assert.Equal(ErrorMessages.InvalidDelVerValue, ex.Message); - } - [Fact] - public void GetFileVersionDetails_Default_NonAsync() - { - var responseObj = TestHelpers.ImagekitResponseFaker.Generate(); - var httpResponse = new HttpResponseMessage - { - StatusCode = HttpStatusCode.OK, - Content = new StringContent(JsonConvert.SerializeObject(responseObj)) - }; - var httpClient = TestHelpers.GetTestHttpClient(httpResponse); - var restClient = new RestClient(GOOD_PUBLICKEY, GOOD_URLENDPOINT, httpClient); - - var response = restClient.GetFileVersionDetails("abc", "1"); - var responseObj1 = JsonConvert.SerializeObject(responseObj); - Assert.Equal(responseObj1, response.Raw); - } - [Fact] - public void Missing_FileVersionDetailsException_NonAsync() - { - - var responseObj = TestHelpers.ImagekitResponseFaker.Generate(); - - var httpResponse = new HttpResponseMessage - { - StatusCode = HttpStatusCode.OK, - Content = new StringContent(JsonConvert.SerializeObject(responseObj)) - }; - var httpClient = TestHelpers.GetTestHttpClient(httpResponse); - var restClient = new RestClient(GOOD_PUBLICKEY, GOOD_URLENDPOINT, httpClient); - var ex = Assert.Throws(() => restClient.GetFileVersionDetails("", "")); - Assert.Equal(ErrorMessages.InvalidDelVerValue, ex.Message); - } - [Fact] - public void Missing_FileDetails_Exception_NonAsync() - { - - var responseObj = TestHelpers.ImagekitResponseFaker.Generate(); - - var httpResponse = new HttpResponseMessage - { - StatusCode = HttpStatusCode.OK, - Content = new StringContent(JsonConvert.SerializeObject(responseObj)) - }; - var httpClient = TestHelpers.GetTestHttpClient(httpResponse); - var restClient = new RestClient(GOOD_PUBLICKEY, GOOD_URLENDPOINT, httpClient); - var ex = Assert.Throws(() => restClient.RestoreFileVersion("", "123")); - Assert.Equal(ErrorMessages.InvalidFieldIdDelVerValue, ex.Message); - } - [Fact] - public void Missing_VersionDetails_Exception_NonAsync() - { - - var responseObj = TestHelpers.ImagekitResponseFaker.Generate(); - - var httpResponse = new HttpResponseMessage - { - StatusCode = HttpStatusCode.OK, - Content = new StringContent(JsonConvert.SerializeObject(responseObj)) - }; - var httpClient = TestHelpers.GetTestHttpClient(httpResponse); - var restClient = new RestClient(GOOD_PUBLICKEY, GOOD_URLENDPOINT, httpClient); - var ex = Assert.Throws(() => restClient.RestoreFileVersion("123", "")); - Assert.Equal(ErrorMessages.InvalidversionIdDelVerValue, ex.Message); - } - - - - - } -} - - - - diff --git a/Imagekit.UnitTests/ImageKitRequestModelValidation.cs b/Imagekit.UnitTests/ImageKitRequestModelValidation.cs deleted file mode 100644 index 67028bcf..00000000 --- a/Imagekit.UnitTests/ImageKitRequestModelValidation.cs +++ /dev/null @@ -1,850 +0,0 @@ -using Imagekit.Constant; -using Imagekit.Models; -using System; -using System.Collections; -using System.Collections.Generic; -using System.Net.Http; -using Xunit; -using RichardSzalay.MockHttp; -using Imagekit.Helper; -using static Imagekit.Models.CustomMetaDataFieldSchemaObject; - -namespace Imagekit.UnitTests -{ - public class ImageKitRequestModelValidation - { - - private const string GOOD_PRIVATEKEY = "private_key"; - private const string GOOD_URLENDPOINT = "https://endpoint_url.io/"; - - [Fact] - public void UploadFileRequest_ModelValidation() - { - string json = "--ImageKit-dLV9Wyq26L\r\nContent-Type: text/plain; charset=utf-8\r\nContent-Disposition: form-data; name=fileName\r\n\r\ntest.jpg\r\n--ImageKit-dLV9Wyq26L\r\nContent-Type: text/plain; charset=utf-8\r\nContent-Disposition: form-data; name=file\r\n\r\nhttps://homepages.cae.wisc.edu/~ece533/images/cat.png\r\n--ImageKit-dLV9Wyq26L\r\nContent-Type: text/plain; charset=utf-8\r\nContent-Disposition: form-data; name=useUniqueFileName\r\n\r\ntrue\r\n--ImageKit-dLV9Wyq26L\r\nContent-Type: text/plain; charset=utf-8\r\nContent-Disposition: form-data; name=tags\r\n\r\nSoftware,Developer,Engineer\r\n--ImageKit-dLV9Wyq26L\r\nContent-Type: text/plain; charset=utf-8\r\nContent-Disposition: form-data; name=folder\r\n\r\ndummy-folder\r\n--ImageKit-dLV9Wyq26L\r\nContent-Type: text/plain; charset=utf-8\r\nContent-Disposition: form-data; name=customCoordinates\r\n\r\n10,10,20,20\r\n--ImageKit-dLV9Wyq26L\r\nContent-Type: text/plain; charset=utf-8\r\nContent-Disposition: form-data; name=overwriteFile\r\n\r\ntrue\r\n--ImageKit-dLV9Wyq26L\r\nContent-Type: text/plain; charset=utf-8\r\nContent-Disposition: form-data; name=overwriteAITags\r\n\r\ntrue\r\n--ImageKit-dLV9Wyq26L\r\nContent-Type: text/plain; charset=utf-8\r\nContent-Disposition: form-data; name=overwriteTags\r\n\r\ntrue\r\n--ImageKit-dLV9Wyq26L\r\nContent-Type: text/plain; charset=utf-8\r\nContent-Disposition: form-data; name=overwriteCustomMetadata\r\n\r\nfalse\r\n--ImageKit-dLV9Wyq26L\r\nContent-Type: text/plain; charset=utf-8\r\nContent-Disposition: form-data; name=extensions\r\n\r\n[{\"options\":{\"add_shadow\":true,\"semitransparency\":false,\"bg_image_url\":\"http://www.google.com/images/logos/ps_logo2.png\"},\"name\":\"remove-bg\"},{\"minConfidence\":95,\"maxTags\":5,\"name\":\"google-auto-tagging\"}]\r\n--ImageKit-dLV9Wyq26L\r\nContent-Type: text/plain; charset=utf-8\r\nContent-Disposition: form-data; name=webhookUrl\r\n\r\nhttps://webhook.site/c78d617f-33bc-40d9-9e61-608999721e2e\r\n--ImageKit-dLV9Wyq26L\r\nContent-Type: text/plain; charset=utf-8\r\nContent-Disposition: form-data; name=customMetadata\r\n\r\n{\"price\":2000}\r\n--ImageKit-dLV9Wyq26L--\r\n"; - string url = "https://upload.imagekit.io/api/v1/files/upload"; - FileCreateRequest ob = new FileCreateRequest - { - file = "https://homepages.cae.wisc.edu/~ece533/images/cat.png", - fileName = "test.jpg", - }; - List tags = new List - { - "Software", - "Developer", - "Engineer" - }; - ob.tags = tags; - - string customCoordinates = "10,10,20,20"; - ob.customCoordinates = customCoordinates; - List model1 = new List(); - BackGroundImage bck = new BackGroundImage - { - name = "remove-bg", - options = new options() { add_shadow = true, semitransparency = false, bg_image_url = "http://www.google.com/images/logos/ps_logo2.png" } - }; - AutoTags autoTags = new AutoTags - { - name = "google-auto-tagging", - maxTags = 5, - minConfidence = 95 - }; - model1.Add(bck); - model1.Add(autoTags); - ob.extensions = model1; - ob.webhookUrl = "https://webhook.site/c78d617f-33bc-40d9-9e61-608999721e2e"; - Hashtable model = new Hashtable - { - { "price", 2000 } - }; - ob.customMetadata = model; - ob.useUniqueFileName = true; - ob.folder = "dummy-folder"; - ob.isPrivateFile = false; - ob.overwriteFile = true; - ob.overwriteAITags = true; - ob.overwriteTags = true; - ob.overwriteCustomMetadata = true; - List responseFields = new List - { - "isPrivateFile", - "tags", - "customCoordinates" - }; - var mockHttp = new MockHttpMessageHandler(); - var request = mockHttp.Expect(url) - .With(a => a.Method.Equals(HttpMethod.Post)) - .WithHeaders("Authorization: Basic cHJpdmF0ZV9rZXk6") - .WithContent(json) - .Respond("application/json", "{'name' : 'ImageKit Response'}"); - var client = mockHttp.ToHttpClient(); - RestClient rs = new RestClient(GOOD_PRIVATEKEY, GOOD_URLENDPOINT, client); - var response = rs.Upload(ob); - mockHttp.VerifyNoOutstandingExpectation(); - } - - [Fact] - public void UpdateFileDetail_ModelValidation() - { - string url = string.Format("https://api.imagekit.io/v1/files/{0}/details", "file-Id"); - FileUpdateRequest ob = new FileUpdateRequest - { - fileId = "file-Id", - - }; - List tags = new List - { - "Software", - "Developer", - "Engineer" - }; - ob.tags = tags; - - string customCoordinates = "10,10,20,20"; - ob.customCoordinates = customCoordinates; - List modelExt = new List(); - BackGroundImage bck = new BackGroundImage - { - name = "remove-bg", - options = new options() { add_shadow = true, semitransparency = false, bg_color = "green", bg_image_url = "http://www.google.com/images/logos/ps_logo2.png" } - }; - AutoTags autoTags = new AutoTags - { - name = "google-auto-tagging", - maxTags = 5, - minConfidence = 95 - }; - modelExt.Add(autoTags); - modelExt.Add(bck); - ob.extensions = modelExt; - ob.webhookUrl = "https://webhook.site/c78d617f-33bc-40d9-9e61-608999721e2e"; - Hashtable model = new Hashtable - { - { "price", 2000 } - }; - ob.customMetadata = model; - string result = "{\"fileId\":\"file-Id\",\"webhookUrl\":\"https://webhook.site/c78d617f-33bc-40d9-9e61-608999721e2e\",\"extensions\":[{\"minConfidence\":95,\"maxTags\":5,\"name\":\"google-auto-tagging\"},{\"options\":{\"add_shadow\":true,\"semitransparency\":false,\"bg_color\":\"green\",\"bg_image_url\":\"http://www.google.com/images/logos/ps_logo2.png\"},\"name\":\"remove-bg\"}],\"tags\":[\"Software\",\"Developer\",\"Engineer\"],\"customCoordinates\":\"10,10,20,20\",\"customMetadata\":{\"price\":2000}}"; - var mockHttp = new MockHttpMessageHandler(); - var request = mockHttp.Expect(url) - .WithHeaders("Authorization: Basic cHJpdmF0ZV9rZXk6") - .WithContent(result) - .Respond("application/json", "{'name' : 'ImageKit Response'}"); - - var client = mockHttp.ToHttpClient(); - RestClient rs = new RestClient(GOOD_PRIVATEKEY, GOOD_URLENDPOINT, client); - var response = rs.UpdateFileDetail(ob); - mockHttp.VerifyNoOutstandingExpectation(); - } - - [Fact] - public void GetFileListRequest_ModelValidation() - { - GetFileListRequest ob = new GetFileListRequest - { - Name = "Test", - Limit = 10, - Skip = 20, - Type = "Test", - Path = "Test", - Sort = "Test", - SearchQuery = "Test", - FileType = "Test", - Tags = null - }; - string param = "sort=Test&path=Test&searchQuery=Test&fileType=Test&name=Test&limit=10&skip=20"; - string url = string.Format("https://api.imagekit.io/v1/files/?{0}", param); - - var mockHttp = new MockHttpMessageHandler(); - var request = mockHttp.Expect(url) - .With(a => a.Method.Equals(HttpMethod.Get)) - .WithHeaders("Authorization: Basic cHJpdmF0ZV9rZXk6") - .Respond("application/json", "{'name' : 'ImageKit Response'}"); - - var client = mockHttp.ToHttpClient(); - RestClient rs = new RestClient(GOOD_PRIVATEKEY, GOOD_URLENDPOINT, client); - var response = rs.GetFileListRequest(ob); - mockHttp.VerifyNoOutstandingExpectation(); - } - [Fact] - public void PurgeCache_ModelValidation() - { - string url = string.Format("https://api.imagekit.io/v1/files/purge"); - string reqJosn = "{\"url\":\"path\"}"; - var mockHttp = new MockHttpMessageHandler(); - var request = mockHttp.Expect(url) - .With(a => a.Method.Equals(HttpMethod.Post)) - .WithHeaders("Authorization: Basic cHJpdmF0ZV9rZXk6") - .WithContent(reqJosn) - .Respond("application/json", "{'name' : 'ImageKit Response'}"); - - var client = mockHttp.ToHttpClient(); - RestClient rs = new RestClient(GOOD_PRIVATEKEY, GOOD_URLENDPOINT, client); - var response = rs.PurgeCache("path"); - mockHttp.VerifyNoOutstandingExpectation(); - } - [Fact] - public void DeleteFileRequest_ModelValidation() - { - string url = string.Format("https://api.imagekit.io/v1/files/{0}/", "fileId"); - - var mockHttp = new MockHttpMessageHandler(); - var request = mockHttp.Expect(url) - .With(a => a.Method.Equals(HttpMethod.Delete)) - .WithHeaders("Authorization: Basic cHJpdmF0ZV9rZXk6") - .Respond("application/json", "{'name' : 'ImageKit Response'}"); - - var client = mockHttp.ToHttpClient(); - RestClient rs = new RestClient(GOOD_PRIVATEKEY, GOOD_URLENDPOINT, client); - var response = rs.DeleteFile("fileId"); - mockHttp.VerifyNoOutstandingExpectation(); - } - - [Fact] - public void PurgeStatusRequest_ModelValidation() - { - string url = string.Format("https://api.imagekit.io/v1/files/purge/{0}", "purgeRequestId"); - - var mockHttp = new MockHttpMessageHandler(); - var request = mockHttp.Expect(url) - .With(a => a.Method.Equals(HttpMethod.Get)) - .WithHeaders("Authorization: Basic cHJpdmF0ZV9rZXk6") - .Respond("application/json", "{'name' : 'ImageKit Response'}"); - - var client = mockHttp.ToHttpClient(); - RestClient rs = new RestClient(GOOD_PRIVATEKEY, GOOD_URLENDPOINT, client); - var response = rs.PurgeStatus("purgeRequestId"); - mockHttp.VerifyNoOutstandingExpectation(); - } - - [Fact] - public void GetFileDetailRequest_ModelValidation() - { - string url = string.Format("https://api.imagekit.io/v1/files/{0}/details", "fileId"); - var mockHttp = new MockHttpMessageHandler(); - var request = mockHttp.Expect(url) - .With(a => a.Method.Equals(HttpMethod.Get)) - .WithHeaders("Authorization: Basic cHJpdmF0ZV9rZXk6") - .Respond("application/json", "{'name' : 'ImageKit Response'}"); - - var client = mockHttp.ToHttpClient(); - RestClient rs = new RestClient(GOOD_PRIVATEKEY, GOOD_URLENDPOINT, client); - var response = rs.GetFileDetail("fileId"); - mockHttp.VerifyNoOutstandingExpectation(); - } - - [Fact] - public void BulkDeleteFilesRequest_ModelValidation() - { - string reqJosn = "{\"fileIds\":[\"fileId1\",\"fileId2\"]}"; - - List fileIds = new List - { - "fileId1", - "fileId2" - }; - string url = string.Format("https://api.imagekit.io/v1/files/batch/deleteByfileIds"); - var mockHttp = new MockHttpMessageHandler(); - var request = mockHttp.Expect(url) - .With(a => a.Method.Equals(HttpMethod.Post)) - .WithHeaders("Authorization: Basic cHJpdmF0ZV9rZXk6") - .WithContent(reqJosn) - .Respond("application/json", "{'name' : 'ImageKit Response'}"); - - var client = mockHttp.ToHttpClient(); - RestClient rs = new RestClient(GOOD_PRIVATEKEY, GOOD_URLENDPOINT, client); - var response = rs.BulkDeleteFiles(fileIds); - mockHttp.VerifyNoOutstandingExpectation(); - } - - [Fact] - public void GetFileMetaDataRequest_ModelValidation() - { - string url = string.Format("https://api.imagekit.io/v1/files/{0}/metadata", "fileId"); - var mockHttp = new MockHttpMessageHandler(); - var request = mockHttp.Expect(url) - .With(a => a.Method.Equals(HttpMethod.Get)) - .WithHeaders("Authorization: Basic cHJpdmF0ZV9rZXk6") - .Respond("application/json", "{'name' : 'ImageKit Response'}"); - - var client = mockHttp.ToHttpClient(); - RestClient rs = new RestClient(GOOD_PRIVATEKEY, GOOD_URLENDPOINT, client); - var response = rs.GetFileMetaData("fileId"); - mockHttp.VerifyNoOutstandingExpectation(); - } - - [Fact] - public void GetRemoteFileMetaDataRequest_ModelValidation() - { - string url = string.Format("https://api.imagekit.io/v1/metadata?url={0}", "url"); - var mockHttp = new MockHttpMessageHandler(); - var request = mockHttp.Expect(url) - .With(a => a.Method.Equals(HttpMethod.Get)) - .WithHeaders("Authorization: Basic cHJpdmF0ZV9rZXk6") - .Respond("application/json", "{'name' : 'ImageKit Response'}"); - - var client = mockHttp.ToHttpClient(); - RestClient rs = new RestClient(GOOD_PRIVATEKEY, GOOD_URLENDPOINT, client); - var response = rs.GetRemoteFileMetaData("url"); - mockHttp.VerifyNoOutstandingExpectation(); - } - - [Fact] - public void AddTagsRequest_ModelValidation() - { - string reqJosn = "{\"fileIds\":[\"abc\"],\"tags\":[\"abc\",\"abc\"]}"; - - TagsRequest tagsRequest = new TagsRequest - { - tags = new List - { - "abc", - "abc" - }, - fileIds = new List - { - "abc" - } - }; - string url = "https://api.imagekit.io/v1/files/addTags"; - var mockHttp = new MockHttpMessageHandler(); - var request = mockHttp.Expect(url) - .With(a => a.Method.Equals(HttpMethod.Post)) - .WithHeaders("Authorization: Basic cHJpdmF0ZV9rZXk6") - .WithContent(reqJosn) - .Respond("application/json", "{'name' : 'ImageKit Response'}"); - - var client = mockHttp.ToHttpClient(); - RestClient rs = new RestClient(GOOD_PRIVATEKEY, GOOD_URLENDPOINT, client); - var response = rs.ManageTags(tagsRequest, "addTags"); - mockHttp.VerifyNoOutstandingExpectation(); - } - [Fact] - public void RemoveTagsRequest_ModelValidation() - { - string reqJosn = "{\"fileIds\":[\"abc\"],\"tags\":[\"abc\",\"abc\"]}"; - - TagsRequest tagsRequest = new TagsRequest - { - tags = new List - { - "abc", - "abc" - }, - fileIds = new List - { - "abc" - } - }; - string url = string.Format("https://api.imagekit.io/" + UrlHandler.RemoveTags); - var mockHttp = new MockHttpMessageHandler(); - var request = mockHttp.Expect(url) - .With(a => a.Method.Equals(HttpMethod.Post)) - .WithHeaders("Authorization: Basic cHJpdmF0ZV9rZXk6") - .WithContent(reqJosn) - .Respond("application/json", "{'name' : 'ImageKit Response'}"); - - var client = mockHttp.ToHttpClient(); - RestClient rs = new RestClient(GOOD_PRIVATEKEY, GOOD_URLENDPOINT, client); - var response = rs.ManageTags(tagsRequest, "removeTags"); - mockHttp.VerifyNoOutstandingExpectation(); - } - - [Fact] - public void RemoveAITagsRequest_ModelValidation() - { - string reqJosn = "{\"fileIds\":[\"abc\"],\"AITags\":[\"abc\",\"abc\"]}"; - - AITagsRequest tagsRequest = new AITagsRequest - { - AITags = new List - { - "abc", - "abc" - }, - fileIds = new List - { - "abc" - } - }; - string url = string.Format("https://api.imagekit.io/" + UrlHandler.RemoveAITags); - var mockHttp = new MockHttpMessageHandler(); - var request = mockHttp.Expect(url) - .With(a => a.Method.Equals(HttpMethod.Post)) - .WithHeaders("Authorization: Basic cHJpdmF0ZV9rZXk6") - .WithContent(reqJosn) - .Respond("application/json", "{'name' : 'ImageKit Response'}"); - - var client = mockHttp.ToHttpClient(); - RestClient rs = new RestClient(GOOD_PRIVATEKEY, GOOD_URLENDPOINT, client); - var response = rs.RemoveAITags(tagsRequest); - mockHttp.VerifyNoOutstandingExpectation(); - } - [Fact] - public void GetCustomMetaDataFields_ModelValidation() - { - string url = string.Format("https://api.imagekit.io/v1/customMetadataFields?includeDeleted={0}", true); - var mockHttp = new MockHttpMessageHandler(); - var request = mockHttp.Expect(url) - .With(a => a.Method.Equals(HttpMethod.Get)) - .WithHeaders("Authorization: Basic cHJpdmF0ZV9rZXk6") - .Respond("application/json", "{'name' : 'ImageKit Response'}"); - - var client = mockHttp.ToHttpClient(); - RestClient rs = new RestClient(GOOD_PRIVATEKEY, GOOD_URLENDPOINT, client); - var response = rs.GetCustomMetaDataFields(true); - mockHttp.VerifyNoOutstandingExpectation(); - } - - [Fact] - public void GetCustomMetaDataFieldsEmpty_ModelValidation() - { - string url = string.Format("https://api.imagekit.io/v1/customMetadataFields?includeDeleted={0}", false); - var mockHttp = new MockHttpMessageHandler(); - var request = mockHttp.Expect(url) - .With(a => a.Method.Equals(HttpMethod.Get)) - .WithHeaders("Authorization: Basic cHJpdmF0ZV9rZXk6") - .Respond("application/json", "{'name' : 'ImageKit Response'}"); - - var client = mockHttp.ToHttpClient(); - RestClient rs = new RestClient(GOOD_PRIVATEKEY, GOOD_URLENDPOINT, client); - var response = rs.GetCustomMetaDataFields(); - mockHttp.VerifyNoOutstandingExpectation(); - } - - [Fact] - public void GetCustomMetaDataFieldsFalse_ModelValidation() - { - string url = string.Format("https://api.imagekit.io/v1/customMetadataFields?includeDeleted={0}", false); - var mockHttp = new MockHttpMessageHandler(); - var request = mockHttp.Expect(url) - .With(a => a.Method.Equals(HttpMethod.Get)) - .WithHeaders("Authorization: Basic cHJpdmF0ZV9rZXk6") - .Respond("application/json", "{'name' : 'ImageKit Response'}"); - - var client = mockHttp.ToHttpClient(); - RestClient rs = new RestClient(GOOD_PRIVATEKEY, GOOD_URLENDPOINT, client); - var response = rs.GetCustomMetaDataFields(false); - mockHttp.VerifyNoOutstandingExpectation(); - } - - [Fact] - public void CreateCustomMetaDataFields_ModelValidation() - { - string reqJosn = "{\n \"name\": \"Tst3\",\n \"label\": \"Test3\",\n \"schema\": {\n \"type\": \"Number\",\n \"minValue\": 1000,\n \"maxValue\": 3000,\n \"isValueRequired\": true,\n \"defaultValue\": 2500\n }\n}"; - CustomMetaDataFieldCreateRequest model = new CustomMetaDataFieldCreateRequest - { - name = "Tst3", - label = "Test3" - }; - CustomMetaDataFieldSchemaObject schema = new CustomMetaDataFieldSchemaObject - { - type = "Number", - minValue = 1000, - maxValue = 3000, - isValueRequired = true, - defaultValue = 2500 - - }; - model.schema = schema; - string url = "https://api.imagekit.io/v1/customMetadataFields"; - var mockHttp = new MockHttpMessageHandler(); - var request = mockHttp.Expect(url) - .With(a => a.Method.Equals(HttpMethod.Post)) - .WithHeaders("Authorization: Basic cHJpdmF0ZV9rZXk6") - .WithContent(reqJosn) - .Respond("application/json", "{'name' : 'ImageKit Response'}"); - - var client = mockHttp.ToHttpClient(); - RestClient rs = new RestClient(GOOD_PRIVATEKEY, GOOD_URLENDPOINT, client); - var response = rs.CreateCustomMetaDataFields(model); - mockHttp.VerifyNoOutstandingExpectation(); - } - - [Fact] - public void CreateCustomMetaDataFields2_ModelValidation() - { - string reqJosn = "{\n \"name\": \"Tst3\",\n \"label\": \"Test3\",\n \"schema\": {\n \"type\": \"Number\",\n \"minValue\": 1000,\n \"maxValue\": 3000,\n \"isValueRequired\": false\n }\n}"; - CustomMetaDataFieldCreateRequest model = new CustomMetaDataFieldCreateRequest - { - name = "Tst3", - label = "Test3" - }; - CustomMetaDataFieldSchemaObject schema = new CustomMetaDataFieldSchemaObject - { - type = "Number", - minValue = 1000, - maxValue = 3000 - - }; - model.schema = schema; - string url = "https://api.imagekit.io/v1/customMetadataFields"; - var mockHttp = new MockHttpMessageHandler(); - var request = mockHttp.Expect(url) - .With(a => a.Method.Equals(HttpMethod.Post)) - .WithHeaders("Authorization: Basic cHJpdmF0ZV9rZXk6") - .WithContent(reqJosn) - .Respond("application/json", "{'name' : 'ImageKit Response'}"); - - var client = mockHttp.ToHttpClient(); - RestClient rs = new RestClient(GOOD_PRIVATEKEY, GOOD_URLENDPOINT, client); - var response = rs.CreateCustomMetaDataFields(model); - mockHttp.VerifyNoOutstandingExpectation(); - } - - [Fact] - public void UpdateCustomMetaDataFields_ModelValidation() - { - string reqJosn = "{\n \"schema\": {\n \"type\": \"Number\",\n \"minValue\": 300,\n \"maxValue\": 500\n }\n}"; - CustomMetaDataFieldUpdateRequest requestUpdateModel = new CustomMetaDataFieldUpdateRequest - { - Id = "field_Id", - }; - CustomMetaDataFieldSchemaObject updateschema = new CustomMetaDataFieldSchemaObject - { - type = "Number", - minValue = 300, - maxValue = 500 - }; - requestUpdateModel.schema = updateschema; - - string url = "https://api.imagekit.io/v1/customMetadataFields/field_Id"; - var mockHttp = new MockHttpMessageHandler(); - var request = mockHttp.Expect(url) - .WithHeaders("Authorization: Basic cHJpdmF0ZV9rZXk6") - .WithContent(reqJosn) - .Respond("application/json", "{'name' : 'ImageKit Response'}"); - - var client = mockHttp.ToHttpClient(); - RestClient rs = new RestClient(GOOD_PRIVATEKEY, GOOD_URLENDPOINT, client); - var response = rs.UpdateCustomMetaDataFields(requestUpdateModel); - mockHttp.VerifyNoOutstandingExpectation(); - } - - [Fact] - public void DeleteCustomMetaDataField_ModelValidation() - { - string url = string.Format("https://api.imagekit.io/v1/customMetadataFields/{0}", "id"); - - var mockHttp = new MockHttpMessageHandler(); - var request = mockHttp.Expect(url) - .With(a => a.Method.Equals(HttpMethod.Delete)) - .WithHeaders("Authorization: Basic cHJpdmF0ZV9rZXk6") - .Respond("application/json", "{'name' : 'ImageKit Response'}"); - - var client = mockHttp.ToHttpClient(); - RestClient rs = new RestClient(GOOD_PRIVATEKEY, GOOD_URLENDPOINT, client); - var response = rs.DeleteCustomMetaDataField("id"); - mockHttp.VerifyNoOutstandingExpectation(); - } - - [Fact] - public void DeleteFileVersion_ModelValidation() - { - DeleteFileVersionRequest model = new DeleteFileVersionRequest - { - fileId = "Tst3", - versionId = "Tst3" - }; - string url = string.Format("https://api.imagekit.io/v1/files/{0}/versions/{1}", model.fileId, - model.versionId); - var mockHttp = new MockHttpMessageHandler(); - var request = mockHttp.Expect(url) - .With(a => a.Method.Equals(HttpMethod.Delete)) - .WithHeaders("Authorization: Basic cHJpdmF0ZV9rZXk6") - .Respond("application/json", "{'name' : 'ImageKit Response'}"); - - var client = mockHttp.ToHttpClient(); - RestClient rs = new RestClient(GOOD_PRIVATEKEY, GOOD_URLENDPOINT, client); - var response = rs.DeleteFileVersion(model); - mockHttp.VerifyNoOutstandingExpectation(); - } - - [Fact] - public void CopyFile_ModelValidation() - { - string reqJosn = "{\"sourceFilePath\":\"Tst3\",\"destinationPath\":\"Tst3\",\"includeFileVersions\":false}"; - - CopyFileRequest model = new CopyFileRequest - { - sourceFilePath = "Tst3", - destinationPath = "Tst3" - }; - string url = string.Empty; - url = string.Format("https://api.imagekit.io/v1/files/copy"); - var mockHttp = new MockHttpMessageHandler(); - var request = mockHttp.Expect(url) - .With(a => a.Method.Equals(HttpMethod.Post)) - .WithHeaders("Authorization: Basic cHJpdmF0ZV9rZXk6") - .WithContent(reqJosn) - .Respond("application/json", "{'name' : 'ImageKit Response'}"); - - var client = mockHttp.ToHttpClient(); - RestClient rs = new RestClient(GOOD_PRIVATEKEY, GOOD_URLENDPOINT, client); - var response = rs.CopyFile(model); - mockHttp.VerifyNoOutstandingExpectation(); - } - - [Fact] - public void CopyFile_includeFileVersions_ModelValidation() - { - string reqJosn = "{\"sourceFilePath\":\"Tst3\",\"destinationPath\":\"Tst3\",\"includeFileVersions\":true}"; - - CopyFileRequest model = new CopyFileRequest - { - sourceFilePath = "Tst3", - destinationPath = "Tst3", - includeFileVersions = true - }; - string url = string.Empty; - url = string.Format("https://api.imagekit.io/v1/files/copy"); - var mockHttp = new MockHttpMessageHandler(); - var request = mockHttp.Expect(url) - .With(a => a.Method.Equals(HttpMethod.Post)) - .WithHeaders("Authorization: Basic cHJpdmF0ZV9rZXk6") - .WithContent(reqJosn) - .Respond("application/json", "{'name' : 'ImageKit Response'}"); - - var client = mockHttp.ToHttpClient(); - RestClient rs = new RestClient(GOOD_PRIVATEKEY, GOOD_URLENDPOINT, client); - var response = rs.CopyFile(model); - mockHttp.VerifyNoOutstandingExpectation(); - } - - [Fact] - public void MoveFile_ModelValidation() - { - string reqJosn = "{\"sourceFilePath\":\"Tst3\",\"destinationPath\":\"Tst3\"}"; - MoveFileRequest model = new MoveFileRequest - { - sourceFilePath = "Tst3", - destinationPath = "Tst3" - }; - - string url = string.Empty; - url = string.Format("https://api.imagekit.io/v1/files/move"); - var mockHttp = new MockHttpMessageHandler(); - var request = mockHttp.Expect(url) - .With(a => a.Method.Equals(HttpMethod.Post)) - .WithHeaders("Authorization: Basic cHJpdmF0ZV9rZXk6") - .WithContent(reqJosn) - .Respond("application/json", "{'name' : 'ImageKit Response'}"); - - var client = mockHttp.ToHttpClient(); - RestClient rs = new RestClient(GOOD_PRIVATEKEY, GOOD_URLENDPOINT, client); - var response = rs.MoveFile(model); - mockHttp.VerifyNoOutstandingExpectation(); - } - - [Fact] - public void RenameFile_ModelValidation() - { - string reqJosn = "{\"filePath\":\"Tst3\",\"newFileName\":\"Tst4\",\"purgeCache\":false}"; - RenameFileRequest model = new RenameFileRequest - { - filePath = "Tst3", - newFileName = "Tst4", - purgeCache = false - }; - - string url = string.Empty; - url = string.Format("https://api.imagekit.io/v1/files/rename"); - var mockHttp = new MockHttpMessageHandler(); - var request = mockHttp.Expect(url) - .With(a => a.Method.Equals(HttpMethod.Put)) - .WithHeaders("Authorization: Basic cHJpdmF0ZV9rZXk6") - .WithContent(reqJosn) - .Respond("application/json", "{'name' : 'ImageKit Response'}"); - - var client = mockHttp.ToHttpClient(); - RestClient rs = new RestClient(GOOD_PRIVATEKEY, GOOD_URLENDPOINT, client); - var response = rs.RenameFile(model); - mockHttp.VerifyNoOutstandingExpectation(); - } - - [Fact] - public void RenameFileTrue_ModelValidation() - { - string reqJosn = "{\"filePath\":\"Tst3\",\"newFileName\":\"Tst4\",\"purgeCache\":true}"; - RenameFileRequest model = new RenameFileRequest - { - filePath = "Tst3", - newFileName = "Tst4", - purgeCache = true - }; - - string url = string.Empty; - url = string.Format("https://api.imagekit.io/v1/files/rename"); - var mockHttp = new MockHttpMessageHandler(); - var request = mockHttp.Expect(url) - .With(a => a.Method.Equals(HttpMethod.Put)) - .WithHeaders("Authorization: Basic cHJpdmF0ZV9rZXk6") - .WithContent(reqJosn) - .Respond("application/json", "{'name' : 'ImageKit Response'}"); - - var client = mockHttp.ToHttpClient(); - RestClient rs = new RestClient(GOOD_PRIVATEKEY, GOOD_URLENDPOINT, client); - var response = rs.RenameFile(model); - mockHttp.VerifyNoOutstandingExpectation(); - } - - [Fact] - public void RenameFileDefaultPurge_ModelValidation() - { - string reqJosn = "{\"filePath\":\"Tst3\",\"newFileName\":\"Tst4\",\"purgeCache\":false}"; - RenameFileRequest model = new RenameFileRequest - { - filePath = "Tst3", - newFileName = "Tst4" - }; - - string url = string.Empty; - url = string.Format("https://api.imagekit.io/v1/files/rename"); - var mockHttp = new MockHttpMessageHandler(); - var request = mockHttp.Expect(url) - .With(a => a.Method.Equals(HttpMethod.Put)) - .WithHeaders("Authorization: Basic cHJpdmF0ZV9rZXk6") - .WithContent(reqJosn) - .Respond("application/json", "{'name' : 'ImageKit Response'}"); - - var client = mockHttp.ToHttpClient(); - RestClient rs = new RestClient(GOOD_PRIVATEKEY, GOOD_URLENDPOINT, client); - var response = rs.RenameFile(model); - mockHttp.VerifyNoOutstandingExpectation(); - } - [Fact] - public void CopyFolder_ModelValidation() - { - string reqJosn = "{\"sourceFolderPath\":\"Tst3\",\"destinationPath\":\"Tst3\",\"includeFileVersions\":false}"; - CopyFolderRequest model = new CopyFolderRequest - { - sourceFolderPath = "Tst3", - destinationPath = "Tst3" - - }; - string url = string.Format("https://api.imagekit.io/v1/bulkJobs/copyFolder"); - var mockHttp = new MockHttpMessageHandler(); - var request = mockHttp.Expect(url) - .With(a => a.Method.Equals(HttpMethod.Post)) - .WithHeaders("Authorization: Basic cHJpdmF0ZV9rZXk6") - .WithContent(reqJosn) - .Respond("application/json", "{'name' : 'ImageKit Response'}"); - - var client = mockHttp.ToHttpClient(); - RestClient rs = new RestClient(GOOD_PRIVATEKEY, GOOD_URLENDPOINT, client); - var response = rs.CopyFolder(model); - mockHttp.VerifyNoOutstandingExpectation(); - } - - [Fact] - public void CopyFolder_includeFileVersions_ModelValidation() - { - string reqJosn = "{\"sourceFolderPath\":\"Tst3\",\"destinationPath\":\"Tst3\",\"includeFileVersions\":true}"; - CopyFolderRequest model = new CopyFolderRequest - { - sourceFolderPath = "Tst3", - destinationPath = "Tst3", - includeFileVersions = true - - }; - string url = string.Format("https://api.imagekit.io/v1/bulkJobs/copyFolder"); - var mockHttp = new MockHttpMessageHandler(); - var request = mockHttp.Expect(url) - .With(a => a.Method.Equals(HttpMethod.Post)) - .WithHeaders("Authorization: Basic cHJpdmF0ZV9rZXk6") - .WithContent(reqJosn) - .Respond("application/json", "{'name' : 'ImageKit Response'}"); - - var client = mockHttp.ToHttpClient(); - RestClient rs = new RestClient(GOOD_PRIVATEKEY, GOOD_URLENDPOINT, client); - var response = rs.CopyFolder(model); - mockHttp.VerifyNoOutstandingExpectation(); - } - - [Fact] - public void MoveFolder_ModelValidation() - { - string reqJosn = "{\"sourceFolderPath\":\"Tst3\",\"destinationPath\":\"Tst3\"}"; - MoveFolderRequest model = new MoveFolderRequest - { - sourceFolderPath = "Tst3", - destinationPath = "Tst3" - }; - string url = string.Format("https://api.imagekit.io/v1/bulkJobs/moveFolder"); - var mockHttp = new MockHttpMessageHandler(); - var request = mockHttp.Expect(url) - .With(a => a.Method.Equals(HttpMethod.Post)) - .WithHeaders("Authorization: Basic cHJpdmF0ZV9rZXk6") - .WithContent(reqJosn) - .Respond("application/json", "{'name' : 'ImageKit Response'}"); - - var client = mockHttp.ToHttpClient(); - RestClient rs = new RestClient(GOOD_PRIVATEKEY, GOOD_URLENDPOINT, client); - var response = rs.MoveFolder(model); - mockHttp.VerifyNoOutstandingExpectation(); - } - - - [Fact] - public void GetBulkJobStatus_ModelValidation() - { - string url = string.Format("https://api.imagekit.io/v1/bulkJobs/{0}", "jobId"); - var mockHttp = new MockHttpMessageHandler(); - var request = mockHttp.Expect(url) - .With(a => a.Method.Equals(HttpMethod.Get)) - .WithHeaders("Authorization: Basic cHJpdmF0ZV9rZXk6") - .Respond("application/json", "{'name' : 'ImageKit Response'}"); - - var client = mockHttp.ToHttpClient(); - RestClient rs = new RestClient(GOOD_PRIVATEKEY, GOOD_URLENDPOINT, client); - var response = rs.GetBulkJobStatus("jobId"); - mockHttp.VerifyNoOutstandingExpectation(); - } - [Fact] - public void GetFileVersions_ModelValidation() - { - string url = string.Format("https://api.imagekit.io/v1/files/{0}/versions", "fileId"); - var mockHttp = new MockHttpMessageHandler(); - var request = mockHttp.Expect(url) - .With(a => a.Method.Equals(HttpMethod.Get)) - .WithHeaders("Authorization: Basic cHJpdmF0ZV9rZXk6") - .Respond("application/json", "{'name' : 'ImageKit Response'}"); - - var client = mockHttp.ToHttpClient(); - RestClient rs = new RestClient(GOOD_PRIVATEKEY, GOOD_URLENDPOINT, client); - var response = rs.GetFileVersions("fileId"); - mockHttp.VerifyNoOutstandingExpectation(); - } - - [Fact] - public void GetFileVersionDetails_ModelValidation() - { - string url = string.Format("https://api.imagekit.io/v1/files/{0}/versions/{1}", "fileId", "versionId"); - var mockHttp = new MockHttpMessageHandler(); - var request = mockHttp.Expect(url) - .With(a => a.Method.Equals(HttpMethod.Get)) - .WithHeaders("Authorization: Basic cHJpdmF0ZV9rZXk6") - .Respond("application/json", "{'name' : 'ImageKit Response'}"); - - var client = mockHttp.ToHttpClient(); - RestClient rs = new RestClient(GOOD_PRIVATEKEY, GOOD_URLENDPOINT, client); - var response = rs.GetFileVersionDetails("fileId", "versionId"); - mockHttp.VerifyNoOutstandingExpectation(); - } - - [Fact] - public void RestoreFileVersion_ModelValidation() - { - string url = string.Format("https://api.imagekit.io/v1/files/{0}/versions/{1}/restore", "fileId", "versionId"); - var mockHttp = new MockHttpMessageHandler(); - var request = mockHttp.Expect(url) - .With(a => a.Method.Equals(HttpMethod.Put)) - .WithHeaders("Authorization: Basic cHJpdmF0ZV9rZXk6") - .Respond("application/json", "{'name' : 'ImageKit Response'}"); - - var client = mockHttp.ToHttpClient(); - RestClient rs = new RestClient(GOOD_PRIVATEKEY, GOOD_URLENDPOINT, client); - var response = rs.RestoreFileVersion("fileId", "versionId"); - mockHttp.VerifyNoOutstandingExpectation(); - } - } -} diff --git a/Imagekit.UnitTests/ImageKitTestCasesAsync.cs b/Imagekit.UnitTests/ImageKitTestCasesAsync.cs deleted file mode 100644 index e2722327..00000000 --- a/Imagekit.UnitTests/ImageKitTestCasesAsync.cs +++ /dev/null @@ -1,726 +0,0 @@ -using Imagekit.Constant; -using Imagekit.Sdk; -using Imagekit.Models; -using Newtonsoft.Json; -using System; -using System.Collections.Generic; -using System.Net; -using System.Net.Http; -using Newtonsoft.Json.Linq; -using Xunit; - -namespace Imagekit.UnitTests -{ - - public class ImageKitTestCasesAsync - { - private const string GOOD_PUBLICKEY = "abc"; - private const string GOOD_PRIVATEKEY = "abc"; - private const string GOOD_URLENDPOINT = "https://dasdsad.dad.io/"; - - [Fact] - public void Missing_Key_Exception() - { - - Exception actualException = Assert.Throws(() => new RestClient("", "https://dasdsad.dad.io/", new HttpClient())); - Assert.Equal(ErrorMessages.InvalidKey, actualException.Message); - } - [Fact] - public void Missing_URL_Exception() - { - - Exception actualException = Assert.Throws(() => new RestClient("abc", "", new HttpClient())); - Assert.Equal(ErrorMessages.InvalidApiUrl, actualException.Message); - } - - [Fact] - public void Constructor_TransformationPosition_Default() - { - var imagekit = new ImagekitClient(GOOD_PUBLICKEY, GOOD_PRIVATEKEY, GOOD_URLENDPOINT); - Assert.NotNull(imagekit); - } - - [Fact] - public void GetFileRequest_Default() - { - GetFileListRequest ob = new GetFileListRequest - { - Type = "file", - Limit = 10, - Skip = 0, - Sort = "ASC_CREATED", - SearchQuery = "createdAt >= \"7d\"", - FileType = "image", - Path = "/" - }; - var responseObj = TestHelpers.ImagekitResponseFaker.Generate(); - - var httpResponse = new HttpResponseMessage - { - StatusCode = HttpStatusCode.OK, - Content = new StringContent(JsonConvert.SerializeObject(responseObj)) - }; - var httpClient = TestHelpers.GetTestHttpClient(httpResponse); - var restClient = new RestClient(GOOD_PUBLICKEY, GOOD_URLENDPOINT, httpClient); - - var response = (ResultList)restClient.GetFileListRequestAsync(ob).Result; - var responseObj1 = JsonConvert.SerializeObject(responseObj.Raw); - responseObj1 = JToken.Parse(responseObj1).ToString(); - - Assert.Equal(responseObj.Raw, responseObj1); - } - [Fact] - public async void GetFileRequestByNameWithoutSearchQuery() - { - GetFileListRequest ob = new GetFileListRequest - { - - Name = "file_name.jpg", - - }; - var responseObj = TestHelpers.ImagekitResponseFaker.Generate(); - - var httpResponse = new HttpResponseMessage - { - StatusCode = HttpStatusCode.OK, - Content = new StringContent(JsonConvert.SerializeObject(responseObj)) - }; - var httpClient = TestHelpers.GetTestHttpClient(httpResponse); - var restClient = new RestClient(GOOD_PUBLICKEY, GOOD_URLENDPOINT, httpClient); - - var response = await restClient.GetFileListRequestAsync(ob); - // Console.WriteLine("res",response); - var responseObj1 = JsonConvert.SerializeObject(responseObj.Raw); - responseObj1 = JToken.Parse(responseObj1).ToString(); - - Assert.Equal(responseObj.Raw, responseObj1); - Console.WriteLine(responseObj.Raw); - } - [Fact] - public void GetFileRequestByName() - { - GetFileListRequest ob = new GetFileListRequest - { - - SearchQuery = "name = \"file_name.jpg\"", - - - }; - var responseObj = TestHelpers.ImagekitResponseFaker.Generate(); - - var httpResponse = new HttpResponseMessage - { - StatusCode = HttpStatusCode.OK, - Content = new StringContent(JsonConvert.SerializeObject(responseObj)) - }; - var httpClient = TestHelpers.GetTestHttpClient(httpResponse); - var restClient = new RestClient(GOOD_PUBLICKEY, GOOD_URLENDPOINT, httpClient); - - var response = (ResultList)restClient.GetFileListRequestAsync(ob).Result; - var responseObj1 = JsonConvert.SerializeObject(responseObj.Raw); - responseObj1 = JToken.Parse(responseObj1).ToString(); - - Assert.Equal(responseObj.Raw, responseObj1); - } - [Fact] - public void GetFileRequestByTag() - { - GetFileListRequest ob = new GetFileListRequest - { - - SearchQuery = "tags = \"tag1,tag2\"", - - }; - var responseObj = TestHelpers.ImagekitResponseFaker.Generate(); - - var httpResponse = new HttpResponseMessage - { - StatusCode = HttpStatusCode.OK, - Content = new StringContent(JsonConvert.SerializeObject(responseObj)) - }; - var httpClient = TestHelpers.GetTestHttpClient(httpResponse); - var restClient = new RestClient(GOOD_PUBLICKEY, GOOD_URLENDPOINT, httpClient); - - var response = (ResultList)restClient.GetFileListRequestAsync(ob).Result; - var responseObj1 = JsonConvert.SerializeObject(responseObj.Raw); - responseObj1 = JToken.Parse(responseObj1).ToString(); - - Assert.Equal(responseObj.Raw, responseObj1); - } - [Fact] - public void GetFileRequestWithoutFilter_Default() - { - GetFileListRequest ob = new GetFileListRequest(); - - var responseObj = TestHelpers.ImagekitResponseFaker.Generate(); - - var httpResponse = new HttpResponseMessage - { - StatusCode = HttpStatusCode.OK, - Content = new StringContent(JsonConvert.SerializeObject(responseObj)) - }; - var httpClient = TestHelpers.GetTestHttpClient(httpResponse); - var restClient = new RestClient(GOOD_PUBLICKEY, GOOD_URLENDPOINT, httpClient); - - var response = (ResultList)restClient.GetFileListRequestAsync(ob).Result; - var responseObj1 = JsonConvert.SerializeObject(responseObj.Raw); - responseObj1 = JToken.Parse(responseObj1).ToString(); - - Assert.Equal(responseObj.Raw, responseObj1); - } - - [Fact] - public void GetFileDetail_Default() - { - var responseObj = TestHelpers.ImagekitResponseFaker.Generate(); - - var httpResponse = new HttpResponseMessage - { - StatusCode = HttpStatusCode.OK, - Content = new StringContent(JsonConvert.SerializeObject(responseObj)) - }; - var httpClient = TestHelpers.GetTestHttpClient(httpResponse); - var restClient = new RestClient(GOOD_PUBLICKEY, GOOD_URLENDPOINT, httpClient); - - var response = (Result)restClient.GetFileDetailAsync("abc").Result; - var responseObj1 = JsonConvert.SerializeObject(responseObj); - Assert.Equal(responseObj1, response.Raw); - } - - [Fact] - public void GetFile_ID_Detail_Exception() - { - var responseObj = TestHelpers.ImagekitResponseFaker.Generate(); - - var httpResponse = new HttpResponseMessage - { - StatusCode = HttpStatusCode.OK, - Content = new StringContent(JsonConvert.SerializeObject(responseObj)) - }; - var httpClient = TestHelpers.GetTestHttpClient(httpResponse); - var restClient = new RestClient(GOOD_PUBLICKEY, GOOD_URLENDPOINT, httpClient); - var ex = Assert.ThrowsAsync(async () => await restClient.GetFileDetailAsync("")); - Assert.Equal(ErrorMessages.FileIdMissing, ex.Result.Message); - } - - [Fact] - public void PurgeCache_Default() - { - var responseObj = TestHelpers.ImagekitResponseFaker.Generate(); - - var httpResponse = new HttpResponseMessage - { - StatusCode = HttpStatusCode.OK, - Content = new StringContent(JsonConvert.SerializeObject(responseObj)) - }; - var httpClient = TestHelpers.GetTestHttpClient(httpResponse); - var restClient = new RestClient(GOOD_PUBLICKEY, GOOD_URLENDPOINT, httpClient); - - var response = restClient.PurgeCacheAsync("abc").Result; - var responseObj1 = JsonConvert.SerializeObject(responseObj); - Assert.Equal(responseObj1, response.Raw); - } - [Fact] - public void PurgeStatus_Default() - { - var responseObj = TestHelpers.ImagekitResponseFaker.Generate(); - - var httpResponse = new HttpResponseMessage - { - StatusCode = HttpStatusCode.OK, - Content = new StringContent(JsonConvert.SerializeObject(responseObj)) - }; - var httpClient = TestHelpers.GetTestHttpClient(httpResponse); - var restClient = new RestClient(GOOD_PUBLICKEY, GOOD_URLENDPOINT, httpClient); - - var response = restClient.PurgeStatusAsync("abc").Result; - var responseObj1 = JsonConvert.SerializeObject(responseObj); - Assert.Equal(responseObj1, response.Raw); - } - - [Fact] - public void DeleteFile_Default() - { - var responseObj = TestHelpers.ImagekitResponseFaker.Generate(); - - var httpResponse = new HttpResponseMessage - { - StatusCode = HttpStatusCode.OK, - Content = new StringContent(JsonConvert.SerializeObject(responseObj)) - }; - var httpClient = TestHelpers.GetTestHttpClient(httpResponse); - var restClient = new RestClient(GOOD_PUBLICKEY, GOOD_URLENDPOINT, httpClient); - - var response = (ResultDelete)restClient.DeleteFileAsync("abc").Result; - var responseObj1 = JsonConvert.SerializeObject(responseObj); - Assert.Equal(responseObj1, response.Raw); - } - [Fact] - public void Delete_File_ID_Exception() - { - var responseObj = TestHelpers.ImagekitResponseFaker.Generate(); - - var httpResponse = new HttpResponseMessage - { - StatusCode = HttpStatusCode.OK, - Content = new StringContent(JsonConvert.SerializeObject(responseObj)) - }; - var httpClient = TestHelpers.GetTestHttpClient(httpResponse); - var restClient = new RestClient(GOOD_PUBLICKEY, GOOD_URLENDPOINT, httpClient); - var ex = Assert.ThrowsAsync(async () => await restClient.DeleteFileAsync("")); - Assert.Equal(ErrorMessages.FileIdMissing, ex.Result.Message); - } - - - [Fact] - public void BulkDeleteFiles_Default() - { - List ob = new List - { - "abc", - "abcd" - }; - - var responseObj = TestHelpers.ImagekitResponseFaker.Generate(); - - var httpResponse = new HttpResponseMessage - { - StatusCode = HttpStatusCode.OK, - Content = new StringContent(JsonConvert.SerializeObject(responseObj)) - }; - var httpClient = TestHelpers.GetTestHttpClient(httpResponse); - var restClient = new RestClient(GOOD_PUBLICKEY, GOOD_URLENDPOINT, httpClient); - - var response = (ResultFileDelete)restClient.BulkDeleteFilesAsync(ob).Result; - var responseObj1 = JsonConvert.SerializeObject(responseObj.Raw); - responseObj1=JToken.Parse(responseObj1).ToString(); - Assert.Equal(responseObj.Raw, responseObj1); - } - [Fact] - public void Bulk_Delete_Files_Input_Missing_Exception() - { - List ob = new List(); - var responseObj = TestHelpers.ImagekitResponseFaker.Generate(); - - var httpResponse = new HttpResponseMessage - { - StatusCode = HttpStatusCode.OK, - Content = new StringContent(JsonConvert.SerializeObject(responseObj)) - }; - var httpClient = TestHelpers.GetTestHttpClient(httpResponse); - var restClient = new RestClient(GOOD_PUBLICKEY, GOOD_URLENDPOINT, httpClient); - var ex = Assert.ThrowsAsync(async () => await restClient.BulkDeleteFilesAsync(ob)); - Assert.Equal(ErrorMessages.ListFilesInputMissing, ex.Result.Message); - } - - [Fact] - public void Missing_Filed_Null_Exception() - { - TagsRequest ob = new TagsRequest - { - tags = new List { "abc" }, - fileIds = null - }; - - var responseObj = TestHelpers.ImagekitResponseFaker.Generate(); - - var httpResponse = new HttpResponseMessage - { - StatusCode = HttpStatusCode.OK, - Content = new StringContent(JsonConvert.SerializeObject(responseObj)) - }; - var httpClient = TestHelpers.GetTestHttpClient(httpResponse); - var restClient = new RestClient(GOOD_PUBLICKEY, GOOD_URLENDPOINT, httpClient); - var ex = Assert.ThrowsAsync(async () => await restClient.ManageTagsAsync(ob, "")); - Assert.Equal(ErrorMessages.InvalidFiledParamValue, ex.Result.Message); - } - - - - - [Fact] - public void Missing_Remove_Filed_Null_Exception() - { - TagsRequest ob = new TagsRequest - { - tags = new List { "abc" }, - fileIds = null - }; - - var responseObj = TestHelpers.ImagekitResponseFaker.Generate(); - - var httpResponse = new HttpResponseMessage - { - StatusCode = HttpStatusCode.OK, - Content = new StringContent(JsonConvert.SerializeObject(responseObj)) - }; - var httpClient = TestHelpers.GetTestHttpClient(httpResponse); - var restClient = new RestClient(GOOD_PUBLICKEY, GOOD_URLENDPOINT, httpClient); - var ex = Assert.ThrowsAsync(async () => await restClient.ManageTagsAsync(ob, "")); - Assert.Equal(ErrorMessages.InvalidFiledParamValue, ex.Result.Message); - } - - - [Fact] - public void Missing_AI_Filed_Null_Exception() - { - AITagsRequest ob = new AITagsRequest - { - AITags = new List { "abc" }, - fileIds = null - }; - - var responseObj = TestHelpers.ImagekitResponseFaker.Generate(); - - var httpResponse = new HttpResponseMessage - { - StatusCode = HttpStatusCode.OK, - Content = new StringContent(JsonConvert.SerializeObject(responseObj)) - }; - var httpClient = TestHelpers.GetTestHttpClient(httpResponse); - var restClient = new RestClient(GOOD_PUBLICKEY, GOOD_URLENDPOINT, httpClient); - var ex = Assert.ThrowsAsync(async () => await restClient.RemoveAITagsAsync(ob)); - Assert.Equal(ErrorMessages.InvalidFiledParamValue, ex.Result.Message); - } - - [Fact] - public void DeleteFileVersion_Default() - { - DeleteFileVersionRequest model = new DeleteFileVersionRequest - { - fileId = "Tst3", - versionId = "Tst3" - }; - - var responseObj = TestHelpers.ImagekitResponseFaker.Generate(); - var httpResponse = new HttpResponseMessage - { - StatusCode = HttpStatusCode.OK, - Content = new StringContent(JsonConvert.SerializeObject(responseObj)) - }; - var httpClient = TestHelpers.GetTestHttpClient(httpResponse); - var restClient = new RestClient(GOOD_PUBLICKEY, GOOD_URLENDPOINT, httpClient); - - var response = restClient.DeleteFileVersionAsync(model).Result; - var responseObj1 = JsonConvert.SerializeObject(responseObj); - Assert.Equal(responseObj1, response.Raw); - } - - [Fact] - public void Missing_Object_FileVersionException() - { - DeleteFileVersionRequest model = null; - var responseObj = TestHelpers.ImagekitResponseFaker.Generate(); - - var httpResponse = new HttpResponseMessage - { - StatusCode = HttpStatusCode.OK, - Content = new StringContent(JsonConvert.SerializeObject(responseObj)) - }; - var httpClient = TestHelpers.GetTestHttpClient(httpResponse); - var restClient = new RestClient(GOOD_PUBLICKEY, GOOD_URLENDPOINT, httpClient); - var ex = Assert.ThrowsAsync(async () => await restClient.DeleteFileVersionAsync(model)); - Assert.Equal(ErrorMessages.InvalidDelVerValue, ex.Result.Message); - } - [Fact] - public void Missing_fileId_FileVersionException() - { - DeleteFileVersionRequest model = new DeleteFileVersionRequest - { - versionId = "abc" - }; - var responseObj = TestHelpers.ImagekitResponseFaker.Generate(); - - var httpResponse = new HttpResponseMessage - { - StatusCode = HttpStatusCode.OK, - Content = new StringContent(JsonConvert.SerializeObject(responseObj)) - }; - var httpClient = TestHelpers.GetTestHttpClient(httpResponse); - var restClient = new RestClient(GOOD_PUBLICKEY, GOOD_URLENDPOINT, httpClient); - var ex = Assert.ThrowsAsync(async () => await restClient.DeleteFileVersionAsync(model)); - Assert.Equal(ErrorMessages.InvalidFieldIdDelVerValue, ex.Result.Message); - } - - [Fact] - public void Missing_versionId_FileVersionException() - { - DeleteFileVersionRequest model = new DeleteFileVersionRequest - { - versionId = "", - fileId = "sas" - }; - var responseObj = TestHelpers.ImagekitResponseFaker.Generate(); - - var httpResponse = new HttpResponseMessage - { - StatusCode = HttpStatusCode.OK, - Content = new StringContent(JsonConvert.SerializeObject(responseObj)) - }; - var httpClient = TestHelpers.GetTestHttpClient(httpResponse); - var restClient = new RestClient(GOOD_PUBLICKEY, GOOD_URLENDPOINT, httpClient); - var ex = Assert.ThrowsAsync(async () => await restClient.DeleteFileVersionAsync(model)); - Assert.Equal(ErrorMessages.InvalidversionIdDelVerValue, ex.Result.Message); - } - - [Fact] - public void CopyFile_Default() - { - CopyFileRequest model = new CopyFileRequest - { - sourceFilePath = "Tst3", - destinationPath = "Tst3", - includeFileVersions = true - }; - var responseObj = TestHelpers.ImagekitResponseFaker.Generate(); - var httpResponse = new HttpResponseMessage - { - StatusCode = HttpStatusCode.OK, - Content = new StringContent(JsonConvert.SerializeObject(responseObj)) - }; - var httpClient = TestHelpers.GetTestHttpClient(httpResponse); - var restClient = new RestClient(GOOD_PUBLICKEY, GOOD_URLENDPOINT, httpClient); - - var response = restClient.CopyFileAsync(model).Result; - var responseObj1 = JsonConvert.SerializeObject(responseObj); - Assert.Equal(responseObj1, response.Raw); - } - [Fact] - public void Missing_Obj_CopyFileException() - { - CopyFileRequest model = null; - var responseObj = TestHelpers.ImagekitResponseFaker.Generate(); - - var httpResponse = new HttpResponseMessage - { - StatusCode = HttpStatusCode.OK, - Content = new StringContent(JsonConvert.SerializeObject(responseObj)) - }; - var httpClient = TestHelpers.GetTestHttpClient(httpResponse); - var restClient = new RestClient(GOOD_PUBLICKEY, GOOD_URLENDPOINT, httpClient); - var ex = Assert.ThrowsAsync(async () => await restClient.CopyFileAsync(model)); - Assert.Equal(ErrorMessages.InvalidCopyValue, ex.Result.Message); - } - - - - [Fact] - public void Missing_Source_CopyFileException() - { - CopyFileRequest model = new CopyFileRequest - { - destinationPath = "abc" - }; - var responseObj = TestHelpers.ImagekitResponseFaker.Generate(); - - var httpResponse = new HttpResponseMessage - { - StatusCode = HttpStatusCode.OK, - Content = new StringContent(JsonConvert.SerializeObject(responseObj)) - }; - var httpClient = TestHelpers.GetTestHttpClient(httpResponse); - var restClient = new RestClient(GOOD_PUBLICKEY, GOOD_URLENDPOINT, httpClient); - var ex = Assert.ThrowsAsync(async () => await restClient.CopyFileAsync(model)); - Assert.Equal(ErrorMessages.InvalidSourceValue, ex.Result.Message); - } - - [Fact] - public void Missing_Destination_CopyFileException() - { - CopyFileRequest model = new CopyFileRequest - { - sourceFilePath = "abc" - }; - var responseObj = TestHelpers.ImagekitResponseFaker.Generate(); - - var httpResponse = new HttpResponseMessage - { - StatusCode = HttpStatusCode.OK, - Content = new StringContent(JsonConvert.SerializeObject(responseObj)) - }; - var httpClient = TestHelpers.GetTestHttpClient(httpResponse); - var restClient = new RestClient(GOOD_PUBLICKEY, GOOD_URLENDPOINT, httpClient); - var ex = Assert.ThrowsAsync(async () => await restClient.CopyFileAsync(model)); - Assert.Equal(ErrorMessages.InvalidDestinationValue, ex.Result.Message); - } - - [Fact] - public void MoveFile_Default() - { - MoveFileRequest model = new MoveFileRequest - { - sourceFilePath = "Tst3", - destinationPath = "Tst3" - }; - - var responseObj = TestHelpers.ImagekitResponseFaker.Generate(); - var httpResponse = new HttpResponseMessage - { - StatusCode = HttpStatusCode.OK, - Content = new StringContent(JsonConvert.SerializeObject(responseObj)) - }; - var httpClient = TestHelpers.GetTestHttpClient(httpResponse); - var restClient = new RestClient(GOOD_PUBLICKEY, GOOD_URLENDPOINT, httpClient); - - var response = restClient.MoveFileAsync(model).Result; - var responseObj1 = JsonConvert.SerializeObject(responseObj); - Assert.Equal(responseObj1, response.Raw); - } - [Fact] - public void Missing_Obj_MoveFileException() - { - MoveFileRequest model = null; - var responseObj = TestHelpers.ImagekitResponseFaker.Generate(); - - var httpResponse = new HttpResponseMessage - { - StatusCode = HttpStatusCode.OK, - Content = new StringContent(JsonConvert.SerializeObject(responseObj)) - }; - var httpClient = TestHelpers.GetTestHttpClient(httpResponse); - var restClient = new RestClient(GOOD_PUBLICKEY, GOOD_URLENDPOINT, httpClient); - var ex = Assert.ThrowsAsync(async () => await restClient.MoveFileAsync(model)); - Assert.Equal(ErrorMessages.InvalidCopyValue, ex.Result.Message); - } - - [Fact] - public void Missing_Source_MoveFileException() - { - MoveFileRequest model = new MoveFileRequest - { - destinationPath = "abc" - }; - var responseObj = TestHelpers.ImagekitResponseFaker.Generate(); - - var httpResponse = new HttpResponseMessage - { - StatusCode = HttpStatusCode.OK, - Content = new StringContent(JsonConvert.SerializeObject(responseObj)) - }; - var httpClient = TestHelpers.GetTestHttpClient(httpResponse); - var restClient = new RestClient(GOOD_PUBLICKEY, GOOD_URLENDPOINT, httpClient); - var ex = Assert.ThrowsAsync(async () => await restClient.MoveFileAsync(model)); - Assert.Equal(ErrorMessages.InvalidSourceValue, ex.Result.Message); - } - - [Fact] - public void Missing_Destination_MoveFileException() - { - MoveFileRequest model = new MoveFileRequest - { - sourceFilePath = "abc" - }; - var responseObj = TestHelpers.ImagekitResponseFaker.Generate(); - - var httpResponse = new HttpResponseMessage - { - StatusCode = HttpStatusCode.OK, - Content = new StringContent(JsonConvert.SerializeObject(responseObj)) - }; - var httpClient = TestHelpers.GetTestHttpClient(httpResponse); - var restClient = new RestClient(GOOD_PUBLICKEY, GOOD_URLENDPOINT, httpClient); - var ex = Assert.ThrowsAsync(async () => await restClient.MoveFileAsync(model)); - Assert.Equal(ErrorMessages.InvalidDestinationValue, ex.Result.Message); - } - - [Fact] - public void RenameFile_Default() - { - RenameFileRequest model = new RenameFileRequest - { - filePath = "Tst3", - newFileName = "Tst4", - purgeCache = false - }; - - var responseObj = TestHelpers.ImagekitResponseFaker.Generate(); - var httpResponse = new HttpResponseMessage - { - StatusCode = HttpStatusCode.OK, - Content = new StringContent(JsonConvert.SerializeObject(responseObj)) - }; - var httpClient = TestHelpers.GetTestHttpClient(httpResponse); - var restClient = new RestClient(GOOD_PUBLICKEY, GOOD_URLENDPOINT, httpClient); - - var response = restClient.RenameFileAsync(model).Result; - var responseObj1 = JsonConvert.SerializeObject(responseObj); - Assert.Equal(responseObj1, response.Raw); - } - [Fact] - public void Missing_FilePath_RenameFileException() - { - RenameFileRequest model = new RenameFileRequest - { - newFileName = "test" - }; - var responseObj = TestHelpers.ImagekitResponseFaker.Generate(); - - var httpResponse = new HttpResponseMessage - { - StatusCode = HttpStatusCode.OK, - Content = new StringContent(JsonConvert.SerializeObject(responseObj)) - }; - var httpClient = TestHelpers.GetTestHttpClient(httpResponse); - var restClient = new RestClient(GOOD_PUBLICKEY, GOOD_URLENDPOINT, httpClient); - var ex = Assert.ThrowsAsync(async () => await restClient.RenameFileAsync(model)); - Assert.Equal(ErrorMessages.InvalidRenameFilePathValue, ex.Result.Message); - } - [Fact] - public void Missing_NewFileName_RenameFileException() - { - RenameFileRequest model = new RenameFileRequest - { - filePath = "test" - }; - var responseObj = TestHelpers.ImagekitResponseFaker.Generate(); - - var httpResponse = new HttpResponseMessage - { - StatusCode = HttpStatusCode.OK, - Content = new StringContent(JsonConvert.SerializeObject(responseObj)) - }; - var httpClient = TestHelpers.GetTestHttpClient(httpResponse); - var restClient = new RestClient(GOOD_PUBLICKEY, GOOD_URLENDPOINT, httpClient); - var ex = Assert.ThrowsAsync(async () => await restClient.RenameFileAsync(model)); - Assert.Equal(ErrorMessages.InvalidRenameNewFileNameValue, ex.Result.Message); - } - - - [Fact] - public void GetBulkJobStatus_Default() - { - var responseObj = TestHelpers.ImagekitResponseFaker.Generate(); - var httpResponse = new HttpResponseMessage - { - StatusCode = HttpStatusCode.OK, - Content = new StringContent(JsonConvert.SerializeObject(responseObj)) - }; - var httpClient = TestHelpers.GetTestHttpClient(httpResponse); - var restClient = new RestClient(GOOD_PUBLICKEY, GOOD_URLENDPOINT, httpClient); - - var response = restClient.GetBulkJobStatusAsync("abc").Result; - var responseObj1 = JsonConvert.SerializeObject(responseObj); - Assert.Equal(responseObj1, response.Raw); - } - [Fact] - public void Missing_Job_Id_BulkJobStatusException() - { - - var responseObj = TestHelpers.ImagekitResponseFaker.Generate(); - - var httpResponse = new HttpResponseMessage - { - StatusCode = HttpStatusCode.OK, - Content = new StringContent(JsonConvert.SerializeObject(responseObj)) - }; - var httpClient = TestHelpers.GetTestHttpClient(httpResponse); - var restClient = new RestClient(GOOD_PUBLICKEY, GOOD_URLENDPOINT, httpClient); - var ex = Assert.ThrowsAsync(async () => await restClient.GetBulkJobStatusAsync("")); - Assert.Equal(ErrorMessages.InvalidJobValue, ex.Result.Message); - } - } -} - - - - diff --git a/Imagekit.UnitTests/ImageKitTestCasesNonAsync.cs b/Imagekit.UnitTests/ImageKitTestCasesNonAsync.cs deleted file mode 100644 index 4e57c7be..00000000 --- a/Imagekit.UnitTests/ImageKitTestCasesNonAsync.cs +++ /dev/null @@ -1,734 +0,0 @@ -using Imagekit.Constant; -using Imagekit.Sdk; -using Imagekit.Models; -using Newtonsoft.Json; -using System; -using System.Collections.Generic; -using System.Net; -using System.Net.Http; -using Xunit; -using Newtonsoft.Json.Linq; - -namespace Imagekit.UnitTests.FileVersion -{ - public class ImageKitTestCasesNonAsync - { - private const string GOOD_PUBLICKEY = "public_key"; - private const string GOOD_PRIVATEKEY = "private_key_test"; - private const string GOOD_URLENDPOINT = "https://endpoint_url.io/"; - - - [Fact] - public void Missing_Key_ExceptionNonAsync() - { - - Exception actualException = Assert.Throws(() => new RestClient("", "https://endpoint_url.io/", new HttpClient())); - Assert.Equal(ErrorMessages.InvalidKey, actualException.Message); - } - [Fact] - public void Missing_URL_ExceptionNonAsync() - { - - Exception actualException = Assert.Throws(() => new RestClient("abc", "", new HttpClient())); - Assert.Equal(ErrorMessages.InvalidApiUrl, actualException.Message); - } - - [Fact] - public void Constructor_TransformationPosition_DefaultNonAsync() - { - var imagekit = new ImagekitClient(GOOD_PUBLICKEY, GOOD_PRIVATEKEY, GOOD_URLENDPOINT); - Assert.NotNull(imagekit); - } - [Fact] - public void UrlValidation() - { - var imagekit = new ImagekitClient(GOOD_PUBLICKEY, GOOD_PRIVATEKEY, GOOD_URLENDPOINT); - string path = "/default-image.jpg"; - Transformation trans = new Transformation() - .Width(400) - .Height(300) - .AspectRatio("4-3") - .Quality(40) - .Crop("force").CropMode("extract"). - Focus("left"). - Format("jpeg"). - Background("A94D34"). - Border("5-A94D34"). - Rotation(90). - Blur(10). - Named("some_name"). - Progressive(true). - Lossless(true). - Trim(5). - Metadata(true). - ColorProfile(true). - DefaultImage("folder/file.jpg/"). //trailing slash case - Dpr(3). - EffectSharpen(10). - EffectUsm("2-2-0.8-0.024"). - EffectContrast(true). - EffectGray(). - EffectShadow("bl-15"). - EffectGradient("from-lightskyblue_to-mintcream"). - Original(). - Raw("l-text,i-Imagekit,fs-50,l-end") - ; - - string imageURL = imagekit.Url(trans).Path(path).TransformationPosition("query").Generate(); - - Assert.Equal("https://endpoint_url.io/default-image.jpg?tr=w-400%2Ch-300%2Car-4-3%2Cq-40%2Cc-force%2Ccm-extract%2Cfo-left%2Cf-jpeg%2Cbg-A94D34%2Cb-5-A94D34%2Crt-90%2Cbl-10%2Cn-some_name%2Cpr-true%2Clo-true%2Ct-5%2Cmd-true%2Ccp-true%2Cdi-folder%40%40file.jpg%2Cdpr-3%2Ce-sharpen-10%2Ce-usm-2-2-0.8-0.024%2Ce-contrast-true%2Ce-grayscale-true%2Ce-shadow-bl-15%2Ce-gradient-from-lightskyblue_to-mintcream%2Corig-true%2Cl-text%2Ci-Imagekit%2Cfs-50%2Cl-end", imageURL); - } - - - [Fact] - public void UrlValidation1() - { - var imagekit = new ImagekitClient(GOOD_PUBLICKEY, GOOD_PRIVATEKEY, GOOD_URLENDPOINT); - var imgUrl1 = "https://ik.imagekit.io/demo/default-image.jpg"; - string[] queryParams = { "b=query", "a=value" }; - try - { - var signedUrl = imagekit.Url(new Transformation().Width(400).Height(300)) - .Src(imgUrl1) - .QueryParameters(queryParams) - .ExpireSeconds(600) - .Signed() - .Generate(); - Console.WriteLine("Signed Url for first image transformed with height: 300, width: 400: - {0}", signedUrl); - } - catch (Exception ex) - { - Console.WriteLine(ex.Message); - } - } - - [Fact] - public void GetFileRequest_DefaultNonAsync() - { - GetFileListRequest ob = new GetFileListRequest - { - Limit = 10, - Skip = 0 - }; - var responseObj = TestHelpers.ImagekitResponseFaker.Generate(); - - var httpResponse = new HttpResponseMessage - { - StatusCode = HttpStatusCode.OK, - Content = new StringContent(JsonConvert.SerializeObject(responseObj)) - }; - var httpClient = TestHelpers.GetTestHttpClient(httpResponse); - var restClient = new RestClient(GOOD_PUBLICKEY, GOOD_URLENDPOINT, httpClient); - - var response = (ResultList)restClient.GetFileListRequest(ob); - - Assert.Equal(response.Raw, response.Raw); - } - - [Fact] - public void GetFileDetail_DefaultNonAsync() - { - var responseObj = TestHelpers.ImagekitResponseFaker.Generate(); - - var httpResponse = new HttpResponseMessage - { - StatusCode = HttpStatusCode.OK, - Content = new StringContent(JsonConvert.SerializeObject(responseObj)) - }; - var httpClient = TestHelpers.GetTestHttpClient(httpResponse); - var restClient = new RestClient(GOOD_PUBLICKEY, GOOD_URLENDPOINT, httpClient); - var response = (Result)restClient.GetFileDetail("abc"); - var responseObj1 = JsonConvert.SerializeObject(responseObj); - Assert.Equal(responseObj1, response.Raw); - } - - [Fact] - public void GetFile_ID_Detail_ExceptionNonAsync() - { - var responseObj = TestHelpers.ImagekitResponseFaker.Generate(); - - var httpResponse = new HttpResponseMessage - { - StatusCode = HttpStatusCode.OK, - Content = new StringContent(JsonConvert.SerializeObject(responseObj)) - }; - var httpClient = TestHelpers.GetTestHttpClient(httpResponse); - var restClient = new RestClient(GOOD_PUBLICKEY, GOOD_URLENDPOINT, httpClient); - var ex = Assert.Throws(() => restClient.GetFileDetail("")); - Assert.Equal(ErrorMessages.FileIdMissing, ex.Message); - } - - - - [Fact] - public void PurgeCache_DefaultNonAsync() - { - var responseObj = TestHelpers.ImagekitResponseFaker.Generate(); - - var httpResponse = new HttpResponseMessage - { - StatusCode = HttpStatusCode.OK, - Content = new StringContent(JsonConvert.SerializeObject(responseObj)) - }; - var httpClient = TestHelpers.GetTestHttpClient(httpResponse); - var restClient = new RestClient(GOOD_PUBLICKEY, GOOD_URLENDPOINT, httpClient); - - var response = restClient.PurgeCache("abc"); - var responseObj1 = JsonConvert.SerializeObject(responseObj); - Assert.Equal(responseObj1, response.Raw); - } - [Fact] - public void PurgeStatus_DefaultNonAsync() - { - var responseObj = TestHelpers.ImagekitResponseFaker.Generate(); - - var httpResponse = new HttpResponseMessage - { - StatusCode = HttpStatusCode.OK, - Content = new StringContent(JsonConvert.SerializeObject(responseObj)) - }; - var httpClient = TestHelpers.GetTestHttpClient(httpResponse); - var restClient = new RestClient(GOOD_PUBLICKEY, GOOD_URLENDPOINT, httpClient); - - var response = restClient.PurgeStatus("abc"); - var responseObj1 = JsonConvert.SerializeObject(responseObj); - Assert.Equal(responseObj1, response.Raw); - } - - [Fact] - public void DeleteFile_DefaultNonAsync() - { - var responseObj = TestHelpers.ImagekitResponseFaker.Generate(); - - var httpResponse = new HttpResponseMessage - { - StatusCode = HttpStatusCode.OK, - Content = new StringContent(JsonConvert.SerializeObject(responseObj)) - }; - var httpClient = TestHelpers.GetTestHttpClient(httpResponse); - var restClient = new RestClient(GOOD_PUBLICKEY, GOOD_URLENDPOINT, httpClient); - - var response = (ResultDelete)restClient.DeleteFile("abc"); - var responseObj1 = JsonConvert.SerializeObject(responseObj); - Assert.Equal(responseObj1, response.Raw); - } - [Fact] - public void Delete_File_ID_ExceptionNonAsync() - { - var responseObj = TestHelpers.ImagekitResponseFaker.Generate(); - - var httpResponse = new HttpResponseMessage - { - StatusCode = HttpStatusCode.OK, - Content = new StringContent(JsonConvert.SerializeObject(responseObj)) - }; - var httpClient = TestHelpers.GetTestHttpClient(httpResponse); - var restClient = new RestClient(GOOD_PUBLICKEY, GOOD_URLENDPOINT, httpClient); - var ex = Assert.Throws(() => restClient.DeleteFile("")); - Assert.Equal(ErrorMessages.FileIdMissing, ex.Message); - } - - - [Fact] - public void BulkDeleteFiles_DefaultNonAsync() - { - List ob = new List - { - "abc", - "abcd" - }; - - var responseObj = TestHelpers.ImagekitResponseFaker.Generate(); - - var httpResponse = new HttpResponseMessage - { - StatusCode = HttpStatusCode.OK, - Content = new StringContent(JsonConvert.SerializeObject(responseObj)) - }; - var httpClient = TestHelpers.GetTestHttpClient(httpResponse); - var restClient = new RestClient(GOOD_PUBLICKEY, GOOD_URLENDPOINT, httpClient); - - var response = (ResultFileDelete)restClient.BulkDeleteFiles(ob); - var responseObj1 = JsonConvert.SerializeObject(responseObj.Raw); - responseObj1 = JToken.Parse(responseObj1).ToString(); - - Assert.Equal(responseObj.Raw, responseObj1); - } - [Fact] - public void Bulk_Delete_Files_Input_Missing_ExceptionNonAsync() - { - List ob = new List(); - var responseObj = TestHelpers.ImagekitResponseFaker.Generate(); - - var httpResponse = new HttpResponseMessage - { - StatusCode = HttpStatusCode.OK, - Content = new StringContent(JsonConvert.SerializeObject(responseObj)) - }; - var httpClient = TestHelpers.GetTestHttpClient(httpResponse); - var restClient = new RestClient(GOOD_PUBLICKEY, GOOD_URLENDPOINT, httpClient); - var ex = Assert.Throws(() => restClient.BulkDeleteFiles(ob)); - Assert.Equal(ErrorMessages.ListFilesInputMissing, ex.Message); - } - - - - - - - - [Fact] - public void Missing_Filed_Null_ExceptionNonAsync() - { - TagsRequest ob = new TagsRequest - { - tags = new List { "abc" }, - fileIds = null - }; - - var responseObj = TestHelpers.ImagekitResponseFaker.Generate(); - - var httpResponse = new HttpResponseMessage - { - StatusCode = HttpStatusCode.OK, - Content = new StringContent(JsonConvert.SerializeObject(responseObj)) - }; - var httpClient = TestHelpers.GetTestHttpClient(httpResponse); - var restClient = new RestClient(GOOD_PUBLICKEY, GOOD_URLENDPOINT, httpClient); - var ex = Assert.Throws(() => restClient.ManageTags(ob, "")); - Assert.Equal(ErrorMessages.InvalidFiledParamValue, ex.Message); - } - - - - - [Fact] - public void Missing_Remove_Filed_Null_ExceptionNonAsync() - { - TagsRequest ob = new TagsRequest - { - tags = new List { "abc" }, - fileIds = null - }; - - var responseObj = TestHelpers.ImagekitResponseFaker.Generate(); - - var httpResponse = new HttpResponseMessage - { - StatusCode = HttpStatusCode.OK, - Content = new StringContent(JsonConvert.SerializeObject(responseObj)) - }; - var httpClient = TestHelpers.GetTestHttpClient(httpResponse); - var restClient = new RestClient(GOOD_PUBLICKEY, GOOD_URLENDPOINT, httpClient); - var ex = Assert.Throws(() => restClient.ManageTags(ob, "")); - Assert.Equal(ErrorMessages.InvalidFiledParamValue, ex.Message); - } - - - [Fact] - public void Missing_AI_Filed_Null_ExceptionNonAsync() - { - AITagsRequest ob = new AITagsRequest - { - AITags = new List { "abc" }, - fileIds = null - }; - - var responseObj = TestHelpers.ImagekitResponseFaker.Generate(); - - var httpResponse = new HttpResponseMessage - { - StatusCode = HttpStatusCode.OK, - Content = new StringContent(JsonConvert.SerializeObject(responseObj)) - }; - var httpClient = TestHelpers.GetTestHttpClient(httpResponse); - var restClient = new RestClient(GOOD_PUBLICKEY, GOOD_URLENDPOINT, httpClient); - var ex = Assert.Throws(() => restClient.RemoveAITags(ob)); - Assert.Equal(ErrorMessages.InvalidFiledParamValue, ex.Message); - } - - [Fact] - public void DeleteFileVersion_DefaultNonAsync() - { - DeleteFileVersionRequest model = new DeleteFileVersionRequest - { - fileId = "Tst3", - versionId = "Tst3" - }; - - var responseObj = TestHelpers.ImagekitResponseFaker.Generate(); - var httpResponse = new HttpResponseMessage - { - StatusCode = HttpStatusCode.OK, - Content = new StringContent(JsonConvert.SerializeObject(responseObj)) - }; - var httpClient = TestHelpers.GetTestHttpClient(httpResponse); - var restClient = new RestClient(GOOD_PUBLICKEY, GOOD_URLENDPOINT, httpClient); - - var response = restClient.DeleteFileVersion(model); - var responseObj1 = JsonConvert.SerializeObject(responseObj); - Assert.Equal(responseObj1, response.Raw); - } - - [Fact] - public void Missing_Object_FileVersionExceptionNonAsync() - { - DeleteFileVersionRequest model = null; - var responseObj = TestHelpers.ImagekitResponseFaker.Generate(); - - var httpResponse = new HttpResponseMessage - { - StatusCode = HttpStatusCode.OK, - Content = new StringContent(JsonConvert.SerializeObject(responseObj)) - }; - var httpClient = TestHelpers.GetTestHttpClient(httpResponse); - var restClient = new RestClient(GOOD_PUBLICKEY, GOOD_URLENDPOINT, httpClient); - var ex = Assert.Throws(() => (ResultNoContent)restClient.DeleteFileVersion(model)); - Assert.Equal(ErrorMessages.InvalidDelVerValue, ex.Message); - } - [Fact] - public void Missing_fileId_FileVersionExceptionNonAsync() - { - DeleteFileVersionRequest model = new DeleteFileVersionRequest - { - versionId = "abc" - }; - var responseObj = TestHelpers.ImagekitResponseFaker.Generate(); - - var httpResponse = new HttpResponseMessage - { - StatusCode = HttpStatusCode.OK, - Content = new StringContent(JsonConvert.SerializeObject(responseObj)) - }; - var httpClient = TestHelpers.GetTestHttpClient(httpResponse); - var restClient = new RestClient(GOOD_PUBLICKEY, GOOD_URLENDPOINT, httpClient); - var ex = Assert.Throws(() => restClient.DeleteFileVersion(model)); - Assert.Equal(ErrorMessages.InvalidFieldIdDelVerValue, ex.Message); - } - - [Fact] - public void Missing_versionId_FileVersionExceptionNonAsync() - { - DeleteFileVersionRequest model = new DeleteFileVersionRequest - { - versionId = "", - fileId = "sas" - }; - var responseObj = TestHelpers.ImagekitResponseFaker.Generate(); - - var httpResponse = new HttpResponseMessage - { - StatusCode = HttpStatusCode.OK, - Content = new StringContent(JsonConvert.SerializeObject(responseObj)) - }; - var httpClient = TestHelpers.GetTestHttpClient(httpResponse); - var restClient = new RestClient(GOOD_PUBLICKEY, GOOD_URLENDPOINT, httpClient); - var ex = Assert.Throws(() => restClient.DeleteFileVersion(model)); - Assert.Equal(ErrorMessages.InvalidversionIdDelVerValue, ex.Message); - } - - [Fact] - public void CopyFile_DefaultNonAsync() - { - CopyFileRequest model = new CopyFileRequest - { - sourceFilePath = "Tst3", - destinationPath = "Tst3", - includeFileVersions = true - }; - var responseObj = TestHelpers.ImagekitResponseFaker.Generate(); - var httpResponse = new HttpResponseMessage - { - StatusCode = HttpStatusCode.OK, - Content = new StringContent(JsonConvert.SerializeObject(responseObj)) - }; - var httpClient = TestHelpers.GetTestHttpClient(httpResponse); - var restClient = new RestClient(GOOD_PUBLICKEY, GOOD_URLENDPOINT, httpClient); - - var response = restClient.CopyFile(model); - var responseObj1 = JsonConvert.SerializeObject(responseObj); - Assert.Equal(responseObj1, response.Raw); - } - [Fact] - public void Missing_Obj_CopyFileExceptionNonAsync() - { - CopyFileRequest model = null; - var responseObj = TestHelpers.ImagekitResponseFaker.Generate(); - - var httpResponse = new HttpResponseMessage - { - StatusCode = HttpStatusCode.OK, - Content = new StringContent(JsonConvert.SerializeObject(responseObj)) - }; - var httpClient = TestHelpers.GetTestHttpClient(httpResponse); - var restClient = new RestClient(GOOD_PUBLICKEY, GOOD_URLENDPOINT, httpClient); - var ex = Assert.Throws(() => restClient.CopyFile(model)); - Assert.Equal(ErrorMessages.InvalidCopyValue, ex.Message); - } - - - - [Fact] - public void Missing_Source_CopyFileExceptionNonAsync() - { - CopyFileRequest model = new CopyFileRequest - { - destinationPath = "abc" - }; - var responseObj = TestHelpers.ImagekitResponseFaker.Generate(); - - var httpResponse = new HttpResponseMessage - { - StatusCode = HttpStatusCode.OK, - Content = new StringContent(JsonConvert.SerializeObject(responseObj)) - }; - var httpClient = TestHelpers.GetTestHttpClient(httpResponse); - var restClient = new RestClient(GOOD_PUBLICKEY, GOOD_URLENDPOINT, httpClient); - var ex = Assert.Throws(() => restClient.CopyFile(model)); - Assert.Equal(ErrorMessages.InvalidSourceValue, ex.Message); - } - - [Fact] - public void Missing_Destination_CopyFileExceptionNonAsync() - { - CopyFileRequest model = new CopyFileRequest - { - sourceFilePath = "abc" - }; - var responseObj = TestHelpers.ImagekitResponseFaker.Generate(); - - var httpResponse = new HttpResponseMessage - { - StatusCode = HttpStatusCode.OK, - Content = new StringContent(JsonConvert.SerializeObject(responseObj)) - }; - var httpClient = TestHelpers.GetTestHttpClient(httpResponse); - var restClient = new RestClient(GOOD_PUBLICKEY, GOOD_URLENDPOINT, httpClient); - var ex = Assert.Throws(() => restClient.CopyFile(model)); - Assert.Equal(ErrorMessages.InvalidDestinationValue, ex.Message); - } - - [Fact] - public void MoveFile_DefaultNonAsync() - { - MoveFileRequest model = new MoveFileRequest - { - sourceFilePath = "Tst3", - destinationPath = "Tst3" - }; - - var responseObj = TestHelpers.ImagekitResponseFaker.Generate(); - var httpResponse = new HttpResponseMessage - { - StatusCode = HttpStatusCode.OK, - Content = new StringContent(JsonConvert.SerializeObject(responseObj)) - }; - var httpClient = TestHelpers.GetTestHttpClient(httpResponse); - var restClient = new RestClient(GOOD_PUBLICKEY, GOOD_URLENDPOINT, httpClient); - - var response = restClient.MoveFile(model); - var responseObj1 = JsonConvert.SerializeObject(responseObj); - Assert.Equal(responseObj1, response.Raw); - } - [Fact] - public void Missing_Obj_MoveFileExceptionNonAsync() - { - MoveFileRequest model = null; - var responseObj = TestHelpers.ImagekitResponseFaker.Generate(); - - var httpResponse = new HttpResponseMessage - { - StatusCode = HttpStatusCode.OK, - Content = new StringContent(JsonConvert.SerializeObject(responseObj)) - }; - var httpClient = TestHelpers.GetTestHttpClient(httpResponse); - var restClient = new RestClient(GOOD_PUBLICKEY, GOOD_URLENDPOINT, httpClient); - var ex = Assert.Throws(() => restClient.MoveFile(model)); - Assert.Equal(ErrorMessages.InvalidCopyValue, ex.Message); - } - - [Fact] - public void Missing_Source_MoveFileExceptionNonAsync() - { - MoveFileRequest model = new MoveFileRequest - { - destinationPath = "abc" - }; - var responseObj = TestHelpers.ImagekitResponseFaker.Generate(); - - var httpResponse = new HttpResponseMessage - { - StatusCode = HttpStatusCode.OK, - Content = new StringContent(JsonConvert.SerializeObject(responseObj)) - }; - var httpClient = TestHelpers.GetTestHttpClient(httpResponse); - var restClient = new RestClient(GOOD_PUBLICKEY, GOOD_URLENDPOINT, httpClient); - var ex = Assert.Throws(() => restClient.MoveFile(model)); - Assert.Equal(ErrorMessages.InvalidSourceValue, ex.Message); - } - - [Fact] - public void Missing_Destination_MoveFileExceptionNonAsync() - { - MoveFileRequest model = new MoveFileRequest - { - sourceFilePath = "abc" - }; - var responseObj = TestHelpers.ImagekitResponseFaker.Generate(); - - var httpResponse = new HttpResponseMessage - { - StatusCode = HttpStatusCode.OK, - Content = new StringContent(JsonConvert.SerializeObject(responseObj)) - }; - var httpClient = TestHelpers.GetTestHttpClient(httpResponse); - var restClient = new RestClient(GOOD_PUBLICKEY, GOOD_URLENDPOINT, httpClient); - var ex = Assert.Throws(() => restClient.MoveFile(model)); - Assert.Equal(ErrorMessages.InvalidDestinationValue, ex.Message); - } - - [Fact] - public void RenameFile_DefaultNonAsync() - { - RenameFileRequest model = new RenameFileRequest - { - filePath = "Tst3", - newFileName = "Tst4", - purgeCache = false - }; - - var responseObj = TestHelpers.ImagekitResponseFaker.Generate(); - var httpResponse = new HttpResponseMessage - { - StatusCode = HttpStatusCode.OK, - Content = new StringContent(JsonConvert.SerializeObject(responseObj)) - }; - var httpClient = TestHelpers.GetTestHttpClient(httpResponse); - var restClient = new RestClient(GOOD_PUBLICKEY, GOOD_URLENDPOINT, httpClient); - - var response = restClient.RenameFile(model); - var responseObj1 = JsonConvert.SerializeObject(responseObj); - Assert.Equal(responseObj1, response.Raw); - } - [Fact] - public void Missing_FilePath_RenameFileExceptionNonAsync() - { - RenameFileRequest model = new RenameFileRequest - { - newFileName = "test" - }; - var responseObj = TestHelpers.ImagekitResponseFaker.Generate(); - - var httpResponse = new HttpResponseMessage - { - StatusCode = HttpStatusCode.OK, - Content = new StringContent(JsonConvert.SerializeObject(responseObj)) - }; - var httpClient = TestHelpers.GetTestHttpClient(httpResponse); - var restClient = new RestClient(GOOD_PUBLICKEY, GOOD_URLENDPOINT, httpClient); - var ex = Assert.Throws(() => restClient.RenameFile(model)); - Assert.Equal(ErrorMessages.InvalidRenameFilePathValue, ex.Message); - } - [Fact] - public void Missing_NewFileName_RenameFileExceptionNonAsync() - { - RenameFileRequest model = new RenameFileRequest - { - filePath = "test" - }; - var responseObj = TestHelpers.ImagekitResponseFaker.Generate(); - - var httpResponse = new HttpResponseMessage - { - StatusCode = HttpStatusCode.OK, - Content = new StringContent(JsonConvert.SerializeObject(responseObj)) - }; - var httpClient = TestHelpers.GetTestHttpClient(httpResponse); - var restClient = new RestClient(GOOD_PUBLICKEY, GOOD_URLENDPOINT, httpClient); - var ex = Assert.Throws(() => restClient.RenameFile(model)); - Assert.Equal(ErrorMessages.InvalidRenameNewFileNameValue, ex.Message); - } - - - [Fact] - public void GetBulkJobStatus_DefaultNonAsync() - { - var responseObj = TestHelpers.ImagekitResponseFaker.Generate(); - var httpResponse = new HttpResponseMessage - { - StatusCode = HttpStatusCode.OK, - Content = new StringContent(JsonConvert.SerializeObject(responseObj)) - }; - var httpClient = TestHelpers.GetTestHttpClient(httpResponse); - var restClient = new RestClient(GOOD_PUBLICKEY, GOOD_URLENDPOINT, httpClient); - - var response = restClient.GetBulkJobStatus("abc"); - var responseObj1 = JsonConvert.SerializeObject(responseObj); - Assert.Equal(responseObj1, response.Raw); - } - [Fact] - public void Missing_Job_Id_BulkJobStatusExceptionNonAsync() - { - - var responseObj = TestHelpers.ImagekitResponseFaker.Generate(); - - var httpResponse = new HttpResponseMessage - { - StatusCode = HttpStatusCode.OK, - Content = new StringContent(JsonConvert.SerializeObject(responseObj)) - }; - var httpClient = TestHelpers.GetTestHttpClient(httpResponse); - var restClient = new RestClient(GOOD_PUBLICKEY, GOOD_URLENDPOINT, httpClient); - var ex = Assert.Throws(() => restClient.GetBulkJobStatus("")); - Assert.Equal(ErrorMessages.InvalidJobValue, ex.Message); - } - - - [Fact] - public void SameImage_getHammingDistance_expectedSuccessWith() - { - var imagekit = new ImagekitClient(GOOD_PUBLICKEY, GOOD_PRIVATEKEY, GOOD_URLENDPOINT); - int hammingDistance = imagekit.PHashDistance("f06830ca9f1e3e90", "f06830ca9f1e3e90"); - Assert.Equal(0, hammingDistance); - } - - - [Fact] - public void SimilarImage_getHammingDistance_expectedSuccessWith() - { - var imagekit = new ImagekitClient(GOOD_PUBLICKEY, GOOD_PRIVATEKEY, GOOD_URLENDPOINT); - int hammingDistance = imagekit.PHashDistance("33699c96619cc69e", "968e978414fe04ea"); - Assert.Equal(2, hammingDistance); - } - - [Fact] - public void AuthenticationParamCheck() - { - var imagekit = new ImagekitClient(GOOD_PUBLICKEY, GOOD_PRIVATEKEY, GOOD_URLENDPOINT); - string token = "your_token"; - string expire = "1582269249"; - AuthParamResponse authParams = imagekit.GetAuthenticationParameters(token, expire); - Assert.Equal(token, authParams.token); - Assert.Equal(expire, authParams.expire); - Assert.Equal("e71bcd6031016b060d349d212e23e85c791decdd", authParams.signature); - } - - [Fact] - public void AuthenticationParamNullCheck() - { - var imagekit = new ImagekitClient(GOOD_PUBLICKEY, GOOD_PRIVATEKEY, GOOD_URLENDPOINT); - string token = null; - string expire = "1582269249"; - AuthParamResponse authParams = imagekit.GetAuthenticationParameters(token, expire); - Assert.NotEmpty(authParams.token); - Assert.IsType(authParams.token); - Assert.Equal(expire, authParams.expire); - Assert.NotEmpty(authParams.signature); - Assert.IsType(authParams.signature); - } - } -} - - - - diff --git a/Imagekit.UnitTests/Imagekit.UnitTests.csproj b/Imagekit.UnitTests/Imagekit.UnitTests.csproj deleted file mode 100644 index 0c21e082..00000000 --- a/Imagekit.UnitTests/Imagekit.UnitTests.csproj +++ /dev/null @@ -1,77 +0,0 @@ - - - - net7.0;net5.0;net6.0;netcoreapp3.1 - 8 - true - false - - - - 1701;1702;NU5125;NU5048; - - - - 1701;1702;NU5125;NU5048; - - - - 1701;1702;NU5125;NU5048; - 5 - - - - 1701;1702;NU5125;NU5048; - 5 - - - - 1701;1702;NU5125;NU5048; - 5 - - - - 1701;1702;NU5125;NU5048; - 5 - - - - 1701;1702;NU5125;NU5048; - - - - 1701;1702;NU5125;NU5048; - - - - 1701;1702;NU5125;NU5048; - - - - 1701;1702;NU5125;NU5048; - - - - - - - - - - - - - - - - - - - - - - - Always - - - diff --git a/Imagekit.UnitTests/ManageFolder/ManageFolderTestAsync.cs b/Imagekit.UnitTests/ManageFolder/ManageFolderTestAsync.cs deleted file mode 100644 index 1d2e829f..00000000 --- a/Imagekit.UnitTests/ManageFolder/ManageFolderTestAsync.cs +++ /dev/null @@ -1,299 +0,0 @@ -using Imagekit.Constant; -using Imagekit.Models; -using Newtonsoft.Json; -using System; -using System.Net; -using System.Net.Http; -using Xunit; - - -namespace Imagekit.UnitTests -{ - - public class ManageFolderTestAsync - - { - private const string GOOD_PUBLICKEY = "abc"; - private const string GOOD_URLENDPOINT = "https://dasdsad.dad.io/"; - - - [Fact] - public void CreateFolder_Default() - { - CreateFolderRequest model = new CreateFolderRequest - { - folderName = "Tst3", - parentFolderPath = "Tst3" - }; - - var responseObj = TestHelpers.ImagekitResponseFaker.Generate(); - var httpResponse = new HttpResponseMessage - { - StatusCode = HttpStatusCode.OK, - Content = new StringContent(JsonConvert.SerializeObject(responseObj)) - }; - var httpClient = TestHelpers.GetTestHttpClient(httpResponse); - var restClient = new RestClient(GOOD_PUBLICKEY, GOOD_URLENDPOINT, httpClient); - - var response = restClient.CreateFolderAsync(model).Result; - var responseObj1 = JsonConvert.SerializeObject(responseObj); - Assert.Equal(responseObj1, response.Raw); - } - - [Fact] - public void CreateFolderException() - { - CreateFolderRequest model = null; - var responseObj = TestHelpers.ImagekitResponseFaker.Generate(); - - var httpResponse = new HttpResponseMessage - { - StatusCode = HttpStatusCode.OK, - Content = new StringContent(JsonConvert.SerializeObject(responseObj)) - }; - var httpClient = TestHelpers.GetTestHttpClient(httpResponse); - var restClient = new RestClient(GOOD_PUBLICKEY, GOOD_URLENDPOINT, httpClient); - var ex = Assert.ThrowsAsync(async () => await restClient.CreateFolderAsync(model)); - Assert.Equal(ErrorMessages.InvalidCreateFolderValue, ex.Result.Message); - } - - [Fact] - public void Missing_folderName_Exception() - { - CreateFolderRequest model = new CreateFolderRequest - { - parentFolderPath = "test" - }; - var responseObj = TestHelpers.ImagekitResponseFaker.Generate(); - - var httpResponse = new HttpResponseMessage - { - StatusCode = HttpStatusCode.OK, - Content = new StringContent(JsonConvert.SerializeObject(responseObj)) - }; - var httpClient = TestHelpers.GetTestHttpClient(httpResponse); - var restClient = new RestClient(GOOD_PUBLICKEY, GOOD_URLENDPOINT, httpClient); - var ex = Assert.ThrowsAsync(async () => await restClient.CreateFolderAsync(model)); - Assert.Equal(ErrorMessages.InvalidfolderNameValue, ex.Result.Message); - } - [Fact] - public void Missing_parentFolderPath_FolderException() - { - CreateFolderRequest model = new CreateFolderRequest - { - folderName = "test" - }; - var responseObj = TestHelpers.ImagekitResponseFaker.Generate(); - - var httpResponse = new HttpResponseMessage - { - StatusCode = HttpStatusCode.OK, - Content = new StringContent(JsonConvert.SerializeObject(responseObj)) - }; - var httpClient = TestHelpers.GetTestHttpClient(httpResponse); - var restClient = new RestClient(GOOD_PUBLICKEY, GOOD_URLENDPOINT, httpClient); - var ex = Assert.ThrowsAsync(async () => await restClient.CreateFolderAsync(model)); - Assert.Equal(ErrorMessages.InvalidFolderPathValue, ex.Result.Message); - } - [Fact] - public void DeleteFolder_Default() - { - DeleteFolderRequest model = new DeleteFolderRequest - { - folderPath = "Tst3" - }; - - - var responseObj = TestHelpers.ImagekitResponseFaker.Generate(); - var httpResponse = new HttpResponseMessage - { - StatusCode = HttpStatusCode.OK, - Content = new StringContent(JsonConvert.SerializeObject(responseObj)) - }; - var httpClient = TestHelpers.GetTestHttpClient(httpResponse); - var restClient = new RestClient(GOOD_PUBLICKEY, GOOD_URLENDPOINT, httpClient); - - var response = restClient.DeleteFolderAsync(model).Result; - var responseObj1 = JsonConvert.SerializeObject(responseObj); - Assert.Equal(responseObj1, response.Raw); - } - [Fact] - public void Missing_Folder_Path_Exception() - { - DeleteFolderRequest model = new DeleteFolderRequest(); - var responseObj = TestHelpers.ImagekitResponseFaker.Generate(); - - var httpResponse = new HttpResponseMessage - { - StatusCode = HttpStatusCode.OK, - Content = new StringContent(JsonConvert.SerializeObject(responseObj)) - }; - var httpClient = TestHelpers.GetTestHttpClient(httpResponse); - var restClient = new RestClient(GOOD_PUBLICKEY, GOOD_URLENDPOINT, httpClient); - var ex = Assert.ThrowsAsync(async () => await restClient.DeleteFolderAsync(model)); - Assert.Equal(ErrorMessages.InvalidDelFolderValue, ex.Result.Message); - } - - - [Fact] - public void CopyFolder_Default() - { - CopyFolderRequest model = new CopyFolderRequest - { - sourceFolderPath = "Tst3", - destinationPath = "Tst3", - includeFileVersions = true - }; - var responseObj = TestHelpers.ImagekitResponseFaker.Generate(); - var httpResponse = new HttpResponseMessage - { - StatusCode = HttpStatusCode.OK, - Content = new StringContent(JsonConvert.SerializeObject(responseObj)) - }; - var httpClient = TestHelpers.GetTestHttpClient(httpResponse); - var restClient = new RestClient(GOOD_PUBLICKEY, GOOD_URLENDPOINT, httpClient); - - var response = restClient.CopyFolderAsync(model).Result; - var responseObj1 = JsonConvert.SerializeObject(responseObj); - Assert.Equal(responseObj1, response.Raw); - } - - [Fact] - public void Missing_Obj_FolderException() - { - CopyFolderRequest model = null; - var responseObj = TestHelpers.ImagekitResponseFaker.Generate(); - var httpResponse = new HttpResponseMessage - { - StatusCode = HttpStatusCode.OK, - Content = new StringContent(JsonConvert.SerializeObject(responseObj)) - }; - var httpClient = TestHelpers.GetTestHttpClient(httpResponse); - var restClient = new RestClient(GOOD_PUBLICKEY, GOOD_URLENDPOINT, httpClient); - var ex = Assert.ThrowsAsync(async () => await restClient.CopyFolderAsync(model)); - Assert.Equal(ErrorMessages.InvalidCopyFolderValue, ex.Result.Message); - } - [Fact] - public void Missing_sourceFolderPath_FolderException() - { - CopyFolderRequest model = new CopyFolderRequest - { - destinationPath = "abc" - }; - - var responseObj = TestHelpers.ImagekitResponseFaker.Generate(); - var httpResponse = new HttpResponseMessage - { - StatusCode = HttpStatusCode.OK, - Content = new StringContent(JsonConvert.SerializeObject(responseObj)) - }; - var httpClient = TestHelpers.GetTestHttpClient(httpResponse); - var restClient = new RestClient(GOOD_PUBLICKEY, GOOD_URLENDPOINT, httpClient); - var ex = Assert.ThrowsAsync(async () => await restClient.CopyFolderAsync(model)); - Assert.Equal(ErrorMessages.InvalidCopysourceFolderPathValue, ex.Result.Message); - } - [Fact] - public void Missing_Destination_FolderPath_FolderException() - { - CopyFolderRequest model = new CopyFolderRequest - { - sourceFolderPath = "abc" - }; - - var responseObj = TestHelpers.ImagekitResponseFaker.Generate(); - var httpResponse = new HttpResponseMessage - { - StatusCode = HttpStatusCode.OK, - Content = new StringContent(JsonConvert.SerializeObject(responseObj)) - }; - var httpClient = TestHelpers.GetTestHttpClient(httpResponse); - var restClient = new RestClient(GOOD_PUBLICKEY, GOOD_URLENDPOINT, httpClient); - var ex = Assert.ThrowsAsync(async () => await restClient.CopyFolderAsync(model)); - Assert.Equal(ErrorMessages.InvalidCopydestinationPathValue, ex.Result.Message); - } - - [Fact] - public void MoveFolder_Default() - { - MoveFolderRequest model = new MoveFolderRequest - { - sourceFolderPath = "Tst3", - destinationPath = "Tst3" - }; - - var responseObj = TestHelpers.ImagekitResponseFaker.Generate(); - var httpResponse = new HttpResponseMessage - { - StatusCode = HttpStatusCode.OK, - Content = new StringContent(JsonConvert.SerializeObject(responseObj)) - }; - var httpClient = TestHelpers.GetTestHttpClient(httpResponse); - var restClient = new RestClient(GOOD_PUBLICKEY, GOOD_URLENDPOINT, httpClient); - - var response = restClient.MoveFolderAsync(model).Result; - var responseObj1 = JsonConvert.SerializeObject(responseObj); - Assert.Equal(responseObj1, response.Raw); - } - - [Fact] - public void Missing_Obj_Move_FolderException() - { - MoveFolderRequest model = null; - var responseObj = TestHelpers.ImagekitResponseFaker.Generate(); - - var httpResponse = new HttpResponseMessage - { - StatusCode = HttpStatusCode.OK, - Content = new StringContent(JsonConvert.SerializeObject(responseObj)) - }; - var httpClient = TestHelpers.GetTestHttpClient(httpResponse); - var restClient = new RestClient(GOOD_PUBLICKEY, GOOD_URLENDPOINT, httpClient); - var ex = Assert.ThrowsAsync(async () => await restClient.MoveFolderAsync(model)); - Assert.Equal(ErrorMessages.InvalidCopyFolderValue, ex.Result.Message); - } - - [Fact] - public void Missing_sourceFolderPath_MoveFolderException() - { - MoveFolderRequest model = new MoveFolderRequest - { - destinationPath = "abc" - }; - - var responseObj = TestHelpers.ImagekitResponseFaker.Generate(); - var httpResponse = new HttpResponseMessage - { - StatusCode = HttpStatusCode.OK, - Content = new StringContent(JsonConvert.SerializeObject(responseObj)) - }; - var httpClient = TestHelpers.GetTestHttpClient(httpResponse); - var restClient = new RestClient(GOOD_PUBLICKEY, GOOD_URLENDPOINT, httpClient); - var ex = Assert.ThrowsAsync(async () => await restClient.MoveFolderAsync(model)); - Assert.Equal(ErrorMessages.InvalidCopysourceFolderPathValue, ex.Result.Message); - } - [Fact] - public void Missing_Destination_FolderPath_MoveFolderException() - { - MoveFolderRequest model = new MoveFolderRequest - { - sourceFolderPath = "abc" - }; - - var responseObj = TestHelpers.ImagekitResponseFaker.Generate(); - var httpResponse = new HttpResponseMessage - { - StatusCode = HttpStatusCode.OK, - Content = new StringContent(JsonConvert.SerializeObject(responseObj)) - }; - var httpClient = TestHelpers.GetTestHttpClient(httpResponse); - var restClient = new RestClient(GOOD_PUBLICKEY, GOOD_URLENDPOINT, httpClient); - var ex = Assert.ThrowsAsync(async () => await restClient.MoveFolderAsync(model)); - Assert.Equal(ErrorMessages.InvalidCopydestinationPathValue, ex.Result.Message); - } - - } -} - - - - diff --git a/Imagekit.UnitTests/ManageFolder/ManageFolderTestNonAsync.cs b/Imagekit.UnitTests/ManageFolder/ManageFolderTestNonAsync.cs deleted file mode 100644 index fb96b647..00000000 --- a/Imagekit.UnitTests/ManageFolder/ManageFolderTestNonAsync.cs +++ /dev/null @@ -1,296 +0,0 @@ -using Imagekit.Constant; -using Imagekit.Models; -using Newtonsoft.Json; -using System; -using System.Net; -using System.Net.Http; -using Xunit; - - -namespace Imagekit.UnitTests -{ - - public class ManageFolderTestNon - - { - private const string GoodPublickey = "abc"; - private const string GoodUrlendpoint = "https://dasdsad.dad.io/"; - - - [Fact] - public void CreateFolder_DefaultNonAsync() - { - CreateFolderRequest model = new CreateFolderRequest - { - folderName = "Tst3", - parentFolderPath = "Tst3" - }; - - var responseObj = TestHelpers.ImagekitResponseFaker.Generate(); - var httpResponse = new HttpResponseMessage - { - StatusCode = HttpStatusCode.OK, - Content = new StringContent(JsonConvert.SerializeObject(responseObj)) - }; - var httpClient = TestHelpers.GetTestHttpClient(httpResponse); - var restClient = new RestClient(GoodPublickey, GoodUrlendpoint, httpClient); - - var response = restClient.CreateFolder(model); - var responseObj1 = JsonConvert.SerializeObject(responseObj); - Assert.Equal(responseObj1, response.Raw); - } - - [Fact] - public void CreateFolderExceptionNonAsync() - { - var responseObj = TestHelpers.ImagekitResponseFaker.Generate(); - - var httpResponse = new HttpResponseMessage - { - StatusCode = HttpStatusCode.OK, - Content = new StringContent(JsonConvert.SerializeObject(responseObj)) - }; - var httpClient = TestHelpers.GetTestHttpClient(httpResponse); - var restClient = new RestClient(GoodPublickey, GoodUrlendpoint, httpClient); - var ex = Assert.Throws(() => restClient.CreateFolder(null)); - Assert.Equal(ErrorMessages.InvalidCreateFolderValue, ex.Message); - } - - [Fact] - public void Missing_folderName_ExceptionNonAsync() - { - CreateFolderRequest model = new CreateFolderRequest - { - parentFolderPath = "test" - }; - var responseObj = TestHelpers.ImagekitResponseFaker.Generate(); - - var httpResponse = new HttpResponseMessage - { - StatusCode = HttpStatusCode.OK, - Content = new StringContent(JsonConvert.SerializeObject(responseObj)) - }; - var httpClient = TestHelpers.GetTestHttpClient(httpResponse); - var restClient = new RestClient(GoodPublickey, GoodUrlendpoint, httpClient); - var ex = Assert.Throws(() => restClient.CreateFolder(model)); - Assert.Equal(ErrorMessages.InvalidfolderNameValue, ex.Message); - } - [Fact] - public void Missing_parentFolderPath_FolderExceptionNonAsync() - { - CreateFolderRequest model = new CreateFolderRequest - { - folderName = "test" - }; - var responseObj = TestHelpers.ImagekitResponseFaker.Generate(); - - var httpResponse = new HttpResponseMessage - { - StatusCode = HttpStatusCode.OK, - Content = new StringContent(JsonConvert.SerializeObject(responseObj)) - }; - var httpClient = TestHelpers.GetTestHttpClient(httpResponse); - var restClient = new RestClient(GoodPublickey, GoodUrlendpoint, httpClient); - var ex = Assert.Throws(() => restClient.CreateFolder(model)); - Assert.Equal(ErrorMessages.InvalidFolderPathValue, ex.Message); - } - [Fact] - public void DeleteFolder_DefaultNonAsync() - { - DeleteFolderRequest model = new DeleteFolderRequest - { - folderPath = "Tst3" - }; - - - var responseObj = TestHelpers.ImagekitResponseFaker.Generate(); - var httpResponse = new HttpResponseMessage - { - StatusCode = HttpStatusCode.OK, - Content = new StringContent(JsonConvert.SerializeObject(responseObj)) - }; - var httpClient = TestHelpers.GetTestHttpClient(httpResponse); - var restClient = new RestClient(GoodPublickey, GoodUrlendpoint, httpClient); - - var response = restClient.DeleteFolder(model); - var responseObj1 = JsonConvert.SerializeObject(responseObj); - Assert.Equal(responseObj1, response.Raw); - } - [Fact] - public void Missing_Folder_Path_ExceptionNonAsync() - { - DeleteFolderRequest model = new DeleteFolderRequest(); - var responseObj = TestHelpers.ImagekitResponseFaker.Generate(); - - var httpResponse = new HttpResponseMessage - { - StatusCode = HttpStatusCode.OK, - Content = new StringContent(JsonConvert.SerializeObject(responseObj)) - }; - var httpClient = TestHelpers.GetTestHttpClient(httpResponse); - var restClient = new RestClient(GoodPublickey, GoodUrlendpoint, httpClient); - var ex = Assert.Throws(() => restClient.DeleteFolder(model)); - Assert.Equal(ErrorMessages.InvalidDelFolderValue, ex.Message); - } - - - [Fact] - public void CopyFolder_DefaultNonAsync() - { - CopyFolderRequest model = new CopyFolderRequest - { - sourceFolderPath = "Tst3", - destinationPath = "Tst3", - includeFileVersions = true - }; - var responseObj = TestHelpers.ImagekitResponseFaker.Generate(); - var httpResponse = new HttpResponseMessage - { - StatusCode = HttpStatusCode.OK, - Content = new StringContent(JsonConvert.SerializeObject(responseObj)) - }; - var httpClient = TestHelpers.GetTestHttpClient(httpResponse); - var restClient = new RestClient(GoodPublickey, GoodUrlendpoint, httpClient); - - var response = restClient.CopyFolder(model); - var responseObj1 = JsonConvert.SerializeObject(responseObj); - Assert.Equal(responseObj1, response.Raw); - } - - [Fact] - public void Missing_Obj_FolderExceptionNonAsync() - { - var responseObj = TestHelpers.ImagekitResponseFaker.Generate(); - var httpResponse = new HttpResponseMessage - { - StatusCode = HttpStatusCode.OK, - Content = new StringContent(JsonConvert.SerializeObject(responseObj)) - }; - var httpClient = TestHelpers.GetTestHttpClient(httpResponse); - var restClient = new RestClient(GoodPublickey, GoodUrlendpoint, httpClient); - var ex = Assert.Throws(() => restClient.CopyFolder(null)); - Assert.Equal(ErrorMessages.InvalidCopyFolderValue, ex.Message); - } - [Fact] - public void Missing_sourceFolderPath_FolderExceptionNonAsync() - { - CopyFolderRequest model = new CopyFolderRequest - { - destinationPath = "abc" - }; - - var responseObj = TestHelpers.ImagekitResponseFaker.Generate(); - var httpResponse = new HttpResponseMessage - { - StatusCode = HttpStatusCode.OK, - Content = new StringContent(JsonConvert.SerializeObject(responseObj)) - }; - var httpClient = TestHelpers.GetTestHttpClient(httpResponse); - var restClient = new RestClient(GoodPublickey, GoodUrlendpoint, httpClient); - var ex = Assert.Throws(() => restClient.CopyFolder(model)); - Assert.Equal(ErrorMessages.InvalidCopysourceFolderPathValue, ex.Message); - } - [Fact] - public void Missing_Destination_FolderPath_FolderExceptionNonAsync() - { - CopyFolderRequest model = new CopyFolderRequest - { - sourceFolderPath = "abc" - }; - - var responseObj = TestHelpers.ImagekitResponseFaker.Generate(); - var httpResponse = new HttpResponseMessage - { - StatusCode = HttpStatusCode.OK, - Content = new StringContent(JsonConvert.SerializeObject(responseObj)) - }; - var httpClient = TestHelpers.GetTestHttpClient(httpResponse); - var restClient = new RestClient(GoodPublickey, GoodUrlendpoint, httpClient); - var ex = Assert.Throws(() => restClient.CopyFolder(model)); - Assert.Equal(ErrorMessages.InvalidCopydestinationPathValue, ex.Message); - } - - [Fact] - public void MoveFolder_DefaultNonAsync() - { - MoveFolderRequest model = new MoveFolderRequest - { - sourceFolderPath = "Tst3", - destinationPath = "Tst3" - }; - - var responseObj = TestHelpers.ImagekitResponseFaker.Generate(); - var httpResponse = new HttpResponseMessage - { - StatusCode = HttpStatusCode.OK, - Content = new StringContent(JsonConvert.SerializeObject(responseObj)) - }; - var httpClient = TestHelpers.GetTestHttpClient(httpResponse); - var restClient = new RestClient(GoodPublickey, GoodUrlendpoint, httpClient); - - var response = restClient.MoveFolder(model); - var responseObj1 = JsonConvert.SerializeObject(responseObj); - Assert.Equal(responseObj1, response.Raw); - } - - [Fact] - public void Missing_Obj_Move_FolderExceptionNonAsync() - { - var responseObj = TestHelpers.ImagekitResponseFaker.Generate(); - - var httpResponse = new HttpResponseMessage - { - StatusCode = HttpStatusCode.OK, - Content = new StringContent(JsonConvert.SerializeObject(responseObj)) - }; - var httpClient = TestHelpers.GetTestHttpClient(httpResponse); - var restClient = new RestClient(GoodPublickey, GoodUrlendpoint, httpClient); - var ex = Assert.Throws(() => restClient.MoveFolder(null)); - Assert.Equal(ErrorMessages.InvalidCopyFolderValue, ex.Message); - } - - [Fact] - public void Missing_sourceFolderPath_MoveFolderExceptionNonAsync() - { - MoveFolderRequest model = new MoveFolderRequest - { - destinationPath = "abc" - }; - - var responseObj = TestHelpers.ImagekitResponseFaker.Generate(); - var httpResponse = new HttpResponseMessage - { - StatusCode = HttpStatusCode.OK, - Content = new StringContent(JsonConvert.SerializeObject(responseObj)) - }; - var httpClient = TestHelpers.GetTestHttpClient(httpResponse); - var restClient = new RestClient(GoodPublickey, GoodUrlendpoint, httpClient); - var ex = Assert.Throws(() => restClient.MoveFolder(model)); - Assert.Equal(ErrorMessages.InvalidCopysourceFolderPathValue, ex.Message); - } - [Fact] - public void Missing_Destination_FolderPath_MoveFolderExceptionNonAsync() - { - MoveFolderRequest model = new MoveFolderRequest - { - sourceFolderPath = "abc" - }; - - var responseObj = TestHelpers.ImagekitResponseFaker.Generate(); - var httpResponse = new HttpResponseMessage - { - StatusCode = HttpStatusCode.OK, - Content = new StringContent(JsonConvert.SerializeObject(responseObj)) - }; - var httpClient = TestHelpers.GetTestHttpClient(httpResponse); - var restClient = new RestClient(GoodPublickey, GoodUrlendpoint, httpClient); - var ex = Assert.Throws(() => restClient.MoveFolder(model)); - Assert.Equal(ErrorMessages.InvalidCopydestinationPathValue, ex.Message); - } - - } -} - - - - diff --git a/Imagekit.UnitTests/MetaData/MetaDataTestAsync.cs b/Imagekit.UnitTests/MetaData/MetaDataTestAsync.cs deleted file mode 100644 index af0f8d52..00000000 --- a/Imagekit.UnitTests/MetaData/MetaDataTestAsync.cs +++ /dev/null @@ -1,557 +0,0 @@ -using Imagekit.Constant; -using Imagekit.Models; -using Newtonsoft.Json; -using System; -using System.Collections.Generic; -using System.Net; -using System.Net.Http; -using Imagekit.Models.Response; -using Xunit; -using static Imagekit.Models.CustomMetaDataFieldSchemaObject; -using Newtonsoft.Json.Linq; - -namespace Imagekit.UnitTests.MetaData -{ - - public class MetaDataTestAsync - { - private const string GOOD_PUBLICKEY = "abc"; - private const string GOOD_URLENDPOINT = "https://dasdsad.dad.io/"; - - - - [Fact] - public void GetFileMetadata_Default() - { - - - var responseObj = TestHelpers.ImagekitResponseFaker.Generate(); - - var httpResponse = new HttpResponseMessage - { - StatusCode = HttpStatusCode.OK, - Content = new StringContent(JsonConvert.SerializeObject(responseObj)) - }; - var httpClient = TestHelpers.GetTestHttpClient(httpResponse); - var restClient = new RestClient(GOOD_PUBLICKEY, GOOD_URLENDPOINT, httpClient); - - var response = (ResultMetaData)restClient.GetFileMetaDataAsync("abc").Result; - var responseObj1 = JsonConvert.SerializeObject(responseObj.Raw); - responseObj1 = JToken.Parse(responseObj1).ToString(); - - Assert.Equal(responseObj.Raw, responseObj1); - } - [Fact] - public void GetFileMetadataException() - { - List ob = new List(); - var responseObj = TestHelpers.ImagekitResponseFaker.Generate(); - - var httpResponse = new HttpResponseMessage - { - StatusCode = HttpStatusCode.OK, - Content = new StringContent(JsonConvert.SerializeObject(responseObj)) - }; - var httpClient = TestHelpers.GetTestHttpClient(httpResponse); - var restClient = new RestClient(GOOD_PUBLICKEY, GOOD_URLENDPOINT, httpClient); - var ex = Assert.Throws(() => restClient.GetFileMetaData("")); - Assert.Equal(ErrorMessages.FileIdMissing, ex.Message); - } - - - [Fact] - public void GetRemoteFileMetadata_Default() - { - - - var responseObj = TestHelpers.ImagekitResponseFaker.Generate(); - - var httpResponse = new HttpResponseMessage - { - StatusCode = HttpStatusCode.OK, - Content = new StringContent(JsonConvert.SerializeObject(responseObj)) - }; - var httpClient = TestHelpers.GetTestHttpClient(httpResponse); - var restClient = new RestClient(GOOD_PUBLICKEY, GOOD_URLENDPOINT, httpClient); - - var response = (ResultMetaData)restClient.GetRemoteFileMetaDataAsync("abc").Result; - var responseObj1 = JsonConvert.SerializeObject(responseObj.Raw); - responseObj1 = JToken.Parse(responseObj1).ToString(); - - Assert.Equal(responseObj.Raw, responseObj1); - } - [Fact] - public void GetRemoteFileMetadataException() - { - List ob = new List(); - var responseObj = TestHelpers.ImagekitResponseFaker.Generate(); - - var httpResponse = new HttpResponseMessage - { - StatusCode = HttpStatusCode.OK, - Content = new StringContent(JsonConvert.SerializeObject(responseObj)) - }; - var httpClient = TestHelpers.GetTestHttpClient(httpResponse); - var restClient = new RestClient(GOOD_PUBLICKEY, GOOD_URLENDPOINT, httpClient); - var ex = Assert.ThrowsAsync(async () => await restClient.GetRemoteFileMetaDataAsync("")); - Assert.Equal(ErrorMessages.InvalidUrlValue, ex.Result.Message); - } - - - [Fact] - public void GetCustomMetaDataFields_Default() - { - - var responseObj = TestHelpers.ImagekitResponseFaker.Generate(); - var httpResponse = new HttpResponseMessage - { - StatusCode = HttpStatusCode.OK, - Content = new StringContent(JsonConvert.SerializeObject(responseObj)) - }; - var httpClient = TestHelpers.GetTestHttpClient(httpResponse); - var restClient = new RestClient(GOOD_PUBLICKEY, GOOD_URLENDPOINT, httpClient); - - var response = restClient.GetCustomMetaDataFieldsAsync(true).Result; - var responseObj1 = JsonConvert.SerializeObject(responseObj); - Assert.Equal(responseObj1, response.Raw); - } - - [Fact] - public void CreateCustomMetaDataFields_Default() - { - CustomMetaDataFieldCreateRequest model = new CustomMetaDataFieldCreateRequest - { - name = "Tst3", - label = "Test3" - }; - CustomMetaDataFieldSchemaObject schema = new CustomMetaDataFieldSchemaObject - { - type = "Number", - minValue = 1000, - maxValue = 3000, - minLength = 500, - maxLength = 600, - isValueRequired = false - }; - - model.schema = schema; - var responseObj = TestHelpers.ImagekitResponseFaker.Generate(); - var httpResponse = new HttpResponseMessage - { - StatusCode = HttpStatusCode.OK, - Content = new StringContent(JsonConvert.SerializeObject(responseObj)) - }; - var httpClient = TestHelpers.GetTestHttpClient(httpResponse); - var restClient = new RestClient(GOOD_PUBLICKEY, GOOD_URLENDPOINT, httpClient); - - var response = restClient.CreateCustomMetaDataFieldsAsync(model).Result; - var responseObj1 = JsonConvert.SerializeObject(responseObj); - Assert.Equal(responseObj1, response.Raw); - } - - [Fact] - public void CreateCustomMetaDataFields_Type_Date() - { - CustomMetaDataFieldCreateRequest model = new CustomMetaDataFieldCreateRequest - { - name = "Tst3", - label = "Test3" - }; - CustomMetaDataFieldSchemaObject schema = new CustomMetaDataFieldSchemaObject - { - type = "Number", - minValue = 1000, - maxValue = 3000, - minLength = 500, - maxLength = 600, - isValueRequired = false - }; - - model.schema = schema; - var responseObj = TestHelpers.ImagekitResponseFaker.Generate(); - var httpResponse = new HttpResponseMessage - { - StatusCode = HttpStatusCode.OK, - Content = new StringContent(JsonConvert.SerializeObject(responseObj)) - }; - var httpClient = TestHelpers.GetTestHttpClient(httpResponse); - var restClient = new RestClient(GOOD_PUBLICKEY, GOOD_URLENDPOINT, httpClient); - - var response = restClient.CreateCustomMetaDataFieldsAsync(model).Result; - var responseObj1 = JsonConvert.SerializeObject(responseObj); - Assert.Equal(responseObj1, response.Raw); - } - [Fact] - public void CreateCustomMetaDataFields_Type_Text() - { - CustomMetaDataFieldCreateRequest model = new CustomMetaDataFieldCreateRequest - { - name = "Tst3", - label = "Test3" - }; - CustomMetaDataFieldSchemaObject schema = new CustomMetaDataFieldSchemaObject - { - type = "Number", - minValue = 1000, - maxValue = 3000 - - }; - - model.schema = schema; - var responseObj = TestHelpers.ImagekitResponseFaker.Generate(); - var httpResponse = new HttpResponseMessage - { - StatusCode = HttpStatusCode.OK, - Content = new StringContent(JsonConvert.SerializeObject(responseObj)) - }; - var httpClient = TestHelpers.GetTestHttpClient(httpResponse); - var restClient = new RestClient(GOOD_PUBLICKEY, GOOD_URLENDPOINT, httpClient); - - var response = restClient.CreateCustomMetaDataFieldsAsync(model).Result; - var responseObj1 = JsonConvert.SerializeObject(responseObj); - Assert.Equal(responseObj1, response.Raw); - } - - [Fact] - public void CreateCustomMetaDataFields_Type_TextArea() - { - - CustomMetaDataFieldCreateRequest model = new CustomMetaDataFieldCreateRequest - { - name = "Tst3", - label = "Test3" - }; - CustomMetaDataFieldSchemaObject schema = new CustomMetaDataFieldSchemaObject - { - type = "Number", - minValue = 1000, - maxValue = 3000 - - }; - - model.schema = schema; - var responseObj = TestHelpers.ImagekitResponseFaker.Generate(); - var httpResponse = new HttpResponseMessage - { - StatusCode = HttpStatusCode.OK, - Content = new StringContent(JsonConvert.SerializeObject(responseObj)) - }; - var httpClient = TestHelpers.GetTestHttpClient(httpResponse); - var restClient = new RestClient(GOOD_PUBLICKEY, GOOD_URLENDPOINT, httpClient); - - var response = restClient.CreateCustomMetaDataFieldsAsync(model).Result; - var responseObj1 = JsonConvert.SerializeObject(responseObj); - Assert.Equal(responseObj1, response.Raw); - } - - [Fact] - public void CreateCustomMetaDataFields_successExpected_type_SingleSelect() - { - - List objectList = new List - { - "small", - "medium", - "large", - 30, - 40, - true - }; - - CustomMetaDataFieldCreateRequest model = new CustomMetaDataFieldCreateRequest - { - name = "Tst3", - label = "Test3" - }; - CustomMetaDataFieldSchemaObject schema = new CustomMetaDataFieldSchemaObject - { - type = "Number", - minValue = 1000, - maxValue = 3000 - }; - - model.schema = schema; - var responseObj = TestHelpers.ImagekitResponseFaker.Generate(); - var httpResponse = new HttpResponseMessage - { - StatusCode = HttpStatusCode.OK, - Content = new StringContent(JsonConvert.SerializeObject(responseObj)) - }; - var httpClient = TestHelpers.GetTestHttpClient(httpResponse); - var restClient = new RestClient(GOOD_PUBLICKEY, GOOD_URLENDPOINT, httpClient); - - var response = restClient.CreateCustomMetaDataFieldsAsync(model).Result; - var responseObj1 = JsonConvert.SerializeObject(responseObj); - Assert.Equal(responseObj1, response.Raw); - } - [Fact] - public void CreateCustomMetaDataFields_successExpected_type_MultiSelect() - { - CustomMetaDataFieldCreateRequest model = new CustomMetaDataFieldCreateRequest - { - name = "Tst3", - label = "Test3" - }; - List objectList = new List - { - "small", - "medium", - "large", - 30, - 40, - true - }; - - CustomMetaDataFieldCreateRequest customMetaDataFieldSchemaObject = new CustomMetaDataFieldCreateRequest - { - name = "Tst3", - label = "Test3" - }; - CustomMetaDataFieldSchemaObject schema = new CustomMetaDataFieldSchemaObject - { - type = "Number", - minValue = 1000, - maxValue = 3000 - }; - - model.schema = schema; - - var responseObj = TestHelpers.ImagekitResponseFaker.Generate(); - var httpResponse = new HttpResponseMessage - { - StatusCode = HttpStatusCode.OK, - Content = new StringContent(JsonConvert.SerializeObject(responseObj)) - }; - var httpClient = TestHelpers.GetTestHttpClient(httpResponse); - var restClient = new RestClient(GOOD_PUBLICKEY, GOOD_URLENDPOINT, httpClient); - - var response = restClient.CreateCustomMetaDataFieldsAsync(model).Result; - var responseObj1 = JsonConvert.SerializeObject(responseObj); - Assert.Equal(responseObj1, response.Raw); - } - [Fact] - public void CreateCustomMetaDataFieldsException() - { - CustomMetaDataFieldCreateRequest model = null; - var responseObj = TestHelpers.ImagekitResponseFaker.Generate(); - - var httpResponse = new HttpResponseMessage - { - StatusCode = HttpStatusCode.OK, - Content = new StringContent(JsonConvert.SerializeObject(responseObj)) - }; - var httpClient = TestHelpers.GetTestHttpClient(httpResponse); - var restClient = new RestClient(GOOD_PUBLICKEY, GOOD_URLENDPOINT, httpClient); - var ex = Assert.ThrowsAsync(async () => await restClient.CreateCustomMetaDataFieldsAsync(model)); - Assert.Equal(ErrorMessages.InvalidMetaTagValue, ex.Result.Message); - } - [Fact] - public void Missing_Name_CustomMetaDataFieldsException() - { - CustomMetaDataFieldCreateRequest model = new CustomMetaDataFieldCreateRequest - { - name = string.Empty - }; - CustomMetaDataFieldSchemaObject ob = new CustomMetaDataFieldSchemaObject - { - maxValue = 1000 - }; - model.schema = ob; - - var responseObj = TestHelpers.ImagekitResponseFaker.Generate(); - - var httpResponse = new HttpResponseMessage - { - StatusCode = HttpStatusCode.OK, - Content = new StringContent(JsonConvert.SerializeObject(responseObj)) - }; - var httpClient = TestHelpers.GetTestHttpClient(httpResponse); - var restClient = new RestClient(GOOD_PUBLICKEY, GOOD_URLENDPOINT, httpClient); - var ex = Assert.ThrowsAsync(async () => await restClient.CreateCustomMetaDataFieldsAsync(model)); - Assert.Equal(ErrorMessages.InvalidMetaTagNameValue, ex.Result.Message); - } - [Fact] - public void Missing_Label_CustomMetaDataFieldsException() - { - CustomMetaDataFieldCreateRequest model = new CustomMetaDataFieldCreateRequest - { - name = "abc", - label = string.Empty - }; - CustomMetaDataFieldSchemaObject ob = new CustomMetaDataFieldSchemaObject - { - maxValue = 1000 - }; - model.schema = ob; - - - - var responseObj = TestHelpers.ImagekitResponseFaker.Generate(); - - var httpResponse = new HttpResponseMessage - { - StatusCode = HttpStatusCode.OK, - Content = new StringContent(JsonConvert.SerializeObject(responseObj)) - }; - var httpClient = TestHelpers.GetTestHttpClient(httpResponse); - var restClient = new RestClient(GOOD_PUBLICKEY, GOOD_URLENDPOINT, httpClient); - var ex = Assert.ThrowsAsync(async () => await restClient.CreateCustomMetaDataFieldsAsync(model)); - Assert.Equal(ErrorMessages.InvalidMetaTagLabelValue, ex.Result.Message); - } - [Fact] - public void Missing_Schema_CustomMetaDataFieldsException() - { - CustomMetaDataFieldCreateRequest model = new CustomMetaDataFieldCreateRequest - { - name = "abc", - label = "test", - schema = null - }; - var responseObj = TestHelpers.ImagekitResponseFaker.Generate(); - - var httpResponse = new HttpResponseMessage - { - StatusCode = HttpStatusCode.OK, - Content = new StringContent(JsonConvert.SerializeObject(responseObj)) - }; - var httpClient = TestHelpers.GetTestHttpClient(httpResponse); - var restClient = new RestClient(GOOD_PUBLICKEY, GOOD_URLENDPOINT, httpClient); - var ex = Assert.ThrowsAsync(async () => await restClient.CreateCustomMetaDataFieldsAsync(model)); - Assert.Equal(ErrorMessages.InvalidMetaTagSchemaValue, ex.Result.Message); - } - - [Fact] - public void DeleteCustomMetaDataField_Default() - { - var responseObj = TestHelpers.ImagekitResponseFaker.Generate(); - var httpResponse = new HttpResponseMessage - { - StatusCode = HttpStatusCode.OK, - Content = new StringContent(JsonConvert.SerializeObject(responseObj)) - }; - var httpClient = TestHelpers.GetTestHttpClient(httpResponse); - var restClient = new RestClient(GOOD_PUBLICKEY, GOOD_URLENDPOINT, httpClient); - - var response = restClient.DeleteCustomMetaDataFieldAsync("abc").Result; - var responseObj1 = JsonConvert.SerializeObject(responseObj); - Assert.Equal(responseObj1, response.Raw); - } - - - [Fact] - public void Missing_fileId_CustomMetaDataFieldException() - { - - var responseObj = TestHelpers.ImagekitResponseFaker.Generate(); - - var httpResponse = new HttpResponseMessage - { - StatusCode = HttpStatusCode.OK, - Content = new StringContent(JsonConvert.SerializeObject(responseObj)) - }; - var httpClient = TestHelpers.GetTestHttpClient(httpResponse); - var restClient = new RestClient(GOOD_PUBLICKEY, GOOD_URLENDPOINT, httpClient); - var ex = Assert.ThrowsAsync(async () => await restClient.DeleteCustomMetaDataFieldAsync("")); - Assert.Equal(ErrorMessages.InvalidfileIdsValue, ex.Result.Message); - } - - - - [Fact] - public void UpdateCustomMetaDataFields_Default() - { - CustomMetaDataFieldUpdateRequest model = new CustomMetaDataFieldUpdateRequest - { - Id = "Tst3" - }; - - CustomMetaDataFieldSchemaObject schema = new CustomMetaDataFieldSchemaObject - { - type = "Number", - minValue = 1000, - maxValue = 3000 - }; - model.schema = schema; - var responseObj = TestHelpers.ImagekitResponseFaker.Generate(); - var httpResponse = new HttpResponseMessage - { - StatusCode = HttpStatusCode.OK, - Content = new StringContent(JsonConvert.SerializeObject(responseObj)) - }; - var httpClient = TestHelpers.GetTestHttpClient(httpResponse); - var restClient = new RestClient(GOOD_PUBLICKEY, GOOD_URLENDPOINT, httpClient); - - var response = restClient.UpdateCustomMetaDataFieldsAsync(model).Result; - var responseObj1 = JsonConvert.SerializeObject(responseObj); - Assert.Equal(responseObj1, response.Raw); - } - - [Fact] - public void Missing_Object_CustomMetaDataFieldsException() - { - CustomMetaDataFieldUpdateRequest model = null; - var responseObj = TestHelpers.ImagekitResponseFaker.Generate(); - - var httpResponse = new HttpResponseMessage - { - StatusCode = HttpStatusCode.OK, - Content = new StringContent(JsonConvert.SerializeObject(responseObj)) - }; - var httpClient = TestHelpers.GetTestHttpClient(httpResponse); - var restClient = new RestClient(GOOD_PUBLICKEY, GOOD_URLENDPOINT, httpClient); - var ex = Assert.ThrowsAsync(async () => await restClient.UpdateCustomMetaDataFieldsAsync(model)); - Assert.Equal(ErrorMessages.InvalidMetaTagValue, ex.Result.Message); - } - - [Fact] - public void Missing_ID_CustomUpdateMetaDataFieldsException() - { - CustomMetaDataFieldUpdateRequest model = new CustomMetaDataFieldUpdateRequest - { - Id = "" - }; - CustomMetaDataFieldSchemaObject ob = new CustomMetaDataFieldSchemaObject - { - maxValue = 1000 - }; - model.schema = ob; - - var responseObj = TestHelpers.ImagekitResponseFaker.Generate(); - - var httpResponse = new HttpResponseMessage - { - StatusCode = HttpStatusCode.OK, - Content = new StringContent(JsonConvert.SerializeObject(responseObj)) - }; - var httpClient = TestHelpers.GetTestHttpClient(httpResponse); - var restClient = new RestClient(GOOD_PUBLICKEY, GOOD_URLENDPOINT, httpClient); - var ex = Assert.ThrowsAsync(async () => await restClient.UpdateCustomMetaDataFieldsAsync(model)); - Assert.Equal(ErrorMessages.InvalidMetaTagIdValue, ex.Result.Message); - } - [Fact] - public void Missing_Schema_CustomUpdateMetaDataFieldsException() - { - CustomMetaDataFieldUpdateRequest model = new CustomMetaDataFieldUpdateRequest - { - Id = "abc", - schema = null - }; - var responseObj = TestHelpers.ImagekitResponseFaker.Generate(); - - var httpResponse = new HttpResponseMessage - { - StatusCode = HttpStatusCode.OK, - Content = new StringContent(JsonConvert.SerializeObject(responseObj)) - }; - var httpClient = TestHelpers.GetTestHttpClient(httpResponse); - var restClient = new RestClient(GOOD_PUBLICKEY, GOOD_URLENDPOINT, httpClient); - var ex = Assert.ThrowsAsync(async () => await restClient.UpdateCustomMetaDataFieldsAsync(model)); - Assert.Equal(ErrorMessages.InvalidMetaTagSchemaValue, ex.Result.Message); - } - - } -} - - - - diff --git a/Imagekit.UnitTests/MetaData/MetaDataTestNonAsync.cs b/Imagekit.UnitTests/MetaData/MetaDataTestNonAsync.cs deleted file mode 100644 index b9d0ef24..00000000 --- a/Imagekit.UnitTests/MetaData/MetaDataTestNonAsync.cs +++ /dev/null @@ -1,546 +0,0 @@ -using Imagekit.Constant; -using Imagekit.Models; -using Newtonsoft.Json; -using System; -using System.Collections.Generic; -using System.Net; -using System.Net.Http; -using Xunit; -using static Imagekit.Models.CustomMetaDataFieldSchemaObject; -using Imagekit.Models.Response; -using Newtonsoft.Json.Linq; - -namespace Imagekit.UnitTests.MetaData -{ - - public class MetaDataTestNonAsync - { - private const string GOOD_PUBLICKEY = "abc"; - private const string GOOD_URLENDPOINT = "https://dasdsad.dad.io/"; - - - - [Fact] - public void GetFileMetadata_DefaultNonAsync() - { - - - var responseObj = TestHelpers.ImagekitResponseFaker.Generate(); - - var httpResponse = new HttpResponseMessage - { - StatusCode = HttpStatusCode.OK, - Content = new StringContent(JsonConvert.SerializeObject(responseObj)) - }; - var httpClient = TestHelpers.GetTestHttpClient(httpResponse); - var restClient = new RestClient(GOOD_PUBLICKEY, GOOD_URLENDPOINT, httpClient); - - var response = (ResultMetaData)restClient.GetFileMetaData("abc"); - var responseObj1 = JsonConvert.SerializeObject(responseObj.Raw); - responseObj1 = JToken.Parse(responseObj1).ToString(); - - Assert.Equal(responseObj.Raw, responseObj1); - } - [Fact] - public void GetFileMetadataExceptionNonAsync() - { - List ob = new List(); - var responseObj = TestHelpers.ImagekitResponseFaker.Generate(); - - var httpResponse = new HttpResponseMessage - { - StatusCode = HttpStatusCode.OK, - Content = new StringContent(JsonConvert.SerializeObject(responseObj)) - }; - var httpClient = TestHelpers.GetTestHttpClient(httpResponse); - var restClient = new RestClient(GOOD_PUBLICKEY, GOOD_URLENDPOINT, httpClient); - var ex = Assert.Throws(() => restClient.GetFileMetaData("")); - Assert.Equal(ErrorMessages.FileIdMissing, ex.Message); - } - - - [Fact] - public void GetRemoteFileMetadata_DefaultNonAsync() - { - - - var responseObj = TestHelpers.ImagekitResponseFaker.Generate(); - - var httpResponse = new HttpResponseMessage - { - StatusCode = HttpStatusCode.OK, - Content = new StringContent(JsonConvert.SerializeObject(responseObj)) - }; - var httpClient = TestHelpers.GetTestHttpClient(httpResponse); - var restClient = new RestClient(GOOD_PUBLICKEY, GOOD_URLENDPOINT, httpClient); - - var response = (ResultMetaData)restClient.GetRemoteFileMetaData("abc"); - var responseObj1 = JsonConvert.SerializeObject(responseObj.Raw); - responseObj1 = JToken.Parse(responseObj1).ToString(); - - Assert.Equal(responseObj.Raw, responseObj1); - } - [Fact] - public void GetRemoteFileMetadataExceptionNonAsync() - { - List ob = new List(); - var responseObj = TestHelpers.ImagekitResponseFaker.Generate(); - - var httpResponse = new HttpResponseMessage - { - StatusCode = HttpStatusCode.OK, - Content = new StringContent(JsonConvert.SerializeObject(responseObj)) - }; - var httpClient = TestHelpers.GetTestHttpClient(httpResponse); - var restClient = new RestClient(GOOD_PUBLICKEY, GOOD_URLENDPOINT, httpClient); - var ex = Assert.Throws(() => restClient.GetRemoteFileMetaData("")); - Assert.Equal(ErrorMessages.InvalidUrlValue, ex.Message); - } - - - [Fact] - public void GetCustomMetaDataFields_DefaultNonAsync() - { - - var responseObj = TestHelpers.ImagekitResponseFaker.Generate(); - var httpResponse = new HttpResponseMessage - { - StatusCode = HttpStatusCode.OK, - Content = new StringContent(JsonConvert.SerializeObject(responseObj)) - }; - var httpClient = TestHelpers.GetTestHttpClient(httpResponse); - var restClient = new RestClient(GOOD_PUBLICKEY, GOOD_URLENDPOINT, httpClient); - - var response = restClient.GetCustomMetaDataFields(true); - var responseObj1 = JsonConvert.SerializeObject(responseObj); - Assert.Equal(responseObj1, response.Raw); - } - - [Fact] - public void CreateCustomMetaDataFields_DefaultNonAsync() - { - CustomMetaDataFieldCreateRequest model = new CustomMetaDataFieldCreateRequest - { - name = "Tst3", - label = "Test3" - }; - CustomMetaDataFieldSchemaObject schema = new CustomMetaDataFieldSchemaObject - { - type = "Number", - minValue = 1000, - maxValue = 3000, - minLength = 500, - maxLength = 600, - isValueRequired = false - }; - - model.schema = schema; - var responseObj = TestHelpers.ImagekitResponseFaker.Generate(); - var httpResponse = new HttpResponseMessage - { - StatusCode = HttpStatusCode.OK, - Content = new StringContent(JsonConvert.SerializeObject(responseObj)) - }; - var httpClient = TestHelpers.GetTestHttpClient(httpResponse); - var restClient = new RestClient(GOOD_PUBLICKEY, GOOD_URLENDPOINT, httpClient); - - var response = restClient.CreateCustomMetaDataFields(model); - var responseObj1 = JsonConvert.SerializeObject(responseObj); - Assert.Equal(responseObj1, response.Raw); - } - - [Fact] - public void CreateCustomMetaDataFields_Type_Date() - { - CustomMetaDataFieldCreateRequest model = new CustomMetaDataFieldCreateRequest - { - name = "Tst3", - label = "Test3" - }; - CustomMetaDataFieldSchemaObject schema = new CustomMetaDataFieldSchemaObject - { - type = "Number", - minValue = 1000, - maxValue = 3000, - minLength = 500, - maxLength = 600, - isValueRequired = false - }; - - model.schema = schema; - var responseObj = TestHelpers.ImagekitResponseFaker.Generate(); - var httpResponse = new HttpResponseMessage - { - StatusCode = HttpStatusCode.OK, - Content = new StringContent(JsonConvert.SerializeObject(responseObj)) - }; - var httpClient = TestHelpers.GetTestHttpClient(httpResponse); - var restClient = new RestClient(GOOD_PUBLICKEY, GOOD_URLENDPOINT, httpClient); - - var response = restClient.CreateCustomMetaDataFields(model); - var responseObj1 = JsonConvert.SerializeObject(responseObj); - Assert.Equal(responseObj1, response.Raw); - } - [Fact] - public void CreateCustomMetaDataFields_Type_Text() - { - CustomMetaDataFieldCreateRequest model = new CustomMetaDataFieldCreateRequest - { - name = "Tst3", - label = "Test3" - }; - CustomMetaDataFieldSchemaObject schema = new CustomMetaDataFieldSchemaObject - { - type = "Number", - minValue = 1000, - maxValue = 3000, - minLength = 500, - maxLength = 600, - isValueRequired = false - }; - - model.schema = schema; - var responseObj = TestHelpers.ImagekitResponseFaker.Generate(); - var httpResponse = new HttpResponseMessage - { - StatusCode = HttpStatusCode.OK, - Content = new StringContent(JsonConvert.SerializeObject(responseObj)) - }; - var httpClient = TestHelpers.GetTestHttpClient(httpResponse); - var restClient = new RestClient(GOOD_PUBLICKEY, GOOD_URLENDPOINT, httpClient); - - var response = restClient.CreateCustomMetaDataFields(model); - var responseObj1 = JsonConvert.SerializeObject(responseObj); - Assert.Equal(responseObj1, response.Raw); - } - - [Fact] - public void CreateCustomMetaDataFields_Type_TextArea() - { - CustomMetaDataFieldCreateRequest model = new CustomMetaDataFieldCreateRequest - { - name = "Tst3", - label = "Test3" - }; - CustomMetaDataFieldSchemaObject schema = new CustomMetaDataFieldSchemaObject - { - type = "Number", - minValue = 1000, - maxValue = 3000, - minLength = 500, - maxLength = 600, - isValueRequired = false - }; - - model.schema = schema; - var responseObj = TestHelpers.ImagekitResponseFaker.Generate(); - var httpResponse = new HttpResponseMessage - { - StatusCode = HttpStatusCode.OK, - Content = new StringContent(JsonConvert.SerializeObject(responseObj)) - }; - var httpClient = TestHelpers.GetTestHttpClient(httpResponse); - var restClient = new RestClient(GOOD_PUBLICKEY, GOOD_URLENDPOINT, httpClient); - - var response = restClient.CreateCustomMetaDataFields(model); - var responseObj1 = JsonConvert.SerializeObject(responseObj); - Assert.Equal(responseObj1, response.Raw); - } - - [Fact] - public void CreateCustomMetaDataFields_successExpected_type_SingleSelect() - { - CustomMetaDataFieldCreateRequest model = new CustomMetaDataFieldCreateRequest - { - name = "Tst3", - label = "Test3" - }; - CustomMetaDataFieldSchemaObject schema = new CustomMetaDataFieldSchemaObject - { - type = "Number", - minValue = 1000, - maxValue = 3000, - minLength = 500, - maxLength = 600, - isValueRequired = false - }; - - model.schema = schema; - var responseObj = TestHelpers.ImagekitResponseFaker.Generate(); - var httpResponse = new HttpResponseMessage - { - StatusCode = HttpStatusCode.OK, - Content = new StringContent(JsonConvert.SerializeObject(responseObj)) - }; - var httpClient = TestHelpers.GetTestHttpClient(httpResponse); - var restClient = new RestClient(GOOD_PUBLICKEY, GOOD_URLENDPOINT, httpClient); - - var response = (ResultCustomMetaDataField)restClient.CreateCustomMetaDataFields(model); - var responseObj1 = JsonConvert.SerializeObject(responseObj); - Assert.Equal(responseObj1, response.Raw); - } - [Fact] - public void CreateCustomMetaDataFields_successExpected_type_MultiSelect() - { - CustomMetaDataFieldCreateRequest model = new CustomMetaDataFieldCreateRequest - { - name = "Tst3", - label = "Test3" - }; - - CustomMetaDataFieldSchemaObject customMetaDataFieldSchemaObject = new CustomMetaDataFieldSchemaObject - { - type = "MultiSelect", - selectOptions = new string[] { "small", "medium", "large" } - }; - - CustomMetaDataFieldSchemaObject schema = new CustomMetaDataFieldSchemaObject - { - type = "Number", - minValue = 1000, - maxValue = 3000, - minLength = 500, - maxLength = 600, - isValueRequired = false - }; - - model.schema = schema; - var responseObj = TestHelpers.ImagekitResponseFaker.Generate(); - var httpResponse = new HttpResponseMessage - { - StatusCode = HttpStatusCode.OK, - Content = new StringContent(JsonConvert.SerializeObject(responseObj)) - }; - var httpClient = TestHelpers.GetTestHttpClient(httpResponse); - var restClient = new RestClient(GOOD_PUBLICKEY, GOOD_URLENDPOINT, httpClient); - - var response = (ResultCustomMetaDataField)restClient.CreateCustomMetaDataFields(model); - var responseObj1 = JsonConvert.SerializeObject(responseObj); - Assert.Equal(responseObj1, response.Raw); - } - [Fact] - public void CreateCustomMetaDataFieldsExceptionNonAsync() - { - CustomMetaDataFieldCreateRequest model = null; - var responseObj = TestHelpers.ImagekitResponseFaker.Generate(); - - var httpResponse = new HttpResponseMessage - { - StatusCode = HttpStatusCode.OK, - Content = new StringContent(JsonConvert.SerializeObject(responseObj)) - }; - var httpClient = TestHelpers.GetTestHttpClient(httpResponse); - var restClient = new RestClient(GOOD_PUBLICKEY, GOOD_URLENDPOINT, httpClient); - var ex = Assert.Throws(() => restClient.CreateCustomMetaDataFields(model)); - Assert.Equal(ErrorMessages.InvalidMetaTagValue, ex.Message); - } - [Fact] - public void Missing_Name_CustomMetaDataFieldsExceptionNonAsync() - { - CustomMetaDataFieldCreateRequest model = new CustomMetaDataFieldCreateRequest - { - name = string.Empty - }; - CustomMetaDataFieldSchemaObject ob = new CustomMetaDataFieldSchemaObject - { - maxValue = 1000 - }; - model.schema = ob; - - var responseObj = TestHelpers.ImagekitResponseFaker.Generate(); - - var httpResponse = new HttpResponseMessage - { - StatusCode = HttpStatusCode.OK, - Content = new StringContent(JsonConvert.SerializeObject(responseObj)) - }; - var httpClient = TestHelpers.GetTestHttpClient(httpResponse); - var restClient = new RestClient(GOOD_PUBLICKEY, GOOD_URLENDPOINT, httpClient); - var ex = Assert.Throws(() => restClient.CreateCustomMetaDataFields(model)); - Assert.Equal(ErrorMessages.InvalidMetaTagNameValue, ex.Message); - } - [Fact] - public void Missing_Label_CustomMetaDataFieldsExceptionNonAsync() - { - CustomMetaDataFieldCreateRequest model = new CustomMetaDataFieldCreateRequest - { - name = "abc", - label = string.Empty - }; - CustomMetaDataFieldSchemaObject ob = new CustomMetaDataFieldSchemaObject - { - maxValue = 1000 - }; - model.schema = ob; - - - - var responseObj = TestHelpers.ImagekitResponseFaker.Generate(); - - var httpResponse = new HttpResponseMessage - { - StatusCode = HttpStatusCode.OK, - Content = new StringContent(JsonConvert.SerializeObject(responseObj)) - }; - var httpClient = TestHelpers.GetTestHttpClient(httpResponse); - var restClient = new RestClient(GOOD_PUBLICKEY, GOOD_URLENDPOINT, httpClient); - var ex = Assert.Throws(() => restClient.CreateCustomMetaDataFields(model)); - Assert.Equal(ErrorMessages.InvalidMetaTagLabelValue, ex.Message); - } - [Fact] - public void Missing_Schema_CustomMetaDataFieldsExceptionNonAsync() - { - CustomMetaDataFieldCreateRequest model = new CustomMetaDataFieldCreateRequest - { - name = "abc", - label = "test", - schema = null - }; - var responseObj = TestHelpers.ImagekitResponseFaker.Generate(); - - var httpResponse = new HttpResponseMessage - { - StatusCode = HttpStatusCode.OK, - Content = new StringContent(JsonConvert.SerializeObject(responseObj)) - }; - var httpClient = TestHelpers.GetTestHttpClient(httpResponse); - var restClient = new RestClient(GOOD_PUBLICKEY, GOOD_URLENDPOINT, httpClient); - var ex = Assert.Throws(() => restClient.CreateCustomMetaDataFields(model)); - Assert.Equal(ErrorMessages.InvalidMetaTagSchemaValue, ex.Message); - } - - [Fact] - public void DeleteCustomMetaDataField_DefaultNonAsync() - { - var responseObj = TestHelpers.ImagekitResponseFaker.Generate(); - var httpResponse = new HttpResponseMessage - { - StatusCode = HttpStatusCode.OK, - Content = new StringContent(JsonConvert.SerializeObject(responseObj)) - }; - var httpClient = TestHelpers.GetTestHttpClient(httpResponse); - var restClient = new RestClient(GOOD_PUBLICKEY, GOOD_URLENDPOINT, httpClient); - - var response = restClient.DeleteCustomMetaDataField("abc"); - var responseObj1 = JsonConvert.SerializeObject(responseObj); - Assert.Equal(responseObj1, response.Raw); - } - - - [Fact] - public void Missing_fileId_CustomMetaDataFieldExceptionNonAsync() - { - - var responseObj = TestHelpers.ImagekitResponseFaker.Generate(); - - var httpResponse = new HttpResponseMessage - { - StatusCode = HttpStatusCode.OK, - Content = new StringContent(JsonConvert.SerializeObject(responseObj)) - }; - var httpClient = TestHelpers.GetTestHttpClient(httpResponse); - var restClient = new RestClient(GOOD_PUBLICKEY, GOOD_URLENDPOINT, httpClient); - var ex = Assert.Throws(() => restClient.DeleteCustomMetaDataField("")); - Assert.Equal(ErrorMessages.InvalidfileIdsValue, ex.Message); - } - - - - [Fact] - public void UpdateCustomMetaDataFields_DefaultNonAsync() - { - CustomMetaDataFieldUpdateRequest model = new CustomMetaDataFieldUpdateRequest - { - Id = "Tst3" - }; - - CustomMetaDataFieldSchemaObject schema = new CustomMetaDataFieldSchemaObject - { - type = "Number", - minValue = 1000, - maxValue = 3000 - }; - model.schema = schema; - var responseObj = TestHelpers.ImagekitResponseFaker.Generate(); - var httpResponse = new HttpResponseMessage - { - StatusCode = HttpStatusCode.OK, - Content = new StringContent(JsonConvert.SerializeObject(responseObj)) - }; - var httpClient = TestHelpers.GetTestHttpClient(httpResponse); - var restClient = new RestClient(GOOD_PUBLICKEY, GOOD_URLENDPOINT, httpClient); - - var response = restClient.UpdateCustomMetaDataFields(model); - var responseObj1 = JsonConvert.SerializeObject(responseObj); - Assert.Equal(responseObj1, response.Raw); - } - - [Fact] - public void Missing_Object_CustomMetaDataFieldsExceptionNonAsync() - { - CustomMetaDataFieldUpdateRequest model = null; - var responseObj = TestHelpers.ImagekitResponseFaker.Generate(); - - var httpResponse = new HttpResponseMessage - { - StatusCode = HttpStatusCode.OK, - Content = new StringContent(JsonConvert.SerializeObject(responseObj)) - }; - var httpClient = TestHelpers.GetTestHttpClient(httpResponse); - var restClient = new RestClient(GOOD_PUBLICKEY, GOOD_URLENDPOINT, httpClient); - var ex = Assert.Throws(() => restClient.UpdateCustomMetaDataFields(model)); - Assert.Equal(ErrorMessages.InvalidMetaTagValue, ex.Message); - } - - [Fact] - public void Missing_ID_CustomUpdateMetaDataFieldsExceptionNonAsync() - { - CustomMetaDataFieldUpdateRequest model = new CustomMetaDataFieldUpdateRequest - { - Id = "" - }; - CustomMetaDataFieldSchemaObject ob = new CustomMetaDataFieldSchemaObject - { - maxValue = 1000 - }; - model.schema = ob; - - var responseObj = TestHelpers.ImagekitResponseFaker.Generate(); - - var httpResponse = new HttpResponseMessage - { - StatusCode = HttpStatusCode.OK, - Content = new StringContent(JsonConvert.SerializeObject(responseObj)) - }; - var httpClient = TestHelpers.GetTestHttpClient(httpResponse); - var restClient = new RestClient(GOOD_PUBLICKEY, GOOD_URLENDPOINT, httpClient); - var ex = Assert.Throws(() => restClient.UpdateCustomMetaDataFields(model)); - Assert.Equal(ErrorMessages.InvalidMetaTagIdValue, ex.Message); - } - [Fact] - public void Missing_Schema_CustomUpdateMetaDataFieldsExceptionNonAsync() - { - CustomMetaDataFieldUpdateRequest model = new CustomMetaDataFieldUpdateRequest - { - Id = "abc", - schema = null - }; - var responseObj = TestHelpers.ImagekitResponseFaker.Generate(); - - var httpResponse = new HttpResponseMessage - { - StatusCode = HttpStatusCode.OK, - Content = new StringContent(JsonConvert.SerializeObject(responseObj)) - }; - var httpClient = TestHelpers.GetTestHttpClient(httpResponse); - var restClient = new RestClient(GOOD_PUBLICKEY, GOOD_URLENDPOINT, httpClient); - var ex = Assert.Throws(() => restClient.UpdateCustomMetaDataFields(model)); - Assert.Equal(ErrorMessages.InvalidMetaTagSchemaValue, ex.Message); - } - - } -} - - - - diff --git a/Imagekit.UnitTests/Sample/test.jpg b/Imagekit.UnitTests/Sample/test.jpg deleted file mode 100644 index 79de088c..00000000 Binary files a/Imagekit.UnitTests/Sample/test.jpg and /dev/null differ diff --git a/Imagekit.UnitTests/Tags/ManageTagsTestAsync.cs b/Imagekit.UnitTests/Tags/ManageTagsTestAsync.cs deleted file mode 100644 index 87d4a1bb..00000000 --- a/Imagekit.UnitTests/Tags/ManageTagsTestAsync.cs +++ /dev/null @@ -1,240 +0,0 @@ -using Imagekit.Constant; -using Newtonsoft.Json; -using System; -using System.Collections.Generic; -using System.Net; -using System.Net.Http; -using Xunit; - -namespace Imagekit.UnitTests.Tags -{ - - public class ManageTagsTestAsync - { - private const string GOOD_PUBLICKEY = "abc"; - private const string GOOD_URLENDPOINT = "https://dasdsad.dad.io/"; - - - [Fact] - public void AddTags_Default() - { - TagsRequest tagsRequest = new TagsRequest - { - tags = new List - { - "abc", - "abc" - }, - fileIds = new List - { - "abc" - } - }; - - var responseObj = TestHelpers.ImagekitResponseFaker.Generate(); - var httpResponse = new HttpResponseMessage - { - StatusCode = HttpStatusCode.OK, - Content = new StringContent(JsonConvert.SerializeObject(responseObj)) - }; - var httpClient = TestHelpers.GetTestHttpClient(httpResponse); - var restClient = new RestClient(GOOD_PUBLICKEY, GOOD_URLENDPOINT, httpClient); - - var response = restClient.ManageTagsAsync(tagsRequest, "addTags").Result; - var responseObj1 = JsonConvert.SerializeObject(responseObj); - Assert.Equal(responseObj1, response.Raw); - } - - [Fact] - public void AddTags_Null_Exception() - { - TagsRequest ob = null; - var responseObj = TestHelpers.ImagekitResponseFaker.Generate(); - - var httpResponse = new HttpResponseMessage - { - StatusCode = HttpStatusCode.OK, - Content = new StringContent(JsonConvert.SerializeObject(responseObj)) - }; - var httpClient = TestHelpers.GetTestHttpClient(httpResponse); - var restClient = new RestClient(GOOD_PUBLICKEY, GOOD_URLENDPOINT, httpClient); - var ex = Assert.ThrowsAsync(async () => await restClient.ManageTagsAsync(ob, "")); - Assert.Equal(ErrorMessages.InvalidTagValue, ex.Result.Message); - } - [Fact] - public void Missing_Tags_Null_Exception() - { - TagsRequest ob = new TagsRequest - { - tags = null, - fileIds = new List { "abc" } - }; - var responseObj = TestHelpers.ImagekitResponseFaker.Generate(); - - var httpResponse = new HttpResponseMessage - { - StatusCode = HttpStatusCode.OK, - Content = new StringContent(JsonConvert.SerializeObject(responseObj)) - }; - var httpClient = TestHelpers.GetTestHttpClient(httpResponse); - var restClient = new RestClient(GOOD_PUBLICKEY, GOOD_URLENDPOINT, httpClient); - var ex = Assert.ThrowsAsync(async () => await restClient.ManageTagsAsync(ob, "")); - Assert.Equal(ErrorMessages.InvalidTagParamValue, ex.Result.Message); - } - - [Fact] - public void Missing_Filed_Null_Exception() - { - TagsRequest ob = new TagsRequest - { - tags = new List { "abc" }, - fileIds = null - }; - - var responseObj = TestHelpers.ImagekitResponseFaker.Generate(); - - var httpResponse = new HttpResponseMessage - { - StatusCode = HttpStatusCode.OK, - Content = new StringContent(JsonConvert.SerializeObject(responseObj)) - }; - var httpClient = TestHelpers.GetTestHttpClient(httpResponse); - var restClient = new RestClient(GOOD_PUBLICKEY, GOOD_URLENDPOINT, httpClient); - var ex = Assert.ThrowsAsync(async () => await restClient.ManageTagsAsync(ob, "")); - Assert.Equal(ErrorMessages.InvalidFiledParamValue, ex.Result.Message); - } - - - [Fact] - public void RemoveTags_Default() - { - TagsRequest tagsRequest = new TagsRequest - { - tags = new List - { - "abc", - "abc" - }, - fileIds = new List - { - "abc" - } - }; - - var responseObj = TestHelpers.ImagekitResponseFaker.Generate(); - var httpResponse = new HttpResponseMessage - { - StatusCode = HttpStatusCode.OK, - Content = new StringContent(JsonConvert.SerializeObject(responseObj)) - }; - var httpClient = TestHelpers.GetTestHttpClient(httpResponse); - var restClient = new RestClient(GOOD_PUBLICKEY, GOOD_URLENDPOINT, httpClient); - - var response = restClient.ManageTagsAsync(tagsRequest, "addTags").Result; - var responseObj1 = JsonConvert.SerializeObject(responseObj); - Assert.Equal(responseObj1, response.Raw); - } - - [Fact] - public void Remove_Tags_Object_Exception() - { - TagsRequest ob = null; - var responseObj = TestHelpers.ImagekitResponseFaker.Generate(); - - var httpResponse = new HttpResponseMessage - { - StatusCode = HttpStatusCode.OK, - Content = new StringContent(JsonConvert.SerializeObject(responseObj)) - }; - var httpClient = TestHelpers.GetTestHttpClient(httpResponse); - var restClient = new RestClient(GOOD_PUBLICKEY, GOOD_URLENDPOINT, httpClient); - var ex = Assert.ThrowsAsync(async () => await restClient.ManageTagsAsync(ob, "")); - Assert.Equal(ErrorMessages.InvalidTagValue, ex.Result.Message); - } - [Fact] - public void Missing_Remove_Tags_Null_Exception() - { - TagsRequest ob = new TagsRequest - { - tags = null, - fileIds = new List { "abc" } - }; - var responseObj = TestHelpers.ImagekitResponseFaker.Generate(); - - var httpResponse = new HttpResponseMessage - { - StatusCode = HttpStatusCode.OK, - Content = new StringContent(JsonConvert.SerializeObject(responseObj)) - }; - var httpClient = TestHelpers.GetTestHttpClient(httpResponse); - var restClient = new RestClient(GOOD_PUBLICKEY, GOOD_URLENDPOINT, httpClient); - var ex = Assert.ThrowsAsync(async () => await restClient.ManageTagsAsync(ob, "")); - Assert.Equal(ErrorMessages.InvalidTagParamValue, ex.Result.Message); - } - - - [Fact] - public void Remove_AITags_Null_Exception() - { - AITagsRequest ob = null; - var responseObj = TestHelpers.ImagekitResponseFaker.Generate(); - - var httpResponse = new HttpResponseMessage - { - StatusCode = HttpStatusCode.OK, - Content = new StringContent(JsonConvert.SerializeObject(responseObj)) - }; - var httpClient = TestHelpers.GetTestHttpClient(httpResponse); - var restClient = new RestClient(GOOD_PUBLICKEY, GOOD_URLENDPOINT, httpClient); - var ex = Assert.ThrowsAsync(async () => await restClient.RemoveAITagsAsync(ob)); - Assert.Equal(ErrorMessages.InvalidTagValue, ex.Result.Message); - } - [Fact] - public void Missing_AI_Tags_Null_Exception() - { - AITagsRequest ob = new AITagsRequest - { - AITags = null, - fileIds = new List { "abc" } - }; - var responseObj = TestHelpers.ImagekitResponseFaker.Generate(); - - var httpResponse = new HttpResponseMessage - { - StatusCode = HttpStatusCode.OK, - Content = new StringContent(JsonConvert.SerializeObject(responseObj)) - }; - var httpClient = TestHelpers.GetTestHttpClient(httpResponse); - var restClient = new RestClient(GOOD_PUBLICKEY, GOOD_URLENDPOINT, httpClient); - var ex = Assert.ThrowsAsync(async () => await restClient.RemoveAITagsAsync(ob)); - Assert.Equal(ErrorMessages.InvalidTagParamValue, ex.Result.Message); - } - - [Fact] - public void Missing_AI_Filed_Null_Exception() - { - AITagsRequest ob = new AITagsRequest - { - AITags = new List { "abc" }, - fileIds = null - }; - - var responseObj = TestHelpers.ImagekitResponseFaker.Generate(); - - var httpResponse = new HttpResponseMessage - { - StatusCode = HttpStatusCode.OK, - Content = new StringContent(JsonConvert.SerializeObject(responseObj)) - }; - var httpClient = TestHelpers.GetTestHttpClient(httpResponse); - var restClient = new RestClient(GOOD_PUBLICKEY, GOOD_URLENDPOINT, httpClient); - var ex = Assert.ThrowsAsync(async () => await restClient.RemoveAITagsAsync(ob)); - Assert.Equal(ErrorMessages.InvalidFiledParamValue, ex.Result.Message); - } - - } -} - - - - diff --git a/Imagekit.UnitTests/Tags/ManageTagsTestNonAsync.cs b/Imagekit.UnitTests/Tags/ManageTagsTestNonAsync.cs deleted file mode 100644 index fca2fdea..00000000 --- a/Imagekit.UnitTests/Tags/ManageTagsTestNonAsync.cs +++ /dev/null @@ -1,240 +0,0 @@ -using Imagekit.Constant; -using Newtonsoft.Json; -using System; -using System.Collections.Generic; -using System.Net; -using System.Net.Http; -using Xunit; - -namespace Imagekit.UnitTests.Tags -{ - - public class ManageTagsTestNonAsync - { - private const string GOOD_PUBLICKEY = "abc"; - private const string GOOD_URLENDPOINT = "https://dasdsad.dad.io/"; - - - [Fact] - public void AddTags_DefaultNonAsync() - { - TagsRequest tagsRequest = new TagsRequest - { - tags = new List - { - "abc", - "abc" - }, - fileIds = new List - { - "abc" - } - }; - - var responseObj = TestHelpers.ImagekitResponseFaker.Generate(); - var httpResponse = new HttpResponseMessage - { - StatusCode = HttpStatusCode.OK, - Content = new StringContent(JsonConvert.SerializeObject(responseObj)) - }; - var httpClient = TestHelpers.GetTestHttpClient(httpResponse); - var restClient = new RestClient(GOOD_PUBLICKEY, GOOD_URLENDPOINT, httpClient); - - var response = restClient.ManageTags(tagsRequest, "addTags"); - var responseObj1 = JsonConvert.SerializeObject(responseObj); - Assert.Equal(responseObj1, response.Raw); - } - - [Fact] - public void AddTags_Null_ExceptionNonAsync() - { - TagsRequest ob = null; - var responseObj = TestHelpers.ImagekitResponseFaker.Generate(); - - var httpResponse = new HttpResponseMessage - { - StatusCode = HttpStatusCode.OK, - Content = new StringContent(JsonConvert.SerializeObject(responseObj)) - }; - var httpClient = TestHelpers.GetTestHttpClient(httpResponse); - var restClient = new RestClient(GOOD_PUBLICKEY, GOOD_URLENDPOINT, httpClient); - var ex = Assert.Throws(() => restClient.ManageTags(ob, "")); - Assert.Equal(ErrorMessages.InvalidTagValue, ex.Message); - } - [Fact] - public void Missing_Tags_Null_ExceptionNonAsync() - { - TagsRequest ob = new TagsRequest - { - tags = null, - fileIds = new List { "abc" } - }; - var responseObj = TestHelpers.ImagekitResponseFaker.Generate(); - - var httpResponse = new HttpResponseMessage - { - StatusCode = HttpStatusCode.OK, - Content = new StringContent(JsonConvert.SerializeObject(responseObj)) - }; - var httpClient = TestHelpers.GetTestHttpClient(httpResponse); - var restClient = new RestClient(GOOD_PUBLICKEY, GOOD_URLENDPOINT, httpClient); - var ex = Assert.Throws(() => restClient.ManageTags(ob, "")); - Assert.Equal(ErrorMessages.InvalidTagParamValue, ex.Message); - } - - [Fact] - public void Missing_Filed_Null_ExceptionNonAsync() - { - TagsRequest ob = new TagsRequest - { - tags = new List { "abc" }, - fileIds = null - }; - - var responseObj = TestHelpers.ImagekitResponseFaker.Generate(); - - var httpResponse = new HttpResponseMessage - { - StatusCode = HttpStatusCode.OK, - Content = new StringContent(JsonConvert.SerializeObject(responseObj)) - }; - var httpClient = TestHelpers.GetTestHttpClient(httpResponse); - var restClient = new RestClient(GOOD_PUBLICKEY, GOOD_URLENDPOINT, httpClient); - var ex = Assert.Throws(() => restClient.ManageTags(ob, "")); - Assert.Equal(ErrorMessages.InvalidFiledParamValue, ex.Message); - } - - - [Fact] - public void RemoveTags_DefaultNonAsync() - { - TagsRequest tagsRequest = new TagsRequest - { - tags = new List - { - "abc", - "abc" - }, - fileIds = new List - { - "abc" - } - }; - - var responseObj = TestHelpers.ImagekitResponseFaker.Generate(); - var httpResponse = new HttpResponseMessage - { - StatusCode = HttpStatusCode.OK, - Content = new StringContent(JsonConvert.SerializeObject(responseObj)) - }; - var httpClient = TestHelpers.GetTestHttpClient(httpResponse); - var restClient = new RestClient(GOOD_PUBLICKEY, GOOD_URLENDPOINT, httpClient); - - var response = restClient.ManageTags(tagsRequest, "removeTags"); - var responseObj1 = JsonConvert.SerializeObject(responseObj); - Assert.Equal(responseObj1, response.Raw); - } - - [Fact] - public void Remove_Tags_Object_ExceptionNonAsync() - { - TagsRequest ob = null; - var responseObj = TestHelpers.ImagekitResponseFaker.Generate(); - - var httpResponse = new HttpResponseMessage - { - StatusCode = HttpStatusCode.OK, - Content = new StringContent(JsonConvert.SerializeObject(responseObj)) - }; - var httpClient = TestHelpers.GetTestHttpClient(httpResponse); - var restClient = new RestClient(GOOD_PUBLICKEY, GOOD_URLENDPOINT, httpClient); - var ex = Assert.Throws(() => restClient.ManageTags(ob, "")); - Assert.Equal(ErrorMessages.InvalidTagValue, ex.Message); - } - [Fact] - public void Missing_Remove_Tags_Null_ExceptionNonAsync() - { - TagsRequest ob = new TagsRequest - { - tags = null, - fileIds = new List { "abc" } - }; - var responseObj = TestHelpers.ImagekitResponseFaker.Generate(); - - var httpResponse = new HttpResponseMessage - { - StatusCode = HttpStatusCode.OK, - Content = new StringContent(JsonConvert.SerializeObject(responseObj)) - }; - var httpClient = TestHelpers.GetTestHttpClient(httpResponse); - var restClient = new RestClient(GOOD_PUBLICKEY, GOOD_URLENDPOINT, httpClient); - var ex = Assert.Throws(() => restClient.ManageTags(ob, "")); - Assert.Equal(ErrorMessages.InvalidTagParamValue, ex.Message); - } - - - [Fact] - public void Remove_AITags_Null_ExceptionNonAsync() - { - AITagsRequest ob = null; - var responseObj = TestHelpers.ImagekitResponseFaker.Generate(); - - var httpResponse = new HttpResponseMessage - { - StatusCode = HttpStatusCode.OK, - Content = new StringContent(JsonConvert.SerializeObject(responseObj)) - }; - var httpClient = TestHelpers.GetTestHttpClient(httpResponse); - var restClient = new RestClient(GOOD_PUBLICKEY, GOOD_URLENDPOINT, httpClient); - var ex = Assert.Throws(() => restClient.RemoveAITags(ob)); - Assert.Equal(ErrorMessages.InvalidTagValue, ex.Message); - } - [Fact] - public void Missing_AI_Tags_Null_ExceptionNonAsync() - { - AITagsRequest ob = new AITagsRequest - { - AITags = null, - fileIds = new List { "abc" } - }; - var responseObj = TestHelpers.ImagekitResponseFaker.Generate(); - - var httpResponse = new HttpResponseMessage - { - StatusCode = HttpStatusCode.OK, - Content = new StringContent(JsonConvert.SerializeObject(responseObj)) - }; - var httpClient = TestHelpers.GetTestHttpClient(httpResponse); - var restClient = new RestClient(GOOD_PUBLICKEY, GOOD_URLENDPOINT, httpClient); - var ex = Assert.Throws(() => restClient.RemoveAITags(ob)); - Assert.Equal(ErrorMessages.InvalidTagParamValue, ex.Message); - } - - [Fact] - public void Missing_AI_Filed_Null_ExceptionNonAsync() - { - AITagsRequest ob = new AITagsRequest - { - AITags = new List { "abc" }, - fileIds = null - }; - - var responseObj = TestHelpers.ImagekitResponseFaker.Generate(); - - var httpResponse = new HttpResponseMessage - { - StatusCode = HttpStatusCode.OK, - Content = new StringContent(JsonConvert.SerializeObject(responseObj)) - }; - var httpClient = TestHelpers.GetTestHttpClient(httpResponse); - var restClient = new RestClient(GOOD_PUBLICKEY, GOOD_URLENDPOINT, httpClient); - var ex = Assert.Throws(() => restClient.RemoveAITags(ob)); - Assert.Equal(ErrorMessages.InvalidFiledParamValue, ex.Message); - } - - } -} - - - - diff --git a/Imagekit.UnitTests/TestHelpers.cs b/Imagekit.UnitTests/TestHelpers.cs deleted file mode 100644 index 8a7aef75..00000000 --- a/Imagekit.UnitTests/TestHelpers.cs +++ /dev/null @@ -1,85 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq.Expressions; -using System.Net.Http; -using System.Threading; -using System.Threading.Tasks; -using Bogus; -using Moq; -using Moq.Protected; -using Newtonsoft.Json; -using Newtonsoft.Json.Linq; -using Xunit; - -namespace Imagekit.UnitTests -{ - public static class TestHelpers - { - static TestHelpers() - { - Faker.DefaultStrictMode = true; - } - - public static Faker ImagekitResponseFaker = new Faker() - .RuleFor(u => u.Raw, (f, u) => f.Random.Utf16String()) - .RuleFor(u => u.HttpStatusCode, (f, u) => 200); - - /// - /// Get a test http client that response to the specified request. - /// - /// An expression that matches the sent in the request. - /// The response to return from the request. - /// The function to call with the sent in the request. - /// - public static HttpClient GetTestHttpClient(Expression requestMatcher, HttpResponseMessage response, Action callback) - { - var handlerMock = new Mock(MockBehavior.Strict); - handlerMock - .Protected() - // Setup the PROTECTED method to mock - .Setup>( - "SendAsync", - requestMatcher, - ItExpr.IsAny() - ) - .Callback((msg, ct) => callback?.Invoke(msg)) - // prepare the expected response of the mocked http call - .ReturnsAsync(response) - .Verifiable(); - - // use real http client with mocked handler here - var httpClient = new HttpClient(handlerMock.Object); - return httpClient; - } - - - /// - /// Get a test http client that response to the specified request. - /// - /// The response to return from the request. - /// The function to call with the sent in the request. - /// - public static HttpClient GetTestHttpClient(HttpResponseMessage response) - { - return GetTestHttpClient(ItExpr.IsAny(), response, null); - } - - - public static Action GetUpdateFileDetailsMessageValidator( - string[] expectedTags, - string expectedCustomCoordinates - ) - { - return async (msg) => - { - var content = await msg.Content.ReadAsStringAsync(); - dynamic jobj = JObject.Parse(content); - string[] actualTags = jobj.tags == null ? null : JsonConvert.DeserializeObject(jobj.tags.ToString()); - string coords = jobj.customCoordinates; - Assert.Equal(expectedTags, actualTags); - Assert.Equal(expectedCustomCoordinates, coords); - }; - } - - } -} diff --git a/Imagekit.UnitTests/Upload/UploadTestCasesAsync.cs b/Imagekit.UnitTests/Upload/UploadTestCasesAsync.cs deleted file mode 100644 index 2a249062..00000000 --- a/Imagekit.UnitTests/Upload/UploadTestCasesAsync.cs +++ /dev/null @@ -1,431 +0,0 @@ -using Imagekit.Constant; -using Newtonsoft.Json; -using System; -using System.Collections.Generic; -using System.Net; -using System.Net.Http; -using Xunit; -using Imagekit.Models; -using System.Collections; - -namespace Imagekit.UnitTests.Upload -{ - - public class UploadTestCasesAsync - { - private const string GOOD_PUBLICKEY = "abc"; - private const string GOOD_URLENDPOINT = "https://dasdsad.dad.io/"; - - - [Fact] - public void Upload_InvalidObject_Exception() - { - - FileCreateRequest ob = null; - var responseObj = TestHelpers.ImagekitResponseFaker.Generate(); - - var httpResponse = new HttpResponseMessage - { - StatusCode = HttpStatusCode.OK, - Content = new StringContent(JsonConvert.SerializeObject(responseObj)) - }; - var httpClient = TestHelpers.GetTestHttpClient(httpResponse); - var restClient = new RestClient(GOOD_PUBLICKEY, GOOD_URLENDPOINT, httpClient); - var ex = Assert.ThrowsAsync(async () => await restClient.UploadAsync(ob)); - Assert.Equal(ErrorMessages.InvalidFileUploadObjValue, ex.Result.Message); - } - [Fact] - public void Upload_InvalidFileName_Exception() - { - FileCreateRequest ob = new FileCreateRequest - { - fileName = string.Empty - }; - var responseObj = TestHelpers.ImagekitResponseFaker.Generate(); - - var httpResponse = new HttpResponseMessage - { - StatusCode = HttpStatusCode.OK, - Content = new StringContent(JsonConvert.SerializeObject(responseObj)) - }; - var httpClient = TestHelpers.GetTestHttpClient(httpResponse); - var restClient = new RestClient(GOOD_PUBLICKEY, GOOD_URLENDPOINT, httpClient); - var ex = Assert.ThrowsAsync(async () => await restClient.UploadAsync(ob)); - Assert.Equal(ErrorMessages.MissingUploadFilenameParameter, ex.Result.Message); - } - [Fact] - public void Upload_InvalidFileParam_Exception() - { - - FileCreateRequest ob = new FileCreateRequest - { - file = null, - fileName = Guid.NewGuid().ToString() - }; - var responseObj = TestHelpers.ImagekitResponseFaker.Generate(); - - var httpResponse = new HttpResponseMessage - { - StatusCode = HttpStatusCode.OK, - Content = new StringContent(JsonConvert.SerializeObject(responseObj)) - }; - var httpClient = TestHelpers.GetTestHttpClient(httpResponse); - var restClient = new RestClient(GOOD_PUBLICKEY, GOOD_URLENDPOINT, httpClient); - var ex = Assert.ThrowsAsync(async () => await restClient.UploadAsync(ob)); - Assert.Equal(ErrorMessages.InvalidFileValue, ex.Result.Message); - } - - [Fact] - public void UploadFileByURI_Default() - { - FileCreateRequest ob = new FileCreateRequest - { - file = "http://www.google.com/images/logos/ps_logo2.png", - fileName = Guid.NewGuid().ToString() - }; - - var responseObj = TestHelpers.ImagekitResponseFaker.Generate(); - var httpResponse = new HttpResponseMessage - { - StatusCode = HttpStatusCode.OK, - Content = new StringContent(JsonConvert.SerializeObject(responseObj)) - }; - var httpClient = TestHelpers.GetTestHttpClient(httpResponse); - - var restClient = new RestClient(GOOD_PUBLICKEY, GOOD_URLENDPOINT, httpClient); - var response = (Result)restClient.Upload(ob); - var responseObj1 = JsonConvert.SerializeObject(responseObj); - Assert.Equal(responseObj1, response.Raw); - } - - [Fact] - public void UploadFileByBytes_Default() - { - - string base64 = "iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAYAAACNbyblAAAAHElEQVQI12P4//8/w38GIAXDIBKE0DHxgljNBAAO9TXL0Y4OHwAAAABJRU5ErkJggg=="; - byte[] bytes = Convert.FromBase64String(base64); - - FileCreateRequest ob = new FileCreateRequest - { - file = bytes, - fileName = Guid.NewGuid().ToString() - }; - var responseObj = TestHelpers.ImagekitResponseFaker.Generate(); - var httpResponse = new HttpResponseMessage - { - StatusCode = HttpStatusCode.OK, - Content = new StringContent(JsonConvert.SerializeObject(responseObj)) - }; - var httpClient = TestHelpers.GetTestHttpClient(httpResponse); - - - var restClient = new RestClient(GOOD_PUBLICKEY, GOOD_URLENDPOINT, httpClient); - - var response = (Result)restClient.UploadAsync(ob).Result; - var responseObj1 = JsonConvert.SerializeObject(responseObj); - Assert.Equal(responseObj1, response.Raw); - } - - [Fact] - public void UploadFileByBase64_Default() - { - string base64 = "iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAYAAACNbyblAAAAHElEQVQI12P4//8/w38GIAXDIBKE0DHxgljNBAAO9TXL0Y4OHwAAAABJRU5ErkJggg=="; - FileCreateRequest ob = new FileCreateRequest - { - file = base64, - fileName = Guid.NewGuid().ToString() - }; - var responseObj = TestHelpers.ImagekitResponseFaker.Generate(); - var httpResponse = new HttpResponseMessage - { - StatusCode = HttpStatusCode.OK, - Content = new StringContent(JsonConvert.SerializeObject(responseObj)) - }; - var httpClient = TestHelpers.GetTestHttpClient(httpResponse); - - - var restClient = new RestClient(GOOD_PUBLICKEY, GOOD_URLENDPOINT, httpClient); - - var response = (Result)restClient.UploadAsync(ob).Result; - var responseObj1 = JsonConvert.SerializeObject(responseObj); - Assert.Equal(responseObj1, response.Raw); - } - [Fact] - public void UploadFile_Default() - { - string base64 = "iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAYAAACNbyblAAAAHElEQVQI12P4//8/w38GIAXDIBKE0DHxgljNBAAO9TXL0Y4OHwAAAABJRU5ErkJggg=="; - FileCreateRequest ob = new FileCreateRequest - { - file = base64, - fileName = Guid.NewGuid().ToString() - }; - List tags = new List - { - "Software", - "Developer", - "Engineer" - }; - ob.tags = tags; - - string customCoordinates = "10,10,20,20"; - ob.customCoordinates = customCoordinates; - List responseFields = new List - { - "isPrivateFile", - "tags", - "customCoordinates" - }; - - ob.responseFields = responseFields; - List model1 = new List(); - BackGroundImage bck = new BackGroundImage - { - name = "remove-bg", - options = new options() { add_shadow = true, bg_color = "green" } - }; - TransformationObject transformationObject = new TransformationObject - { - value = "w-100" - }; - List postTransformations = new List(); - postTransformations.Add(transformationObject); - UploadTransformation uploadTransformation = new UploadTransformation - { - pre = "l-text,i-Imagekit,fs-50,l-end", - post = postTransformations, - }; - model1.Add(bck); - ob.webhookUrl = "https://webhook.site/c78d617f-33bc-40d9-9e61-608999721e2e"; - ob.useUniqueFileName = true; - ob.folder = "dummy-folder"; - ob.isPrivateFile = false; - ob.overwriteFile = true; - ob.overwriteAITags = true; - ob.overwriteTags = true; - ob.overwriteCustomMetadata = true; - ob.transformation = uploadTransformation; - ob.checks = "'request.folder' : '/dummy-folder'"; - ob.isPublished = true; - Hashtable model = new Hashtable - { - { "price", 2000 } - }; - ob.customMetadata = model; - var responseObj = TestHelpers.ImagekitResponseFaker.Generate(); - var httpResponse = new HttpResponseMessage - { - StatusCode = HttpStatusCode.OK, - Content = new StringContent(JsonConvert.SerializeObject(responseObj)) - }; - var httpClient = TestHelpers.GetTestHttpClient(httpResponse); - - var restClient = new RestClient(GOOD_PUBLICKEY, GOOD_URLENDPOINT, httpClient); - - var response = (Result)restClient.UploadAsync(ob).Result; - var responseObj1 = JsonConvert.SerializeObject(responseObj); - Assert.Equal(responseObj1, response.Raw); - } - - [Fact] - public void UploadFile_Null_List() - { - string base64 = "iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAYAAACNbyblAAAAHElEQVQI12P4//8/w38GIAXDIBKE0DHxgljNBAAO9TXL0Y4OHwAAAABJRU5ErkJggg=="; - FileCreateRequest ob = new FileCreateRequest - { - file = base64, - fileName = Guid.NewGuid().ToString() - }; - List tags = null; - ob.tags = tags; - ob.folder = "demo1"; - string customCoordinates = "10,10,20,20"; - ob.customCoordinates = customCoordinates; - List responseFields = null; - ob.responseFields = responseFields; - List model1 = new List(); - BackGroundImage bck = new BackGroundImage - { - name = "remove-bg", - options = new options() { add_shadow = true, bg_color = "green", bg_image_url = "http://www.google.com/images/logos/ps_logo2.png" } - }; - model1.Add(bck); - ob.webhookUrl = "https://webhook.site/c78d617f-33bc-40d9-9e61-608999721e2e"; - ob.useUniqueFileName = false; - ob.isPrivateFile = false; - ob.overwriteFile = false; - ob.overwriteAITags = false; - ob.overwriteTags = false; - ob.overwriteCustomMetadata = true; - Hashtable model = new Hashtable - { - { "price", 2000 } - }; - ob.customMetadata = model; - - - - var responseObj = TestHelpers.ImagekitResponseFaker.Generate(); - var httpResponse = new HttpResponseMessage - { - StatusCode = HttpStatusCode.OK, - Content = new StringContent(JsonConvert.SerializeObject(responseObj)) - }; - var httpClient = TestHelpers.GetTestHttpClient(httpResponse); - - - var restClient = new RestClient(GOOD_PUBLICKEY, GOOD_URLENDPOINT, httpClient); - - var response = (Result)restClient.UploadAsync(ob).Result; - var responseObj1 = JsonConvert.SerializeObject(responseObj); - Assert.Equal(responseObj1, response.Raw); - } - - - [Fact] - public void UploadFile_Null_Object_List() - { - string base64 = "iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAYAAACNbyblAAAAHElEQVQI12P4//8/w38GIAXDIBKE0DHxgljNBAAO9TXL0Y4OHwAAAABJRU5ErkJggg=="; - FileCreateRequest ob = new FileCreateRequest - { - file = base64, - fileName = Guid.NewGuid().ToString() - }; - List tags = null; - ob.tags = tags; - ob.folder = "demo1"; - string customCoordinates = "10,10,20,20"; - ob.customCoordinates = customCoordinates; - List responseFields = null; - ob.responseFields = responseFields; - Hashtable model = new Hashtable - { - { "price", 2000 } - }; - ob.customMetadata = model; - var responseObj = TestHelpers.ImagekitResponseFaker.Generate(); - var httpResponse = new HttpResponseMessage - { - StatusCode = HttpStatusCode.OK, - Content = new StringContent(JsonConvert.SerializeObject(responseObj)) - }; - var httpClient = TestHelpers.GetTestHttpClient(httpResponse); - - - var restClient = new RestClient(GOOD_PUBLICKEY, GOOD_URLENDPOINT, httpClient); - - var response = (Result)restClient.UploadAsync(ob).Result; - var responseObj1 = JsonConvert.SerializeObject(responseObj); - Assert.Equal(responseObj1, response.Raw); - } - - [Fact] - public void UpdateFile_Missing_File_Id() - { - FileUpdateRequest ob = new FileUpdateRequest - { - fileId = "", - - }; - - var responseObj = TestHelpers.ImagekitResponseFaker.Generate(); - var httpResponse = new HttpResponseMessage - { - StatusCode = HttpStatusCode.OK, - Content = new StringContent(JsonConvert.SerializeObject(responseObj)) - }; - var httpClient = TestHelpers.GetTestHttpClient(httpResponse); - - var restClient = new RestClient(GOOD_PUBLICKEY, GOOD_URLENDPOINT, httpClient); - - var ex = Assert.ThrowsAsync(async () => await restClient.UpdateFileDetailAsync(ob)); - Assert.Equal(ErrorMessages.FileIdMissing, ex.Result.Message); - } - - [Fact] - public void UpdateFile_Default() - { - FileUpdateRequest ob = new FileUpdateRequest - { - fileId = "file-Id", - - }; - List tags = new List - { - "Software", - "Developer", - "Engineer" - }; - ob.tags = tags; - - string customCoordinates = "10,10,20,20"; - ob.customCoordinates = customCoordinates; - List responseFields = new List - { - "isPrivateFile", - "tags", - "customCoordinates" - }; - List model1 = new List(); - BackGroundImage bck = new BackGroundImage - { - name = "remove-bg", - options = new options() { add_shadow = true, bg_color = "green", bg_image_url = "http://www.google.com/images/logos/ps_logo2.png" } - }; - model1.Add(bck); - ob.webhookUrl = "https://webhook.site/c78d617f-33bc-40d9-9e61-608999721e2e"; - Hashtable model = new Hashtable - { - { "price", 2000 } - }; - ob.customMetadata = model; - - var responseObj = TestHelpers.ImagekitResponseFaker.Generate(); - var httpResponse = new HttpResponseMessage - { - StatusCode = HttpStatusCode.OK, - Content = new StringContent(JsonConvert.SerializeObject(responseObj)) - }; - var httpClient = TestHelpers.GetTestHttpClient(httpResponse); - - var restClient = new RestClient(GOOD_PUBLICKEY, GOOD_URLENDPOINT, httpClient); - - var response = (Result)restClient.UpdateFileDetailAsync(ob).Result; - var responseObj1 = JsonConvert.SerializeObject(responseObj); - Assert.Equal(responseObj1, response.Raw); - } - - [Fact] - public void UpdateFile_Publish_Status() - { - FileUpdateRequest ob = new FileUpdateRequest - { - fileId = "file-Id", - - }; - PublishStatus publishStatus = new PublishStatus - { - isPublished = false - }; - ob.publish = publishStatus; - var responseObj = TestHelpers.ImagekitResponseFaker.Generate(); - var httpResponse = new HttpResponseMessage - { - StatusCode = HttpStatusCode.OK, - Content = new StringContent(JsonConvert.SerializeObject(responseObj)) - }; - var httpClient = TestHelpers.GetTestHttpClient(httpResponse); - - var restClient = new RestClient(GOOD_PUBLICKEY, GOOD_URLENDPOINT, httpClient); - - var response = (Result)restClient.UpdateFileDetailAsync(ob).Result; - var responseObj1 = JsonConvert.SerializeObject(responseObj); - Assert.Equal(responseObj1, response.Raw); - } - - - } -} - - - - diff --git a/Imagekit.UnitTests/Upload/UploadTestCasesNonAsync.cs b/Imagekit.UnitTests/Upload/UploadTestCasesNonAsync.cs deleted file mode 100644 index 4ed8340f..00000000 --- a/Imagekit.UnitTests/Upload/UploadTestCasesNonAsync.cs +++ /dev/null @@ -1,421 +0,0 @@ -using Imagekit.Constant; -using Newtonsoft.Json; -using System; -using System.Collections.Generic; -using System.Net; -using System.Net.Http; -using Xunit; -using Imagekit.Models; -using System.Collections; - -namespace Imagekit.UnitTests.Upload -{ - - public class UploadTestCasesNonAsync - { - private const string GOOD_PUBLICKEY = "abc"; - private const string GOOD_URLENDPOINT = "https://dasdsad.dad.io/"; - - - [Fact] - public void Upload_InvalidObject_ExceptionNonAsync() - { - - FileCreateRequest ob = null; - var responseObj = TestHelpers.ImagekitResponseFaker.Generate(); - - var httpResponse = new HttpResponseMessage - { - StatusCode = HttpStatusCode.OK, - Content = new StringContent(JsonConvert.SerializeObject(responseObj)) - }; - var httpClient = TestHelpers.GetTestHttpClient(httpResponse); - var restClient = new RestClient(GOOD_PUBLICKEY, GOOD_URLENDPOINT, httpClient); - var ex = Assert.Throws(() => restClient.Upload(ob)); - Assert.Equal(ErrorMessages.InvalidFileUploadObjValue, ex.Message); - } - [Fact] - public void Upload_InvalidFileName_ExceptionNonAsync() - { - FileCreateRequest ob = new FileCreateRequest - { - fileName = string.Empty - }; - var responseObj = TestHelpers.ImagekitResponseFaker.Generate(); - - var httpResponse = new HttpResponseMessage - { - StatusCode = HttpStatusCode.OK, - Content = new StringContent(JsonConvert.SerializeObject(responseObj)) - }; - var httpClient = TestHelpers.GetTestHttpClient(httpResponse); - var restClient = new RestClient(GOOD_PUBLICKEY, GOOD_URLENDPOINT, httpClient); - var ex = Assert.Throws(() => restClient.Upload(ob)); - Assert.Equal(ErrorMessages.MissingUploadFilenameParameter, ex.Message); - } - [Fact] - public void Upload_InvalidFileParam_ExceptionNonAsync() - { - - FileCreateRequest ob = new FileCreateRequest - { - file = null, - fileName = Guid.NewGuid().ToString() - }; - var responseObj = TestHelpers.ImagekitResponseFaker.Generate(); - - var httpResponse = new HttpResponseMessage - { - StatusCode = HttpStatusCode.OK, - Content = new StringContent(JsonConvert.SerializeObject(responseObj)) - }; - var httpClient = TestHelpers.GetTestHttpClient(httpResponse); - var restClient = new RestClient(GOOD_PUBLICKEY, GOOD_URLENDPOINT, httpClient); - var ex = Assert.Throws(() => restClient.Upload(ob)); - Assert.Equal(ErrorMessages.InvalidFileValue, ex.Message); - } - - [Fact] - public void UploadFileByURI_DefaultNonAsync() - { - FileCreateRequest ob = new FileCreateRequest - { - file = "http://www.google.com/images/logos/ps_logo2.png", - fileName = Guid.NewGuid().ToString() - }; - - var responseObj = TestHelpers.ImagekitResponseFaker.Generate(); - var httpResponse = new HttpResponseMessage - { - StatusCode = HttpStatusCode.OK, - Content = new StringContent(JsonConvert.SerializeObject(responseObj)) - }; - var httpClient = TestHelpers.GetTestHttpClient(httpResponse); - - var restClient = new RestClient(GOOD_PUBLICKEY, GOOD_URLENDPOINT, httpClient); - var response = (Result)restClient.Upload(ob); - var responseObj1 = JsonConvert.SerializeObject(responseObj); - Assert.Equal(responseObj1, response.Raw); - } - - [Fact] - public void UploadFileByBytes_DefaultNonAsync() - { - - string base64 = "iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAYAAACNbyblAAAAHElEQVQI12P4//8/w38GIAXDIBKE0DHxgljNBAAO9TXL0Y4OHwAAAABJRU5ErkJggg=="; - byte[] bytes = Convert.FromBase64String(base64); - - FileCreateRequest ob = new FileCreateRequest - { - file = bytes, - fileName = Guid.NewGuid().ToString() - }; - var responseObj = TestHelpers.ImagekitResponseFaker.Generate(); - var httpResponse = new HttpResponseMessage - { - StatusCode = HttpStatusCode.OK, - Content = new StringContent(JsonConvert.SerializeObject(responseObj)) - }; - var httpClient = TestHelpers.GetTestHttpClient(httpResponse); - - - var restClient = new RestClient(GOOD_PUBLICKEY, GOOD_URLENDPOINT, httpClient); - - var response = (Result)restClient.Upload(ob); - var responseObj1 = JsonConvert.SerializeObject(responseObj); - Assert.Equal(responseObj1, response.Raw); - } - - [Fact] - public void UploadFileByBase64_DefaultNonAsync() - { - string base64 = "iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAYAAACNbyblAAAAHElEQVQI12P4//8/w38GIAXDIBKE0DHxgljNBAAO9TXL0Y4OHwAAAABJRU5ErkJggg=="; - FileCreateRequest ob = new FileCreateRequest - { - file = base64, - fileName = Guid.NewGuid().ToString() - }; - var responseObj = TestHelpers.ImagekitResponseFaker.Generate(); - var httpResponse = new HttpResponseMessage - { - StatusCode = HttpStatusCode.OK, - Content = new StringContent(JsonConvert.SerializeObject(responseObj)) - }; - var httpClient = TestHelpers.GetTestHttpClient(httpResponse); - - - var restClient = new RestClient(GOOD_PUBLICKEY, GOOD_URLENDPOINT, httpClient); - - var response = (Result)restClient.Upload(ob); - var responseObj1 = JsonConvert.SerializeObject(responseObj); - Assert.Equal(responseObj1, response.Raw); - } - [Fact] - public void UploadFile_DefaultNonAsync() - { - string base64 = "iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAYAAACNbyblAAAAHElEQVQI12P4//8/w38GIAXDIBKE0DHxgljNBAAO9TXL0Y4OHwAAAABJRU5ErkJggg=="; - FileCreateRequest ob = new FileCreateRequest - { - file = base64, - fileName = Guid.NewGuid().ToString() - }; - List tags = new List - { - "Software", - "Developer", - "Engineer" - }; - ob.tags = tags; - ob.folder = "demo1"; - string customCoordinates = "10,10,20,20"; - ob.customCoordinates = customCoordinates; - List responseFields = new List - { - "isPrivateFile", - "tags", - "customCoordinates" - }; - - ob.responseFields = responseFields; - - List model1 = new List(); - BackGroundImage bck = new BackGroundImage - { - name = "remove-bg", - options = new options() { add_shadow = true, bg_image_url = "http://www.google.com/images/logos/ps_logo2.png" } - }; - model1.Add(bck); - ob.extensions = model1; - ob.webhookUrl = "https://webhook.site/c78d617f-33bc-40d9-9e61-608999721e2e"; - ob.useUniqueFileName = false; - ob.isPrivateFile = false; - ob.overwriteFile = false; - ob.overwriteAITags = false; - ob.overwriteTags = false; - ob.overwriteCustomMetadata = true; - ob.checks = "'request.folder' : '/dummy-folder'"; - ob.isPublished = true; - Hashtable model = new Hashtable - { - { "price", 2000 } - }; - ob.customMetadata = model; - var responseObj = TestHelpers.ImagekitResponseFaker.Generate(); - var httpResponse = new HttpResponseMessage - { - StatusCode = HttpStatusCode.OK, - Content = new StringContent(JsonConvert.SerializeObject(responseObj)) - }; - var httpClient = TestHelpers.GetTestHttpClient(httpResponse); - - - var restClient = new RestClient(GOOD_PUBLICKEY, GOOD_URLENDPOINT, httpClient); - - var response = (Result)restClient.Upload(ob); - var responseObj1 = JsonConvert.SerializeObject(responseObj); - Assert.Equal(responseObj1, response.Raw); - } - - [Fact] - public void UploadFile_Null_List() - { - string base64 = "iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAYAAACNbyblAAAAHElEQVQI12P4//8/w38GIAXDIBKE0DHxgljNBAAO9TXL0Y4OHwAAAABJRU5ErkJggg=="; - FileCreateRequest ob = new FileCreateRequest - { - file = base64, - fileName = Guid.NewGuid().ToString() - }; - List tags = null; - ob.tags = tags; - ob.folder = "demo1"; - string customCoordinates = "10,10,20,20"; - ob.customCoordinates = customCoordinates; - List responseFields = null; - - ob.responseFields = responseFields; - List model1 = new List(); - BackGroundImage bck = new BackGroundImage - { - name = "remove-bg", - options = new options() { add_shadow = true, bg_image_url = "http://www.google.com/images/logos/ps_logo2.png" } - }; - model1.Add(bck); - ob.webhookUrl = "https://webhook.site/c78d617f-33bc-40d9-9e61-608999721e2e"; - ob.useUniqueFileName = false; - ob.isPrivateFile = false; - ob.overwriteFile = false; - ob.overwriteAITags = false; - ob.overwriteTags = false; - ob.overwriteCustomMetadata = true; - Hashtable model = new Hashtable - { - { "price", 2000 } - }; - ob.customMetadata = model; - - - - - var responseObj = TestHelpers.ImagekitResponseFaker.Generate(); - var httpResponse = new HttpResponseMessage - { - StatusCode = HttpStatusCode.OK, - Content = new StringContent(JsonConvert.SerializeObject(responseObj)) - }; - var httpClient = TestHelpers.GetTestHttpClient(httpResponse); - - - var restClient = new RestClient(GOOD_PUBLICKEY, GOOD_URLENDPOINT, httpClient); - - var response = (Result)restClient.Upload(ob); - var responseObj1 = JsonConvert.SerializeObject(responseObj); - Assert.Equal(responseObj1, response.Raw); - } - - - [Fact] - public void UploadFile_Null_Object_List() - { - string base64 = "iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAYAAACNbyblAAAAHElEQVQI12P4//8/w38GIAXDIBKE0DHxgljNBAAO9TXL0Y4OHwAAAABJRU5ErkJggg=="; - FileCreateRequest ob = new FileCreateRequest - { - file = base64, - fileName = Guid.NewGuid().ToString() - }; - List tags = null; - ob.tags = tags; - ob.folder = "demo1"; - string customCoordinates = "10,10,20,20"; - ob.customCoordinates = customCoordinates; - List responseFields = null; - ob.responseFields = responseFields; - Hashtable model = new Hashtable - { - { "price", 2000 } - }; - ob.customMetadata = model; - var responseObj = TestHelpers.ImagekitResponseFaker.Generate(); - var httpResponse = new HttpResponseMessage - { - StatusCode = HttpStatusCode.OK, - Content = new StringContent(JsonConvert.SerializeObject(responseObj)) - }; - var httpClient = TestHelpers.GetTestHttpClient(httpResponse); - - - var restClient = new RestClient(GOOD_PUBLICKEY, GOOD_URLENDPOINT, httpClient); - - var response = (Result)restClient.Upload(ob); - var responseObj1 = JsonConvert.SerializeObject(responseObj); - Assert.Equal(responseObj1, response.Raw); - } - [Fact] - public void UpdateFile_Missing_File_Id() - { - FileUpdateRequest ob = new FileUpdateRequest - { - fileId = "", - - }; - - var responseObj = TestHelpers.ImagekitResponseFaker.Generate(); - var httpResponse = new HttpResponseMessage - { - StatusCode = HttpStatusCode.OK, - Content = new StringContent(JsonConvert.SerializeObject(responseObj)) - }; - var httpClient = TestHelpers.GetTestHttpClient(httpResponse); - - var restClient = new RestClient(GOOD_PUBLICKEY, GOOD_URLENDPOINT, httpClient); - - var ex = Assert.ThrowsAsync(async () => await restClient.UpdateFileDetailAsync(ob)); - Assert.Equal(ErrorMessages.FileIdMissing, ex.Result.Message); - } - [Fact] - public void UpdateFile_Default() - { - FileUpdateRequest ob = new FileUpdateRequest - { - fileId = "file-Id", - - }; - List tags = new List - { - "Software", - "Developer", - "Engineer" - }; - ob.tags = tags; - - string customCoordinates = "10,10,20,20"; - ob.customCoordinates = customCoordinates; - List responseFields = new List - { - "isPrivateFile", - "tags", - "customCoordinates" - }; - List model1 = new List(); - BackGroundImage bck = new BackGroundImage - { - name = "remove-bg", - options = new options() { add_shadow = true, bg_color = "green" } - }; - model1.Add(bck); - ob.webhookUrl = "https://webhook.site/c78d617f-33bc-40d9-9e61-608999721e2e"; - Hashtable model = new Hashtable - { - { "price", 2000 } - }; - ob.customMetadata = model; - - var responseObj = TestHelpers.ImagekitResponseFaker.Generate(); - var httpResponse = new HttpResponseMessage - { - StatusCode = HttpStatusCode.OK, - Content = new StringContent(JsonConvert.SerializeObject(responseObj)) - }; - var httpClient = TestHelpers.GetTestHttpClient(httpResponse); - - var restClient = new RestClient(GOOD_PUBLICKEY, GOOD_URLENDPOINT, httpClient); - - var response = (Result)restClient.UpdateFileDetail(ob); - var responseObj1 = JsonConvert.SerializeObject(responseObj); - Assert.Equal(responseObj1, response.Raw); - } - - [Fact] - public void UpdateFile_Publish_Status() - { - FileUpdateRequest ob = new FileUpdateRequest - { - fileId = "file-Id", - - }; - PublishStatus publishStatus = new PublishStatus - { - isPublished = false - }; - ob.publish = publishStatus; - - var responseObj = TestHelpers.ImagekitResponseFaker.Generate(); - var httpResponse = new HttpResponseMessage - { - StatusCode = HttpStatusCode.OK, - Content = new StringContent(JsonConvert.SerializeObject(responseObj)) - }; - var httpClient = TestHelpers.GetTestHttpClient(httpResponse); - - var restClient = new RestClient(GOOD_PUBLICKEY, GOOD_URLENDPOINT, httpClient); - - var response = (Result)restClient.UpdateFileDetail(ob); - var responseObj1 = JsonConvert.SerializeObject(responseObj); - Assert.Equal(responseObj1, response.Raw); - } - - } -} - - - - diff --git a/Imagekit.crdata b/Imagekit.crdata deleted file mode 100644 index bb1963a8..00000000 --- a/Imagekit.crdata +++ /dev/null @@ -1,19 +0,0 @@ - - - - - - - - - AAEAAAD/////AQAAAAAAAAAMAgAAAFxTdWJNYWluLkNvZGVJdFJpZ2h0LlNkaywgVmVyc2lvbj0xLjEuMzYuMjAsIEN1bHR1cmU9bmV1dHJhbCwgUHVibGljS2V5VG9rZW49MTNmODc4MmMwYzg4YjUxMAwDAAAAYFN1Yk1haW4uQ29kZUl0UmlnaHQuU2RrLkNvcmUsIFZlcnNpb249MS4xLjIyLjAsIEN1bHR1cmU9bmV1dHJhbCwgUHVibGljS2V5VG9rZW49NzliYzBkYjk3NDBhNWYwNAwEAAAAZlN1Yk1haW4uQ29kZUl0UmlnaHQuQ29kZU9iamVjdE1vZGVsLCBWZXJzaW9uPTIuMi4wLjAsIEN1bHR1cmU9bmV1dHJhbCwgUHVibGljS2V5VG9rZW49YmE5NjRiYzlhZGYxZTE4OQUBAAAALFN1Yk1haW4uQ29kZUl0UmlnaHQuU2RrLlJlZmxlY3Rpb24uQ2xhc3NJbmZvCAAAAAVfbmFtZQpfY2xhc3NUeXBlB19wYXJlbnQOX25hbWVzcGFjZUluZm8OX2Nhc2VTZW5zaXRpdmUKX21vZGlmaWVycwxfcHJvamVjdE5hbWUNX3Byb2plY3RGaWxlcwEEBAQABAEENVN1Yk1haW4uQ29kZUl0UmlnaHQuU2RrLkNvcmUuUmVmbGVjdGlvbi5DbGFzc0luZm9UeXBlAwAAADFTdWJNYWluLkNvZGVJdFJpZ2h0LlNkay5Db3JlLlJlZmxlY3Rpb24uSVR5cGVJbmZvAwAAADBTdWJNYWluLkNvZGVJdFJpZ2h0LlNkay5SZWZsZWN0aW9uLk5hbWVzcGFjZUluZm8CAAAAATJTdWJNYWluLkNvZGVPYmplY3RNb2RlbC5SZWZsZWN0aW9uLk1lbWJlck1vZGlmaWVycwQAAAA6U3ViTWFpbi5Db2RlSXRSaWdodC5TZGsuQ29yZS5SZWZsZWN0aW9uLklQcm9qZWN0RmlsZUluZm9bXQMAAAACAAAABgUAAAAHUHJvZ3JhbQX6////NVN1Yk1haW4uQ29kZUl0UmlnaHQuU2RrLkNvcmUuUmVmbGVjdGlvbi5DbGFzc0luZm9UeXBlAQAAAAd2YWx1ZV9fAAgDAAAAAAAAAAoJBwAAAAEF+P///zJTdWJNYWluLkNvZGVPYmplY3RNb2RlbC5SZWZsZWN0aW9uLk1lbWJlck1vZGlmaWVycwEAAAAHdmFsdWVfXwAIBAAAAAgAAAAGCQAAAAtDb25zb2xlQXBwMQkKAAAABQcAAAAwU3ViTWFpbi5Db2RlSXRSaWdodC5TZGsuUmVmbGVjdGlvbi5OYW1lc3BhY2VJbmZvAgAAABNfZnVsbHlRdWFsaWZpZWROYW1lCV9wcm9qZWN0cwEENlN1Yk1haW4uQ29kZUl0UmlnaHQuU2RrLkNvcmUuUmVmbGVjdGlvbi5JUHJvamVjdEluZm9bXQMAAAACAAAABgsAAAALQ29uc29sZUFwcDEJDAAAAAcKAAAAAAEAAAABAAAABDhTdWJNYWluLkNvZGVJdFJpZ2h0LlNkay5Db3JlLlJlZmxlY3Rpb24uSVByb2plY3RGaWxlSW5mbwMAAAAJDQAAAAcMAAAAAAEAAAABAAAABDRTdWJNYWluLkNvZGVJdFJpZ2h0LlNkay5Db3JlLlJlZmxlY3Rpb24uSVByb2plY3RJbmZvAwAAAAkOAAAABQ0AAAAyU3ViTWFpbi5Db2RlSXRSaWdodC5TZGsuUmVmbGVjdGlvbi5Qcm9qZWN0RmlsZUluZm8CAAAADF9wcm9qZWN0TmFtZRFfcmVsYXRpdmVGaWxlTmFtZQEBAgAAAAkJAAAABhAAAAAMLlxQcm9ncmFtLmNzBQ4AAAAuU3ViTWFpbi5Db2RlSXRSaWdodC5TZGsuUmVmbGVjdGlvbi5Qcm9qZWN0SW5mbwEAAAAFX25hbWUBAgAAAAkJAAAACwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA= - - - - AAEAAAD/////AQAAAAAAAAAMAgAAAFxTdWJNYWluLkNvZGVJdFJpZ2h0LlNkaywgVmVyc2lvbj0xLjEuMzYuMjAsIEN1bHR1cmU9bmV1dHJhbCwgUHVibGljS2V5VG9rZW49MTNmODc4MmMwYzg4YjUxMAwDAAAAZlN1Yk1haW4uQ29kZUl0UmlnaHQuQ29kZU9iamVjdE1vZGVsLCBWZXJzaW9uPTIuMi4wLjAsIEN1bHR1cmU9bmV1dHJhbCwgUHVibGljS2V5VG9rZW49YmE5NjRiYzlhZGYxZTE4OQUBAAAAMVN1Yk1haW4uQ29kZUl0UmlnaHQuU2RrLlJlZmxlY3Rpb24uRXhwcmVzc2lvbkluZm8EAAAAD19leHByZXNzaW9uVHlwZQdfcGFyZW50DF9wcm9qZWN0RmlsZQZfaW5kZXgEAgQAMVN1Yk1haW4uQ29kZU9iamVjdE1vZGVsLlJlZmxlY3Rpb24uRXhwcmVzc2lvblR5cGUDAAAAMlN1Yk1haW4uQ29kZUl0UmlnaHQuU2RrLlJlZmxlY3Rpb24uUHJvamVjdEZpbGVJbmZvAgAAAAgCAAAABfz///8xU3ViTWFpbi5Db2RlT2JqZWN0TW9kZWwuUmVmbGVjdGlvbi5FeHByZXNzaW9uVHlwZQEAAAAHdmFsdWVfXwAIAwAAAA8AAAAJBQAAAAkGAAAAAAAAAAEFAAAAAQAAAAH5/////P///wsAAAAJCAAAAAkJAAAAAAAAAAUGAAAAMlN1Yk1haW4uQ29kZUl0UmlnaHQuU2RrLlJlZmxlY3Rpb24uUHJvamVjdEZpbGVJbmZvAgAAAAxfcHJvamVjdE5hbWURX3JlbGF0aXZlRmlsZU5hbWUBAQIAAAAGCgAAAAhJbWFnZWtpdAYLAAAADy5cUmVzdENsaWVudC5jcwEIAAAAAQAAAAH0/////P///xgAAAAJDQAAAAkOAAAAAAAAAAEJAAAABgAAAAkKAAAABhAAAAAPLlxSZXN0Q2xpZW50LmNzAQ0AAAABAAAAAe/////8////IwAAAAkSAAAACRMAAAD/////AQ4AAAAGAAAACQoAAAAGFQAAAA8uXFJlc3RDbGllbnQuY3MFEgAAAC9TdWJNYWluLkNvZGVJdFJpZ2h0LlNkay5SZWZsZWN0aW9uLlZhcmlhYmxlSW5mbwQAAAAFX25hbWUPX3JldHVyblR5cGVJbmZvB19wYXJlbnQKX3N0YXRlbWVudAEEBAQxU3ViTWFpbi5Db2RlSXRSaWdodC5TZGsuUmVmbGVjdGlvbi5SZXR1cm5UeXBlSW5mbwIAAAAtU3ViTWFpbi5Db2RlSXRSaWdodC5TZGsuUmVmbGVjdGlvbi5NZXRob2RJbmZvAgAAADBTdWJNYWluLkNvZGVJdFJpZ2h0LlNkay5SZWZsZWN0aW9uLlN0YXRlbWVudEluZm8CAAAAAgAAAAYWAAAABmFwSXVybAkXAAAACRgAAAAJGQAAAAETAAAABgAAAAkKAAAABhsAAAAPLlxSZXN0Q2xpZW50LmNzDBwAAABgU3ViTWFpbi5Db2RlSXRSaWdodC5TZGsuQ29yZSwgVmVyc2lvbj0xLjEuMjIuMCwgQ3VsdHVyZT1uZXV0cmFsLCBQdWJsaWNLZXlUb2tlbj03OWJjMGRiOTc0MGE1ZjA0BRcAAAAxU3ViTWFpbi5Db2RlSXRSaWdodC5TZGsuUmVmbGVjdGlvbi5SZXR1cm5UeXBlSW5mbwYAAAAFX3R5cGUUX3BvaW50ZXJOZXN0aW5nTGV2ZWwQX2FycmF5RGltZW5zaW9ucwxfcHJvamVjdEZpbGURX2dlbmVyaWNBcmd1bWVudHMTX2Z1bGx5UXVhbGlmaWVkTmFtZQQABwQEATFTdWJNYWluLkNvZGVJdFJpZ2h0LlNkay5Db3JlLlJlZmxlY3Rpb24uSVR5cGVJbmZvHAAAAAgIMlN1Yk1haW4uQ29kZUl0UmlnaHQuU2RrLlJlZmxlY3Rpb24uUHJvamVjdEZpbGVJbmZvAgAAADlTdWJNYWluLkNvZGVJdFJpZ2h0LlNkay5Db3JlLlJlZmxlY3Rpb24uSVJldHVyblR5cGVJbmZvW10cAAAAAgAAAAoAAAAACgkdAAAACR4AAAAGHwAAAA1TeXN0ZW0uU3RyaW5nBRgAAAAtU3ViTWFpbi5Db2RlSXRSaWdodC5TZGsuUmVmbGVjdGlvbi5NZXRob2RJbmZvBwAAAAVfbmFtZQdfcGFyZW50C19yZXR1cm5UeXBlDF9wcm9qZWN0RmlsZQ5fY2FzZVNlbnNpdGl2ZQpfbW9kaWZpZXJzC19wYXJhbWV0ZXJzAQQEBAAEBCxTdWJNYWluLkNvZGVJdFJpZ2h0LlNkay5SZWZsZWN0aW9uLkNsYXNzSW5mbwIAAAAxU3ViTWFpbi5Db2RlSXRSaWdodC5TZGsuUmVmbGVjdGlvbi5SZXR1cm5UeXBlSW5mbwIAAAAyU3ViTWFpbi5Db2RlSXRSaWdodC5TZGsuUmVmbGVjdGlvbi5Qcm9qZWN0RmlsZUluZm8CAAAAATtTdWJNYWluLkNvZGVJdFJpZ2h0LlNkay5Db3JlLlJlZmxlY3Rpb24uTWVtYmVySW5mb01vZGlmaWVycxwAAAA4U3ViTWFpbi5Db2RlSXRSaWdodC5TZGsuQ29yZS5SZWZsZWN0aW9uLklQYXJhbWV0ZXJJbmZvW10cAAAAAgAAAAYgAAAAFWdldFJlbW90ZUZpbGVNZXRhRGF0YQkhAAAACSIAAAAJIwAAAAEF3P///ztTdWJNYWluLkNvZGVJdFJpZ2h0LlNkay5Db3JlLlJlZmxlY3Rpb24uTWVtYmVySW5mb01vZGlmaWVycwEAAAAHdmFsdWVfXwAIHAAAAAIAAAAJJQAAAAUZAAAAMFN1Yk1haW4uQ29kZUl0UmlnaHQuU2RrLlJlZmxlY3Rpb24uU3RhdGVtZW50SW5mbwQAAAAYQmxvY2tJbmZvK19zdGF0ZW1lbnRUeXBlFUJsb2NrSW5mbytfbWVtYmVySW5mbxFCbG9ja0luZm8rX3BhcmVudBBCbG9ja0luZm8rX2luZGV4BAQEADBTdWJNYWluLkNvZGVPYmplY3RNb2RlbC5SZWZsZWN0aW9uLlN0YXRlbWVudFR5cGUDAAAALVN1Yk1haW4uQ29kZUl0UmlnaHQuU2RrLlJlZmxlY3Rpb24uTWV0aG9kSW5mbwIAAAA2U3ViTWFpbi5Db2RlSXRSaWdodC5TZGsuQ29yZS5SZWZsZWN0aW9uLklTdGF0ZW1lbnRJbmZvHAAAAAgCAAAABdr///8wU3ViTWFpbi5Db2RlT2JqZWN0TW9kZWwuUmVmbGVjdGlvbi5TdGF0ZW1lbnRUeXBlAQAAAAd2YWx1ZV9fAAgDAAAAAwAAAAknAAAACgEAAAABHQAAAAYAAAAJCgAAAAYpAAAADy5cUmVzdENsaWVudC5jcwceAAAAAAEAAAAAAAAABDdTdWJNYWluLkNvZGVJdFJpZ2h0LlNkay5Db3JlLlJlZmxlY3Rpb24uSVJldHVyblR5cGVJbmZvHAAAAAUhAAAALFN1Yk1haW4uQ29kZUl0UmlnaHQuU2RrLlJlZmxlY3Rpb24uQ2xhc3NJbmZvCAAAAAVfbmFtZQpfY2xhc3NUeXBlB19wYXJlbnQOX25hbWVzcGFjZUluZm8OX2Nhc2VTZW5zaXRpdmUKX21vZGlmaWVycwxfcHJvamVjdE5hbWUNX3Byb2plY3RGaWxlcwEEBAQABAEENVN1Yk1haW4uQ29kZUl0UmlnaHQuU2RrLkNvcmUuUmVmbGVjdGlvbi5DbGFzc0luZm9UeXBlHAAAADFTdWJNYWluLkNvZGVJdFJpZ2h0LlNkay5Db3JlLlJlZmxlY3Rpb24uSVR5cGVJbmZvHAAAADBTdWJNYWluLkNvZGVJdFJpZ2h0LlNkay5SZWZsZWN0aW9uLk5hbWVzcGFjZUluZm8CAAAAATJTdWJNYWluLkNvZGVPYmplY3RNb2RlbC5SZWZsZWN0aW9uLk1lbWJlck1vZGlmaWVycwMAAAA6U3ViTWFpbi5Db2RlSXRSaWdodC5TZGsuQ29yZS5SZWZsZWN0aW9uLklQcm9qZWN0RmlsZUluZm9bXRwAAAACAAAABioAAAAKUmVzdENsaWVudAXV////NVN1Yk1haW4uQ29kZUl0UmlnaHQuU2RrLkNvcmUuUmVmbGVjdGlvbi5DbGFzc0luZm9UeXBlAQAAAAd2YWx1ZV9fAAgcAAAAAAAAAAoJLAAAAAEF0////zJTdWJNYWluLkNvZGVPYmplY3RNb2RlbC5SZWZsZWN0aW9uLk1lbWJlck1vZGlmaWVycwEAAAAHdmFsdWVfXwAIAwAAAAIAAAAJCgAAAAkvAAAAASIAAAAXAAAACgAAAAAKCSMAAAAJMQAAAAYyAAAANXtBQzczREM2MS05OTkxLTRBMTUtQjg0NC0yNTMyREU0MkFCOER9LlJlc3VsdE1ldGFEYXRhASMAAAAGAAAACQoAAAAGNAAAAA8uXFJlc3RDbGllbnQuY3MHJQAAAAABAAAAAQAAAAQ2U3ViTWFpbi5Db2RlSXRSaWdodC5TZGsuQ29yZS5SZWZsZWN0aW9uLklQYXJhbWV0ZXJJbmZvHAAAAAk1AAAAAScAAAAYAAAACSAAAAAJNwAAAAk4AAAACTkAAAABAcb////c////AgAAAAk7AAAABSwAAAAwU3ViTWFpbi5Db2RlSXRSaWdodC5TZGsuUmVmbGVjdGlvbi5OYW1lc3BhY2VJbmZvAgAAABNfZnVsbHlRdWFsaWZpZWROYW1lCV9wcm9qZWN0cwEENlN1Yk1haW4uQ29kZUl0UmlnaHQuU2RrLkNvcmUuUmVmbGVjdGlvbi5JUHJvamVjdEluZm9bXRwAAAACAAAABjwAAAAISW1hZ2VraXQJPQAAAAcvAAAAAAEAAAABAAAABDhTdWJNYWluLkNvZGVJdFJpZ2h0LlNkay5Db3JlLlJlZmxlY3Rpb24uSVByb2plY3RGaWxlSW5mbxwAAAAJPgAAAAcxAAAAAAEAAAAAAAAABDdTdWJNYWluLkNvZGVJdFJpZ2h0LlNkay5Db3JlLlJlZmxlY3Rpb24uSVJldHVyblR5cGVJbmZvHAAAAAU1AAAAMFN1Yk1haW4uQ29kZUl0UmlnaHQuU2RrLlJlZmxlY3Rpb24uUGFyYW1ldGVySW5mbwMAAAAFX25hbWUPX3JldHVyblR5cGVJbmZvB19wYXJlbnQBBAQxU3ViTWFpbi5Db2RlSXRSaWdodC5TZGsuUmVmbGVjdGlvbi5SZXR1cm5UeXBlSW5mbwIAAAAtU3ViTWFpbi5Db2RlSXRSaWdodC5TZGsuUmVmbGVjdGlvbi5NZXRob2RJbmZvAgAAAAIAAAAGPwAAAAN1cmwJQAAAAAkYAAAAATcAAAAhAAAABkIAAAAKUmVzdENsaWVudAG9////1f///wAAAAAKCUQAAAABAbv////T////AgAAAAkKAAAACUcAAAABOAAAABcAAAAKAAAAAAoJOQAAAAlJAAAACTIAAAABOQAAAAYAAAAJCgAAAAZMAAAADy5cUmVzdENsaWVudC5jcwc7AAAAAAEAAAABAAAABDZTdWJNYWluLkNvZGVJdFJpZ2h0LlNkay5Db3JlLlJlZmxlY3Rpb24uSVBhcmFtZXRlckluZm8cAAAACU0AAAAHPQAAAAABAAAAAQAAAAQ0U3ViTWFpbi5Db2RlSXRSaWdodC5TZGsuQ29yZS5SZWZsZWN0aW9uLklQcm9qZWN0SW5mbxwAAAAJTgAAAAE+AAAABgAAAAkKAAAABlAAAAAPLlxSZXN0Q2xpZW50LmNzAUAAAAAXAAAACgAAAAAKCSMAAAAJUgAAAAkfAAAAAUQAAAAsAAAACTwAAAAJVQAAAAdHAAAAAAEAAAABAAAABDhTdWJNYWluLkNvZGVJdFJpZ2h0LlNkay5Db3JlLlJlZmxlY3Rpb24uSVByb2plY3RGaWxlSW5mbxwAAAAJVgAAAAdJAAAAAAEAAAAAAAAABDdTdWJNYWluLkNvZGVJdFJpZ2h0LlNkay5Db3JlLlJlZmxlY3Rpb24uSVJldHVyblR5cGVJbmZvHAAAAAFNAAAANQAAAAk/AAAACVgAAAAJJwAAAAVOAAAALlN1Yk1haW4uQ29kZUl0UmlnaHQuU2RrLlJlZmxlY3Rpb24uUHJvamVjdEluZm8BAAAABV9uYW1lAQIAAAAJCgAAAAdSAAAAAAEAAAAAAAAABDdTdWJNYWluLkNvZGVJdFJpZ2h0LlNkay5Db3JlLlJlZmxlY3Rpb24uSVJldHVyblR5cGVJbmZvHAAAAAdVAAAAAAEAAAABAAAABDRTdWJNYWluLkNvZGVJdFJpZ2h0LlNkay5Db3JlLlJlZmxlY3Rpb24uSVByb2plY3RJbmZvHAAAAAlbAAAAAVYAAAAGAAAACQoAAAAGXQAAAA8uXFJlc3RDbGllbnQuY3MBWAAAABcAAAAKAAAAAAoJOQAAAAlfAAAACR8AAAABWwAAAE4AAAAJCgAAAAdfAAAAAAEAAAAAAAAABDdTdWJNYWluLkNvZGVJdFJpZ2h0LlNkay5Db3JlLlJlZmxlY3Rpb24uSVJldHVyblR5cGVJbmZvHAAAAAsAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA= - - - - - AAEAAAD/////AQAAAAAAAAAMAgAAAGBTdWJNYWluLkNvZGVJdFJpZ2h0LlNkay5Db3JlLCBWZXJzaW9uPTEuMS4yMi4wLCBDdWx0dXJlPW5ldXRyYWwsIFB1YmxpY0tleVRva2VuPTc5YmMwZGI5NzQwYTVmMDQFAQAAADhTdWJNYWluLkNvZGVJdFJpZ2h0LlNkay5Db3JlLkNvbGxlY3Rpb25zLlJ1bGVzQ29sbGVjdGlvbgMAAAANX2NvbHVtblNvcnRlcgZfY291bnQKSW5uZXJBcnJheQQABD9TdWJNYWluLkNvZGVJdFJpZ2h0LlNkay5Db3JlLkNvbGxlY3Rpb25zLlJ1bGVzQ29sbGVjdGlvbitTb3J0ZXICAAAACCpTdWJNYWluLkNvZGVJdFJpZ2h0LlNkay5Db3JlLlJ1bGVzLklSdWxlW10CAAAAAgAAAAkDAAAABQAAAAkEAAAABQMAAAA/U3ViTWFpbi5Db2RlSXRSaWdodC5TZGsuQ29yZS5Db2xsZWN0aW9ucy5SdWxlc0NvbGxlY3Rpb24rU29ydGVyAQAAAAxDb2x1bW5Ub1NvcnQBAgAAAAYFAAAAAAcEAAAAAAEAAABkAAAABChTdWJNYWluLkNvZGVJdFJpZ2h0LlNkay5Db3JlLlJ1bGVzLklSdWxlAgAAAAkGAAAACQcAAAAJCAAAAAkJAAAACQoAAAANXwwLAAAAaVN1Yk1haW4uQ29kZUl0UmlnaHQuUnVsZXMuUGVyZm9ybWFuY2UsIFZlcnNpb249MS4wLjAuMTQsIEN1bHR1cmU9bmV1dHJhbCwgUHVibGljS2V5VG9rZW49MTBjYmVjNTdjZjEwZWFjYgwMAAAAXFN1Yk1haW4uQ29kZUl0UmlnaHQuU2RrLCBWZXJzaW9uPTEuMS4zNi4yMCwgQ3VsdHVyZT1uZXV0cmFsLCBQdWJsaWNLZXlUb2tlbj0xM2Y4NzgyYzBjODhiNTEwDA0AAABmU3ViTWFpbi5Db2RlSXRSaWdodC5Db2RlT2JqZWN0TW9kZWwsIFZlcnNpb249Mi4yLjAuMCwgQ3VsdHVyZT1uZXV0cmFsLCBQdWJsaWNLZXlUb2tlbj1iYTk2NGJjOWFkZjFlMTg5BQYAAAA4U3ViTWFpbi5Db2RlSXRSaWdodC5SdWxlcy5QZXJmb3JtYW5jZS5SZW1vdmVVbnVzZWRMb2NhbHMjAAAAFF91bnVzZWRMb2NhbFZhcmlhYmxlCF90YXJnZXRzCl9sYW5ndWFnZXMLX2NhbkNvcnJlY3QdX2RlZmF1bHRDb3JyZWN0aW9uT3B0aW9uSW5kZXgMX3Byb2plY3ROYW1lI1N1Yk1haW5QZXJmb3JtYW5jZVJ1bGVCYXNlK190YXJnZXRzJVN1Yk1haW5QZXJmb3JtYW5jZVJ1bGVCYXNlK19sYW5ndWFnZXMmU3ViTWFpblBlcmZvcm1hbmNlUnVsZUJhc2UrX2NhbkNvcnJlY3Q4U3ViTWFpblBlcmZvcm1hbmNlUnVsZUJhc2UrX2RlZmF1bHRDb3JyZWN0aW9uT3B0aW9uSW5kZXgnU3ViTWFpblBlcmZvcm1hbmNlUnVsZUJhc2UrX3Byb2plY3ROYW1lGFN1Yk1haW5SdWxlQmFzZStfdGFyZ2V0cxpTdWJNYWluUnVsZUJhc2UrX2xhbmd1YWdlcxtTdWJNYWluUnVsZUJhc2UrX2NhbkNvcnJlY3QtU3ViTWFpblJ1bGVCYXNlK19kZWZhdWx0Q29ycmVjdGlvbk9wdGlvbkluZGV4HFN1Yk1haW5SdWxlQmFzZStfcHJvamVjdE5hbWURUnVsZUJhc2UrX3RhcmdldHMTUnVsZUJhc2UrX2xhbmd1YWdlcxRSdWxlQmFzZStfY2FuQ29ycmVjdCZSdWxlQmFzZStfZGVmYXVsdENvcnJlY3Rpb25PcHRpb25JbmRleBVSdWxlQmFzZStfcHJvamVjdE5hbWUWQWJzdHJhY3RSdWxlQmFzZStfbmFtZRdBYnN0cmFjdFJ1bGVCYXNlK190aXRsZRpBYnN0cmFjdFJ1bGVCYXNlK19zZXZlcml0eRhBYnN0cmFjdFJ1bGVCYXNlK19zdGF0dXMYQWJzdHJhY3RSdWxlQmFzZStfc2NvcGVzGUFic3RyYWN0UnVsZUJhc2UrX2VsZW1lbnQZQWJzdHJhY3RSdWxlQmFzZStfdGFyZ2V0cxtBYnN0cmFjdFJ1bGVCYXNlK19sYW5ndWFnZXMcQWJzdHJhY3RSdWxlQmFzZStfY2FuQ29ycmVjdBZBYnN0cmFjdFJ1bGVCYXNlK19ub3RlLkFic3RyYWN0UnVsZUJhc2UrX2RlZmF1bHRDb3JyZWN0aW9uT3B0aW9uSW5kZXgdQWJzdHJhY3RSdWxlQmFzZStfcHJvamVjdE5hbWUeQWJzdHJhY3RSdWxlQmFzZStfcmVsYXRpdmVQYXRoIEFic3RyYWN0UnVsZUJhc2UrX2lzU3R5bGVDb3BSdWxlBAQEAAABBAQAAAEEBAAAAQQEAAABAQEEBAQEBAQABAABAQAvU3ViTWFpbi5Db2RlSXRSaWdodC5TZGsuUmVmbGVjdGlvbi5WYXJpYWJsZUluZm8MAAAALlN1Yk1haW4uQ29kZUl0UmlnaHQuU2RrLkNvcmUuUnVsZXMuUnVsZVRhcmdldHMCAAAALFN1Yk1haW4uQ29kZU9iamVjdE1vZGVsLlJlZmxlY3Rpb24uTGFuZ3VhZ2VzDQAAAAEILlN1Yk1haW4uQ29kZUl0UmlnaHQuU2RrLkNvcmUuUnVsZXMuUnVsZVRhcmdldHMCAAAALFN1Yk1haW4uQ29kZU9iamVjdE1vZGVsLlJlZmxlY3Rpb24uTGFuZ3VhZ2VzDQAAAAEILlN1Yk1haW4uQ29kZUl0UmlnaHQuU2RrLkNvcmUuUnVsZXMuUnVsZVRhcmdldHMCAAAALFN1Yk1haW4uQ29kZU9iamVjdE1vZGVsLlJlZmxlY3Rpb24uTGFuZ3VhZ2VzDQAAAAEILlN1Yk1haW4uQ29kZUl0UmlnaHQuU2RrLkNvcmUuUnVsZXMuUnVsZVRhcmdldHMCAAAALFN1Yk1haW4uQ29kZU9iamVjdE1vZGVsLlJlZmxlY3Rpb24uTGFuZ3VhZ2VzDQAAAAEIMFN1Yk1haW4uQ29kZUl0UmlnaHQuU2RrLkNvcmUuUnVsZXMuU2V2ZXJpdHlMZXZlbAIAAAAvU3ViTWFpbi5Db2RlSXRSaWdodC5TZGsuQ29yZS5SdWxlcy5BY3RpdmVTdGF0dXMCAAAALVN1Yk1haW4uQ29kZUl0UmlnaHQuU2RrLkNvcmUuUnVsZXMuUnVsZVNjb3BlcwIAAAAtU3ViTWFpbi5Db2RlSXRSaWdodC5TZGsuUmVmbGVjdGlvbi5NZXRob2RJbmZvDAAAAC5TdWJNYWluLkNvZGVJdFJpZ2h0LlNkay5Db3JlLlJ1bGVzLlJ1bGVUYXJnZXRzAgAAACxTdWJNYWluLkNvZGVPYmplY3RNb2RlbC5SZWZsZWN0aW9uLkxhbmd1YWdlcw0AAAABJ1N1Yk1haW4uQ29kZUl0UmlnaHQuU2RrLkNvcmUuUnVsZXMuTm90ZQIAAAAIDwsAAAAJDgAAAAXx////LlN1Yk1haW4uQ29kZUl0UmlnaHQuU2RrLkNvcmUuUnVsZXMuUnVsZVRhcmdldHMBAAAAB3ZhbHVlX18ACQIAAAAAYAAAAAAAAAXw////LFN1Yk1haW4uQ29kZU9iamVjdE1vZGVsLlJlZmxlY3Rpb24uTGFuZ3VhZ2VzAQAAAAd2YWx1ZV9fAAgNAAAAAwAAAAAAAAAABhEAAAALQ29uc29sZUFwcDEB7v////H///8AYAAAAAAAAAHt////8P///wMAAAAAAAAAAAkRAAAAAez////x////AGAAAAAAAAAB6/////D///8DAAAAAAAAAAAJEQAAAAHq////8f///wBgAAAAAAAAAen////w////AwAAAAAAAAAACREAAAAGGAAAAB5NZXRob2QgLT4gUmVtb3ZlIHVudXNlZCBsb2NhbHMGGQAAABRSZW1vdmUgdW51c2VkIGxvY2FscwXm////MFN1Yk1haW4uQ29kZUl0UmlnaHQuU2RrLkNvcmUuUnVsZXMuU2V2ZXJpdHlMZXZlbAEAAAAHdmFsdWVfXwAIAgAAAAIAAAAF5f///y9TdWJNYWluLkNvZGVJdFJpZ2h0LlNkay5Db3JlLlJ1bGVzLkFjdGl2ZVN0YXR1cwEAAAAHdmFsdWVfXwAIAgAAAAEAAAAF5P///y1TdWJNYWluLkNvZGVJdFJpZ2h0LlNkay5Db3JlLlJ1bGVzLlJ1bGVTY29wZXMBAAAAB3ZhbHVlX18ACAIAAAD/nxUACR0AAAAB4v////H///8AYAAAAAAAAAHh////8P///wMAAAAACgAAAAAJEQAAAAYhAAAADC5cUHJvZ3JhbS5jcwIAAAAMIgAAAGRTdWJNYWluLkNvZGVJdFJpZ2h0LlJ1bGVzLk5hbWluZywgVmVyc2lvbj0xLjAuMC4xMSwgQ3VsdHVyZT1uZXV0cmFsLCBQdWJsaWNLZXlUb2tlbj0wYmVhNGY3YjdiOGVhZGI2DCMAAABJU3lzdGVtLCBWZXJzaW9uPTQuMC4wLjAsIEN1bHR1cmU9bmV1dHJhbCwgUHVibGljS2V5VG9rZW49Yjc3YTVjNTYxOTM0ZTA4OQUHAAAAQlN1Yk1haW4uQ29kZUl0UmlnaHQuUnVsZXMuTmFtaW5nLklkZW50aWZpZXJzU2hvdWxkQmVDYXNlZENvcnJlY3RseSkAAAAPX2lkZW50aWZpZXJDYXNlFV9wcm9jZXNzRXZlbnRIYW5kbGVycw5fZXhjbHVkZWRXb3JkcxVfY2FuQ29ycmVjdFdhc0NoYW5nZWQTX3VzZXJDb3JyZWN0T3B0aW9ucwhfdGFyZ2V0cwpfbGFuZ3VhZ2VzC19jYW5Db3JyZWN0HV9kZWZhdWx0Q29ycmVjdGlvbk9wdGlvbkluZGV4DF9wcm9qZWN0TmFtZSRTdWJNYWluTmFtaW5nUnVsZUJhc2UrX2V4Y2x1ZGVkV29yZHMrU3ViTWFpbk5hbWluZ1J1bGVCYXNlK19jYW5Db3JyZWN0V2FzQ2hhbmdlZClTdWJNYWluTmFtaW5nUnVsZUJhc2UrX3VzZXJDb3JyZWN0T3B0aW9ucx5TdWJNYWluTmFtaW5nUnVsZUJhc2UrX3RhcmdldHMgU3ViTWFpbk5hbWluZ1J1bGVCYXNlK19sYW5ndWFnZXMhU3ViTWFpbk5hbWluZ1J1bGVCYXNlK19jYW5Db3JyZWN0M1N1Yk1haW5OYW1pbmdSdWxlQmFzZStfZGVmYXVsdENvcnJlY3Rpb25PcHRpb25JbmRleCJTdWJNYWluTmFtaW5nUnVsZUJhc2UrX3Byb2plY3ROYW1lHU5hbWluZ1J1bGVCYXNlK19leGNsdWRlZFdvcmRzJE5hbWluZ1J1bGVCYXNlK19jYW5Db3JyZWN0V2FzQ2hhbmdlZBtOYW1pbmdSdWxlQmFzZStfZXhjbHVkZUxpc3QiTmFtaW5nUnVsZUJhc2UrX3VzZXJDb3JyZWN0T3B0aW9ucxdOYW1pbmdSdWxlQmFzZStfdGFyZ2V0cxlOYW1pbmdSdWxlQmFzZStfbGFuZ3VhZ2VzGk5hbWluZ1J1bGVCYXNlK19jYW5Db3JyZWN0LE5hbWluZ1J1bGVCYXNlK19kZWZhdWx0Q29ycmVjdGlvbk9wdGlvbkluZGV4G05hbWluZ1J1bGVCYXNlK19wcm9qZWN0TmFtZRZBYnN0cmFjdFJ1bGVCYXNlK19uYW1lF0Fic3RyYWN0UnVsZUJhc2UrX3RpdGxlGkFic3RyYWN0UnVsZUJhc2UrX3NldmVyaXR5GEFic3RyYWN0UnVsZUJhc2UrX3N0YXR1cxhBYnN0cmFjdFJ1bGVCYXNlK19zY29wZXMZQWJzdHJhY3RSdWxlQmFzZStfZWxlbWVudBlBYnN0cmFjdFJ1bGVCYXNlK190YXJnZXRzG0Fic3RyYWN0UnVsZUJhc2UrX2xhbmd1YWdlcxxBYnN0cmFjdFJ1bGVCYXNlK19jYW5Db3JyZWN0FkFic3RyYWN0UnVsZUJhc2UrX25vdGUuQWJzdHJhY3RSdWxlQmFzZStfZGVmYXVsdENvcnJlY3Rpb25PcHRpb25JbmRleB1BYnN0cmFjdFJ1bGVCYXNlK19wcm9qZWN0TmFtZR5BYnN0cmFjdFJ1bGVCYXNlK19yZWxhdGl2ZVBhdGggQWJzdHJhY3RSdWxlQmFzZStfaXNTdHlsZUNvcFJ1bGUEAAYABAQEAAABBgAEBAQAAAEGAAEEBAQAAAEBAQQEBAQEBAAEAAEBACtTdWJNYWluLkNvZGVJdFJpZ2h0LlJ1bGVzLk5hbWluZy5DYXNlT3B0aW9uIgAAAAEBL1N5c3RlbS5Db2xsZWN0aW9ucy5TcGVjaWFsaXplZC5TdHJpbmdDb2xsZWN0aW9uIwAAAC5TdWJNYWluLkNvZGVJdFJpZ2h0LlNkay5Db3JlLlJ1bGVzLlJ1bGVUYXJnZXRzAgAAACxTdWJNYWluLkNvZGVPYmplY3RNb2RlbC5SZWZsZWN0aW9uLkxhbmd1YWdlcw0AAAABCAEvU3lzdGVtLkNvbGxlY3Rpb25zLlNwZWNpYWxpemVkLlN0cmluZ0NvbGxlY3Rpb24jAAAALlN1Yk1haW4uQ29kZUl0UmlnaHQuU2RrLkNvcmUuUnVsZXMuUnVsZVRhcmdldHMCAAAALFN1Yk1haW4uQ29kZU9iamVjdE1vZGVsLlJlZmxlY3Rpb24uTGFuZ3VhZ2VzDQAAAAEIAS9TeXN0ZW0uQ29sbGVjdGlvbnMuU3BlY2lhbGl6ZWQuU3RyaW5nQ29sbGVjdGlvbiMAAAAuU3ViTWFpbi5Db2RlSXRSaWdodC5TZGsuQ29yZS5SdWxlcy5SdWxlVGFyZ2V0cwIAAAAsU3ViTWFpbi5Db2RlT2JqZWN0TW9kZWwuUmVmbGVjdGlvbi5MYW5ndWFnZXMNAAAAAQgwU3ViTWFpbi5Db2RlSXRSaWdodC5TZGsuQ29yZS5SdWxlcy5TZXZlcml0eUxldmVsAgAAAC9TdWJNYWluLkNvZGVJdFJpZ2h0LlNkay5Db3JlLlJ1bGVzLkFjdGl2ZVN0YXR1cwIAAAAtU3ViTWFpbi5Db2RlSXRSaWdodC5TZGsuQ29yZS5SdWxlcy5SdWxlU2NvcGVzAgAAAC1TdWJNYWluLkNvZGVJdFJpZ2h0LlNkay5SZWZsZWN0aW9uLk1ldGhvZEluZm8MAAAALlN1Yk1haW4uQ29kZUl0UmlnaHQuU2RrLkNvcmUuUnVsZXMuUnVsZVRhcmdldHMCAAAALFN1Yk1haW4uQ29kZU9iamVjdE1vZGVsLlJlZmxlY3Rpb24uTGFuZ3VhZ2VzDQAAAAEnU3ViTWFpbi5Db2RlSXRSaWdodC5TZGsuQ29yZS5SdWxlcy5Ob3RlAgAAAAgPIgAAAAXc////K1N1Yk1haW4uQ29kZUl0UmlnaHQuUnVsZXMuTmFtaW5nLkNhc2VPcHRpb24BAAAAB3ZhbHVlX18ACCIAAAACAAAAAAoACSUAAAAB2v////H///8A4BcAAAAAAAHZ////8P///wMAAAABAAAAAAkRAAAACgAJJQAAAAHW////8f///wDgFwAAAAAAAdX////w////AwAAAAEAAAAACREAAAAKAAoJJQAAAAHS////8f///wDgFwAAAAAAAdH////w////AwAAAAEAAAAACREAAAAGMQAAABZNZW1iZXIgLT4gUGFzY2FsIENhc2VkBjIAAAAsTWVtYmVyIGlkZW50aWZpZXJzIHNob3VsZCBiZSBjYXNlZCBjb3JyZWN0bHkBzf///+b///8CAAAAAcz////l////AQAAAAHL////5P////63NQAJNgAAAAHJ////8f///wDgFwAAAAAAAcj////w////AwAAAAEKAAAAAAkRAAAABjoAAAAMLlxQcm9ncmFtLmNzAgAAAAEIAAAABgAAAAk7AAAAAcT////x////AGAAAAAAAAABw/////D///8DAAAAAAAAAAAJEQAAAAHB////8f///wBgAAAAAAAAAcD////w////AwAAAAAAAAAACREAAAABv/////H///8AYAAAAAAAAAG+////8P///wMAAAAAAAAAAAkRAAAAAb3////x////AGAAAAAAAAABvP////D///8DAAAAAAAAAAAJEQAAAAZFAAAAHk1ldGhvZCAtPiBSZW1vdmUgdW51c2VkIGxvY2FscwZGAAAAFFJlbW92ZSB1bnVzZWQgbG9jYWxzAbn////m////AgAAAAG4////5f///wEAAAABt////+T/////nxUACTYAAAABtf////H///8AYAAAAAAAAAG0////8P///wMAAAAACgAAAAAJEQAAAAZOAAAADC5cUHJvZ3JhbS5jcwIAAAABCQAAAAcAAAABsf///9z///8CAAAAAAoACVAAAAABr/////H///8A4BcAAAAAAAGu////8P///wMAAAABAAAAAAkRAAAACgAJUAAAAAGr////8f///wDgFwAAAAAAAar////w////AwAAAAEAAAAACREAAAAKAAoJUAAAAAGn////8f///wDgFwAAAAAAAab////w////AwAAAAEAAAAACREAAAAGXAAAABZNZW1iZXIgLT4gUGFzY2FsIENhc2VkBl0AAAAsTWVtYmVyIGlkZW50aWZpZXJzIHNob3VsZCBiZSBjYXNlZCBjb3JyZWN0bHkBov///+b///8CAAAAAaH////l////AQAAAAGg////5P////63NQAJYQAAAAGe////8f///wDgFwAAAAAAAZ3////w////AwAAAAEKAAAAAAkRAAAABmUAAAAMLlxQcm9ncmFtLmNzAgAAAAEKAAAABgAAAAlmAAAAAZn////x////AGAAAAAAAAABmP////D///8DAAAAAAAAAAAJEQAAAAGW////8f///wBgAAAAAAAAAZX////w////AwAAAAAAAAAACREAAAABlP////H///8AYAAAAAAAAAGT////8P///wMAAAAAAAAAAAkRAAAAAZL////x////AGAAAAAAAAABkf////D///8DAAAAAAAAAAAJEQAAAAZwAAAAHk1ldGhvZCAtPiBSZW1vdmUgdW51c2VkIGxvY2FscwZxAAAAFFJlbW92ZSB1bnVzZWQgbG9jYWxzAY7////m////AgAAAAGN////5f///wEAAAABjP///+T/////nxUACWEAAAABiv////H///8AYAAAAAAAAAGJ////8P///wMAAAAACgAAAAAJEQAAAAZ5AAAADC5cUHJvZ3JhbS5jcwIAAAAFDgAAAC9TdWJNYWluLkNvZGVJdFJpZ2h0LlNkay5SZWZsZWN0aW9uLlZhcmlhYmxlSW5mbwQAAAAFX25hbWUPX3JldHVyblR5cGVJbmZvB19wYXJlbnQKX3N0YXRlbWVudAEEBAQxU3ViTWFpbi5Db2RlSXRSaWdodC5TZGsuUmVmbGVjdGlvbi5SZXR1cm5UeXBlSW5mbwwAAAAtU3ViTWFpbi5Db2RlSXRSaWdodC5TZGsuUmVmbGVjdGlvbi5NZXRob2RJbmZvDAAAADBTdWJNYWluLkNvZGVJdFJpZ2h0LlNkay5SZWZsZWN0aW9uLlN0YXRlbWVudEluZm8MAAAADAAAAAZ6AAAABXRva2VuCXsAAAAJfAAAAAl9AAAABR0AAAAtU3ViTWFpbi5Db2RlSXRSaWdodC5TZGsuUmVmbGVjdGlvbi5NZXRob2RJbmZvBwAAAAVfbmFtZQdfcGFyZW50C19yZXR1cm5UeXBlDF9wcm9qZWN0RmlsZQ5fY2FzZVNlbnNpdGl2ZQpfbW9kaWZpZXJzC19wYXJhbWV0ZXJzAQQEBAAEBCxTdWJNYWluLkNvZGVJdFJpZ2h0LlNkay5SZWZsZWN0aW9uLkNsYXNzSW5mbwwAAAAxU3ViTWFpbi5Db2RlSXRSaWdodC5TZGsuUmVmbGVjdGlvbi5SZXR1cm5UeXBlSW5mbwwAAAAyU3ViTWFpbi5Db2RlSXRSaWdodC5TZGsuUmVmbGVjdGlvbi5Qcm9qZWN0RmlsZUluZm8MAAAAATtTdWJNYWluLkNvZGVJdFJpZ2h0LlNkay5Db3JlLlJlZmxlY3Rpb24uTWVtYmVySW5mb01vZGlmaWVycwIAAAA4U3ViTWFpbi5Db2RlSXRSaWdodC5TZGsuQ29yZS5SZWZsZWN0aW9uLklQYXJhbWV0ZXJJbmZvW10CAAAADAAAAAZ+AAAABE1haW4JfwAAAAmAAAAACYEAAAABBX7///87U3ViTWFpbi5Db2RlSXRSaWdodC5TZGsuQ29yZS5SZWZsZWN0aW9uLk1lbWJlckluZm9Nb2RpZmllcnMBAAAAB3ZhbHVlX18ACAIAAACQAAAACYMAAAAFJQAAAC9TeXN0ZW0uQ29sbGVjdGlvbnMuU3BlY2lhbGl6ZWQuU3RyaW5nQ29sbGVjdGlvbgEAAAAEZGF0YQMcU3lzdGVtLkNvbGxlY3Rpb25zLkFycmF5TGlzdCMAAAAJhAAAAAE2AAAAHQAAAAaFAAAACWdldEJhc2U2NAmGAAAACYcAAAAJiAAAAAEBd////37///+QAAAACgE7AAAADgAAAAaKAAAAGWJhc2U2NEltYWdlUmVwcmVzZW50YXRpb24JiwAAAAmMAAAACY0AAAABUAAAACUAAAAJjgAAAAFhAAAAHQAAAAaPAAAADGdldEJhc2U2NFVSSQmQAAAACZEAAAAJkgAAAAEBbf///37///+QAAAACgFmAAAADgAAAAaUAAAACWNvbnZlcnRlZAmVAAAACZYAAAAJlwAAAAV7AAAAMVN1Yk1haW4uQ29kZUl0UmlnaHQuU2RrLlJlZmxlY3Rpb24uUmV0dXJuVHlwZUluZm8GAAAABV90eXBlFF9wb2ludGVyTmVzdGluZ0xldmVsEF9hcnJheURpbWVuc2lvbnMMX3Byb2plY3RGaWxlEV9nZW5lcmljQXJndW1lbnRzE19mdWxseVF1YWxpZmllZE5hbWUEAAcEBAExU3ViTWFpbi5Db2RlSXRSaWdodC5TZGsuQ29yZS5SZWZsZWN0aW9uLklUeXBlSW5mbwIAAAAICDJTdWJNYWluLkNvZGVJdFJpZ2h0LlNkay5SZWZsZWN0aW9uLlByb2plY3RGaWxlSW5mbwwAAAA5U3ViTWFpbi5Db2RlSXRSaWdodC5TZGsuQ29yZS5SZWZsZWN0aW9uLklSZXR1cm5UeXBlSW5mb1tdAgAAAAwAAAAKAAAAAAoJmAAAAAmZAAAABpoAAAADdmFyAXwAAAAdAAAACX4AAAAJnAAAAAmdAAAACZ4AAAABAWH///9+////kAAAAAmgAAAABX0AAAAwU3ViTWFpbi5Db2RlSXRSaWdodC5TZGsuUmVmbGVjdGlvbi5TdGF0ZW1lbnRJbmZvBAAAABhCbG9ja0luZm8rX3N0YXRlbWVudFR5cGUVQmxvY2tJbmZvK19tZW1iZXJJbmZvEUJsb2NrSW5mbytfcGFyZW50EEJsb2NrSW5mbytfaW5kZXgEBAQAMFN1Yk1haW4uQ29kZU9iamVjdE1vZGVsLlJlZmxlY3Rpb24uU3RhdGVtZW50VHlwZQ0AAAAtU3ViTWFpbi5Db2RlSXRSaWdodC5TZGsuUmVmbGVjdGlvbi5NZXRob2RJbmZvDAAAADZTdWJNYWluLkNvZGVJdFJpZ2h0LlNkay5Db3JlLlJlZmxlY3Rpb24uSVN0YXRlbWVudEluZm8CAAAACAwAAAAFX////zBTdWJNYWluLkNvZGVPYmplY3RNb2RlbC5SZWZsZWN0aW9uLlN0YXRlbWVudFR5cGUBAAAAB3ZhbHVlX18ACA0AAAADAAAACaIAAAAKAAAAAAV/AAAALFN1Yk1haW4uQ29kZUl0UmlnaHQuU2RrLlJlZmxlY3Rpb24uQ2xhc3NJbmZvCAAAAAVfbmFtZQpfY2xhc3NUeXBlB19wYXJlbnQOX25hbWVzcGFjZUluZm8OX2Nhc2VTZW5zaXRpdmUKX21vZGlmaWVycwxfcHJvamVjdE5hbWUNX3Byb2plY3RGaWxlcwEEBAQABAEENVN1Yk1haW4uQ29kZUl0UmlnaHQuU2RrLkNvcmUuUmVmbGVjdGlvbi5DbGFzc0luZm9UeXBlAgAAADFTdWJNYWluLkNvZGVJdFJpZ2h0LlNkay5Db3JlLlJlZmxlY3Rpb24uSVR5cGVJbmZvAgAAADBTdWJNYWluLkNvZGVJdFJpZ2h0LlNkay5SZWZsZWN0aW9uLk5hbWVzcGFjZUluZm8MAAAAATJTdWJNYWluLkNvZGVPYmplY3RNb2RlbC5SZWZsZWN0aW9uLk1lbWJlck1vZGlmaWVycw0AAAA6U3ViTWFpbi5Db2RlSXRSaWdodC5TZGsuQ29yZS5SZWZsZWN0aW9uLklQcm9qZWN0RmlsZUluZm9bXQIAAAAMAAAABqMAAAAHUHJvZ3JhbQVc////NVN1Yk1haW4uQ29kZUl0UmlnaHQuU2RrLkNvcmUuUmVmbGVjdGlvbi5DbGFzc0luZm9UeXBlAQAAAAd2YWx1ZV9fAAgCAAAAAAAAAAoJpQAAAAEFWv///zJTdWJNYWluLkNvZGVPYmplY3RNb2RlbC5SZWZsZWN0aW9uLk1lbWJlck1vZGlmaWVycwEAAAAHdmFsdWVfXwAIDQAAAAgAAAAJEQAAAAmoAAAAAYAAAAB7AAAACgAAAAAKCYEAAAAJqgAAAAarAAAAC1N5c3RlbS5Wb2lkBYEAAAAyU3ViTWFpbi5Db2RlSXRSaWdodC5TZGsuUmVmbGVjdGlvbi5Qcm9qZWN0RmlsZUluZm8CAAAADF9wcm9qZWN0TmFtZRFfcmVsYXRpdmVGaWxlTmFtZQEBDAAAAAkRAAAABq0AAAAMLlxQcm9ncmFtLmNzB4MAAAAAAQAAAAEAAAAENlN1Yk1haW4uQ29kZUl0UmlnaHQuU2RrLkNvcmUuUmVmbGVjdGlvbi5JUGFyYW1ldGVySW5mbwIAAAAJrgAAAASEAAAAHFN5c3RlbS5Db2xsZWN0aW9ucy5BcnJheUxpc3QDAAAABl9pdGVtcwVfc2l6ZQhfdmVyc2lvbgUAAAgICa8AAAABAAAAAQAAAAGGAAAAfwAAAAawAAAAB1Byb2dyYW0BT////1z///8AAAAACgmyAAAAAQFN////Wv///wgAAAAJEQAAAAm1AAAAAYcAAAB7AAAACgAAAAAJtgAAAAmIAAAACbgAAAAGuQAAAAtTeXN0ZW0uQnl0ZQGIAAAAgQAAAAkRAAAABrsAAAAMLlxQcm9ncmFtLmNzAYsAAAB7AAAACgAAAAAKCbwAAAAJvQAAAAa+AAAADVN5c3RlbS5TdHJpbmcBjAAAAB0AAAAJhQAAAAnAAAAACcEAAAAJwgAAAAEBPf///37///+QAAAACgGNAAAAfQAAAAE8////X////wMAAAAJxQAAAAoCAAAAAY4AAACEAAAACcYAAAABAAAAAQAAAAGQAAAAfwAAAAbHAAAAB1Byb2dyYW0BOP///1z///8AAAAACgnJAAAAAQE2////Wv///wgAAAAJEQAAAAnMAAAAAZEAAAB7AAAACgAAAAAKCZIAAAAJzgAAAAbPAAAAA1VyaQGSAAAAgQAAAAkRAAAABtEAAAAMLlxQcm9ncmFtLmNzAZUAAAB7AAAACgAAAAAKCdIAAAAJ0wAAAAbUAAAAA3ZhcgGWAAAAHQAAAAmPAAAACdYAAAAJ1wAAAAnYAAAAAQEn////fv///5AAAAAKAZcAAAB9AAAAASb///9f////AwAAAAnbAAAACgIAAAABmAAAAIEAAAAJEQAAAAbdAAAADC5cUHJvZ3JhbS5jcweZAAAAAAEAAAAAAAAABDdTdWJNYWluLkNvZGVJdFJpZ2h0LlNkay5Db3JlLlJlZmxlY3Rpb24uSVJldHVyblR5cGVJbmZvAgAAAAGcAAAAfwAAAAbeAAAAB1Byb2dyYW0BIf///1z///8AAAAACgngAAAAAQEf////Wv///wgAAAAJEQAAAAnjAAAAAZ0AAAB7AAAACgAAAAAKCZ4AAAAJ5QAAAAmrAAAAAZ4AAACBAAAACREAAAAG6AAAAAwuXFByb2dyYW0uY3MHoAAAAAABAAAAAQAAAAQ2U3ViTWFpbi5Db2RlSXRSaWdodC5TZGsuQ29yZS5SZWZsZWN0aW9uLklQYXJhbWV0ZXJJbmZvAgAAAAnpAAAAAaIAAAAdAAAACX4AAAAJ6wAAAAnsAAAACe0AAAABARL///9+////kAAAAAnvAAAABaUAAAAwU3ViTWFpbi5Db2RlSXRSaWdodC5TZGsuUmVmbGVjdGlvbi5OYW1lc3BhY2VJbmZvAgAAABNfZnVsbHlRdWFsaWZpZWROYW1lCV9wcm9qZWN0cwEENlN1Yk1haW4uQ29kZUl0UmlnaHQuU2RrLkNvcmUuUmVmbGVjdGlvbi5JUHJvamVjdEluZm9bXQIAAAAMAAAABvAAAAALQ29uc29sZUFwcDEJ8QAAAAeoAAAAAAEAAAABAAAABDhTdWJNYWluLkNvZGVJdFJpZ2h0LlNkay5Db3JlLlJlZmxlY3Rpb24uSVByb2plY3RGaWxlSW5mbwIAAAAJ8gAAAAeqAAAAAAEAAAAAAAAABDdTdWJNYWluLkNvZGVJdFJpZ2h0LlNkay5Db3JlLlJlZmxlY3Rpb24uSVJldHVyblR5cGVJbmZvAgAAAAWuAAAAMFN1Yk1haW4uQ29kZUl0UmlnaHQuU2RrLlJlZmxlY3Rpb24uUGFyYW1ldGVySW5mbwMAAAAFX25hbWUPX3JldHVyblR5cGVJbmZvB19wYXJlbnQBBAQxU3ViTWFpbi5Db2RlSXRSaWdodC5TZGsuUmVmbGVjdGlvbi5SZXR1cm5UeXBlSW5mbwwAAAAtU3ViTWFpbi5Db2RlSXRSaWdodC5TZGsuUmVmbGVjdGlvbi5NZXRob2RJbmZvDAAAAAwAAAAG8wAAAARhcmdzCfQAAAAJHQAAABCvAAAABAAAAAb2AAAACUdldEJhc2U2NA0DAbIAAAClAAAACfAAAAAJ+AAAAAe1AAAAAAEAAAABAAAABDhTdWJNYWluLkNvZGVJdFJpZ2h0LlNkay5Db3JlLlJlZmxlY3Rpb24uSVByb2plY3RGaWxlSW5mbwIAAAAJ+QAAAA+2AAAAAQAAAAgBAAAAB7gAAAAAAQAAAAAAAAAEN1N1Yk1haW4uQ29kZUl0UmlnaHQuU2RrLkNvcmUuUmVmbGVjdGlvbi5JUmV0dXJuVHlwZUluZm8CAAAAAbwAAACBAAAACREAAAAG+wAAAAwuXFByb2dyYW0uY3MHvQAAAAABAAAAAAAAAAQ3U3ViTWFpbi5Db2RlSXRSaWdodC5TZGsuQ29yZS5SZWZsZWN0aW9uLklSZXR1cm5UeXBlSW5mbwIAAAABwAAAAH8AAAAG/AAAAAdQcm9ncmFtAQP///9c////AAAAAAoJ/gAAAAEBAf///1r///8IAAAACREAAAAJAQEAAAHBAAAAewAAAAoAAAAACbYAAAAJwgAAAAkEAQAACbkAAAABwgAAAIEAAAAJEQAAAAYHAQAADC5cUHJvZ3JhbS5jcwHFAAAAHQAAAAmFAAAACQkBAAAJCgEAAAkLAQAAAQH0/v//fv///5AAAAAKEMYAAAAEAAAABg0BAAAMR2V0QmFzZTY0VXJpDQMByQAAAKUAAAAJ8AAAAAkPAQAAB8wAAAAAAQAAAAEAAAAEOFN1Yk1haW4uQ29kZUl0UmlnaHQuU2RrLkNvcmUuUmVmbGVjdGlvbi5JUHJvamVjdEZpbGVJbmZvAgAAAAkQAQAAB84AAAAAAQAAAAAAAAAEN1N1Yk1haW4uQ29kZUl0UmlnaHQuU2RrLkNvcmUuUmVmbGVjdGlvbi5JUmV0dXJuVHlwZUluZm8CAAAAAdIAAACBAAAACREAAAAGEgEAAAwuXFByb2dyYW0uY3MH0wAAAAABAAAAAAAAAAQ3U3ViTWFpbi5Db2RlSXRSaWdodC5TZGsuQ29yZS5SZWZsZWN0aW9uLklSZXR1cm5UeXBlSW5mbwIAAAAB1gAAAH8AAAAGEwEAAAdQcm9ncmFtAez+//9c////AAAAAAoJFQEAAAEB6v7//1r///8IAAAACREAAAAJGAEAAAHXAAAAewAAAAoAAAAACgnYAAAACRoBAAAJzwAAAAHYAAAAgQAAAAkRAAAABh0BAAAMLlxQcm9ncmFtLmNzAdsAAAAdAAAACY8AAAAJHwEAAAkgAQAACSEBAAABAd7+//9+////kAAAAAoB4AAAAKUAAAAJ8AAAAAkkAQAAB+MAAAAAAQAAAAEAAAAEOFN1Yk1haW4uQ29kZUl0UmlnaHQuU2RrLkNvcmUuUmVmbGVjdGlvbi5JUHJvamVjdEZpbGVJbmZvAgAAAAklAQAAB+UAAAAAAQAAAAAAAAAEN1N1Yk1haW4uQ29kZUl0UmlnaHQuU2RrLkNvcmUuUmVmbGVjdGlvbi5JUmV0dXJuVHlwZUluZm8CAAAAAekAAACuAAAACfMAAAAJJwEAAAl8AAAAAesAAAB/AAAABikBAAAHUHJvZ3JhbQHW/v//XP///wAAAAAKCSsBAAABAdT+//9a////CAAAAAkRAAAACS4BAAAB7AAAAHsAAAAKAAAAAAoJ7QAAAAkwAQAACasAAAAB7QAAAIEAAAAJEQAAAAYzAQAADC5cUHJvZ3JhbS5jcwfvAAAAAAEAAAABAAAABDZTdWJNYWluLkNvZGVJdFJpZ2h0LlNkay5Db3JlLlJlZmxlY3Rpb24uSVBhcmFtZXRlckluZm8CAAAACTQBAAAH8QAAAAABAAAAAQAAAAQ0U3ViTWFpbi5Db2RlSXRSaWdodC5TZGsuQ29yZS5SZWZsZWN0aW9uLklQcm9qZWN0SW5mbwIAAAAJNQEAAAHyAAAAgQAAAAkRAAAABjcBAAAMLlxQcm9ncmFtLmNzAfQAAAB7AAAACgAAAAAJOAEAAAmBAAAACToBAAAJvgAAAAf4AAAAAAEAAAABAAAABDRTdWJNYWluLkNvZGVJdFJpZ2h0LlNkay5Db3JlLlJlZmxlY3Rpb24uSVByb2plY3RJbmZvAgAAAAk8AQAAAfkAAACBAAAACREAAAAGPgEAAAwuXFByb2dyYW0uY3MB/gAAAKUAAAAJ8AAAAAlAAQAABwEBAAAAAQAAAAEAAAAEOFN1Yk1haW4uQ29kZUl0UmlnaHQuU2RrLkNvcmUuUmVmbGVjdGlvbi5JUHJvamVjdEZpbGVJbmZvAgAAAAlBAQAABwQBAAAAAQAAAAAAAAAEN1N1Yk1haW4uQ29kZUl0UmlnaHQuU2RrLkNvcmUuUmVmbGVjdGlvbi5JUmV0dXJuVHlwZUluZm8CAAAAAQkBAAB/AAAABkIBAAAHUHJvZ3JhbQG9/v//XP///wAAAAAKCUQBAAABAbv+//9a////CAAAAAkRAAAACUcBAAABCgEAAHsAAAAKAAAAAAm2AAAACQsBAAAJSgEAAAm5AAAAAQsBAACBAAAACREAAAAGTQEAAAwuXFByb2dyYW0uY3MHDwEAAAABAAAAAQAAAAQ0U3ViTWFpbi5Db2RlSXRSaWdodC5TZGsuQ29yZS5SZWZsZWN0aW9uLklQcm9qZWN0SW5mbwIAAAAJTgEAAAEQAQAAgQAAAAkRAAAABlABAAAMLlxQcm9ncmFtLmNzARUBAAClAAAACfAAAAAJUgEAAAcYAQAAAAEAAAABAAAABDhTdWJNYWluLkNvZGVJdFJpZ2h0LlNkay5Db3JlLlJlZmxlY3Rpb24uSVByb2plY3RGaWxlSW5mbwIAAAAJUwEAAAcaAQAAAAEAAAAAAAAABDdTdWJNYWluLkNvZGVJdFJpZ2h0LlNkay5Db3JlLlJlZmxlY3Rpb24uSVJldHVyblR5cGVJbmZvAgAAAAEfAQAAfwAAAAZUAQAAB1Byb2dyYW0Bq/7//1z///8AAAAACglWAQAAAQGp/v//Wv///wgAAAAJEQAAAAlZAQAAASABAAB7AAAACgAAAAAKCSEBAAAJWwEAAAnPAAAAASEBAACBAAAACREAAAAGXgEAAAwuXFByb2dyYW0uY3MHJAEAAAABAAAAAQAAAAQ0U3ViTWFpbi5Db2RlSXRSaWdodC5TZGsuQ29yZS5SZWZsZWN0aW9uLklQcm9qZWN0SW5mbwIAAAAJXwEAAAElAQAAgQAAAAkRAAAABmEBAAAMLlxQcm9ncmFtLmNzAScBAAB7AAAACgAAAAAJOAEAAAmeAAAACWQBAAAJvgAAAAErAQAApQAAAAnwAAAACWcBAAAHLgEAAAABAAAAAQAAAAQ4U3ViTWFpbi5Db2RlSXRSaWdodC5TZGsuQ29yZS5SZWZsZWN0aW9uLklQcm9qZWN0RmlsZUluZm8CAAAACWgBAAAHMAEAAAABAAAAAAAAAAQ3U3ViTWFpbi5Db2RlSXRSaWdodC5TZGsuQ29yZS5SZWZsZWN0aW9uLklSZXR1cm5UeXBlSW5mbwIAAAABNAEAAK4AAAAJ8wAAAAlqAQAACaIAAAAFNQEAAC5TdWJNYWluLkNvZGVJdFJpZ2h0LlNkay5SZWZsZWN0aW9uLlByb2plY3RJbmZvAQAAAAVfbmFtZQEMAAAACREAAAAPOAEAAAEAAAAIAQAAAAc6AQAAAAEAAAAAAAAABDdTdWJNYWluLkNvZGVJdFJpZ2h0LlNkay5Db3JlLlJlZmxlY3Rpb24uSVJldHVyblR5cGVJbmZvAgAAAAE8AQAANQEAAAkRAAAAB0ABAAAAAQAAAAEAAAAENFN1Yk1haW4uQ29kZUl0UmlnaHQuU2RrLkNvcmUuUmVmbGVjdGlvbi5JUHJvamVjdEluZm8CAAAACW0BAAABQQEAAIEAAAAJEQAAAAZvAQAADC5cUHJvZ3JhbS5jcwFEAQAApQAAAAnwAAAACXEBAAAHRwEAAAABAAAAAQAAAAQ4U3ViTWFpbi5Db2RlSXRSaWdodC5TZGsuQ29yZS5SZWZsZWN0aW9uLklQcm9qZWN0RmlsZUluZm8CAAAACXIBAAAHSgEAAAABAAAAAAAAAAQ3U3ViTWFpbi5Db2RlSXRSaWdodC5TZGsuQ29yZS5SZWZsZWN0aW9uLklSZXR1cm5UeXBlSW5mbwIAAAABTgEAADUBAAAJEQAAAAdSAQAAAAEAAAABAAAABDRTdWJNYWluLkNvZGVJdFJpZ2h0LlNkay5Db3JlLlJlZmxlY3Rpb24uSVByb2plY3RJbmZvAgAAAAl0AQAAAVMBAACBAAAACREAAAAGdgEAAAwuXFByb2dyYW0uY3MBVgEAAKUAAAAJ8AAAAAl4AQAAB1kBAAAAAQAAAAEAAAAEOFN1Yk1haW4uQ29kZUl0UmlnaHQuU2RrLkNvcmUuUmVmbGVjdGlvbi5JUHJvamVjdEZpbGVJbmZvAgAAAAl5AQAAB1sBAAAAAQAAAAAAAAAEN1N1Yk1haW4uQ29kZUl0UmlnaHQuU2RrLkNvcmUuUmVmbGVjdGlvbi5JUmV0dXJuVHlwZUluZm8CAAAAAV8BAAA1AQAACREAAAAHZAEAAAABAAAAAAAAAAQ3U3ViTWFpbi5Db2RlSXRSaWdodC5TZGsuQ29yZS5SZWZsZWN0aW9uLklSZXR1cm5UeXBlSW5mbwIAAAAHZwEAAAABAAAAAQAAAAQ0U3ViTWFpbi5Db2RlSXRSaWdodC5TZGsuQ29yZS5SZWZsZWN0aW9uLklQcm9qZWN0SW5mbwIAAAAJewEAAAFoAQAAgQAAAAkRAAAABn0BAAAMLlxQcm9ncmFtLmNzAWoBAAB7AAAACgAAAAAJOAEAAAntAAAACYABAAAJvgAAAAFtAQAANQEAAAkRAAAAB3EBAAAAAQAAAAEAAAAENFN1Yk1haW4uQ29kZUl0UmlnaHQuU2RrLkNvcmUuUmVmbGVjdGlvbi5JUHJvamVjdEluZm8CAAAACYMBAAABcgEAAIEAAAAJEQAAAAaFAQAADC5cUHJvZ3JhbS5jcwF0AQAANQEAAAkRAAAAB3gBAAAAAQAAAAEAAAAENFN1Yk1haW4uQ29kZUl0UmlnaHQuU2RrLkNvcmUuUmVmbGVjdGlvbi5JUHJvamVjdEluZm8CAAAACYcBAAABeQEAAIEAAAAJEQAAAAaJAQAADC5cUHJvZ3JhbS5jcwF7AQAANQEAAAkRAAAAB4ABAAAAAQAAAAAAAAAEN1N1Yk1haW4uQ29kZUl0UmlnaHQuU2RrLkNvcmUuUmVmbGVjdGlvbi5JUmV0dXJuVHlwZUluZm8CAAAAAYMBAAA1AQAACREAAAABhwEAADUBAAAJEQAAAAsAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA== - \ No newline at end of file diff --git a/Imagekit.sln b/Imagekit.sln index 84305571..2e968497 100644 --- a/Imagekit.sln +++ b/Imagekit.sln @@ -1,43 +1,27 @@ - -Microsoft Visual Studio Solution File, Format Version 12.00 +Microsoft Visual Studio Solution File, Format Version 12.00 # Visual Studio Version 17 -VisualStudioVersion = 17.2.32630.192 +VisualStudioVersion = 17.0.31903.59 MinimumVisualStudioVersion = 10.0.40219.1 -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Imagekit", "Imagekit\Imagekit.csproj", "{D7929DCF-13EC-4677-9859-D55DA9D752E4}" +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Imagekit", "src\Imagekit\Imagekit.csproj", "{5816A0C1-3BA1-454E-8D08-85B23DEF309D}" EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{C4C9DA70-E3C7-4848-AB58-E93762408560}" - ProjectSection(SolutionItems) = preProject - .editorconfig = .editorconfig - EndProjectSection -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Imagekit.UnitTests", "Imagekit.UnitTests\Imagekit.UnitTests.csproj", "{B459E977-A7C2-47CB-A743-2F0AAFCE8178}" +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Imagekit.Tests", "src\Imagekit.Tests\Imagekit.Tests.csproj", "{0732C8A6-7313-4C33-AE2E-FFAA82EFB481}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU Release|Any CPU = Release|Any CPU EndGlobalSection - GlobalSection(ProjectConfigurationPlatforms) = postSolution - {D7929DCF-13EC-4677-9859-D55DA9D752E4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {D7929DCF-13EC-4677-9859-D55DA9D752E4}.Debug|Any CPU.Build.0 = Debug|Any CPU - {D7929DCF-13EC-4677-9859-D55DA9D752E4}.Release|Any CPU.ActiveCfg = Release|Any CPU - {D7929DCF-13EC-4677-9859-D55DA9D752E4}.Release|Any CPU.Build.0 = Release|Any CPU - {B459E977-A7C2-47CB-A743-2F0AAFCE8178}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {B459E977-A7C2-47CB-A743-2F0AAFCE8178}.Debug|Any CPU.Build.0 = Debug|Any CPU - {B459E977-A7C2-47CB-A743-2F0AAFCE8178}.Release|Any CPU.ActiveCfg = Release|Any CPU - {B459E977-A7C2-47CB-A743-2F0AAFCE8178}.Release|Any CPU.Build.0 = Release|Any CPU - EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE EndGlobalSection - GlobalSection(ExtensibilityGlobals) = postSolution - SolutionGuid = {CCE1EF90-4EA0-4458-90C1-7F408AE6E292} - EndGlobalSection - GlobalSection(MonoDevelopProperties) = preSolution - Policies = $0 - $0.DotNetNamingPolicy = $1 - $1.DirectoryNamespaceAssociation = PrefixedHierarchical - $0.StandardHeader = $2 - $0.VersionControlPolicy = $3 + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {5816A0C1-3BA1-454E-8D08-85B23DEF309D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {5816A0C1-3BA1-454E-8D08-85B23DEF309D}.Debug|Any CPU.Build.0 = Debug|Any CPU + {5816A0C1-3BA1-454E-8D08-85B23DEF309D}.Release|Any CPU.ActiveCfg = Release|Any CPU + {5816A0C1-3BA1-454E-8D08-85B23DEF309D}.Release|Any CPU.Build.0 = Release|Any CPU + {0732C8A6-7313-4C33-AE2E-FFAA82EFB481}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {0732C8A6-7313-4C33-AE2E-FFAA82EFB481}.Debug|Any CPU.Build.0 = Debug|Any CPU + {0732C8A6-7313-4C33-AE2E-FFAA82EFB481}.Release|Any CPU.ActiveCfg = Release|Any CPU + {0732C8A6-7313-4C33-AE2E-FFAA82EFB481}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection EndGlobal diff --git a/Imagekit.sln.CodeItRight.xml b/Imagekit.sln.CodeItRight.xml deleted file mode 100644 index ee2ebdb7..00000000 --- a/Imagekit.sln.CodeItRight.xml +++ /dev/null @@ -1,6 +0,0 @@ - - - *.min.js - jquery*.js - - diff --git a/Imagekit/Constant/UrlHandler.cs b/Imagekit/Constant/UrlHandler.cs deleted file mode 100644 index 07ef3c3b..00000000 --- a/Imagekit/Constant/UrlHandler.cs +++ /dev/null @@ -1,42 +0,0 @@ -// -// Copyright (c) PlaceholderCompany. All rights reserved. -// - -namespace Imagekit.Constant -{ - public static class UrlHandler - { - public const string MediaAPIBaseUrl = "https://api.imagekit.io/"; - public const string UploadAPIBaseUrl = "https://upload.imagekit.io/"; - public const string UploadFile = @"api/v1/files/upload"; - public const string UpdateFileRequest = @"v1/files/{0}/details"; - public const string GetFileRequest = @"v1/files/?{0}"; - public const string GetPurge = @"v1/files/purge"; - public const string GetPurgeStatus = @"v1/files/purge/{0}"; - public const string GetFileDetails = @"v1/files/{0}/details"; - public const string DeleteFile = @"v1/files/{0}/"; - public const string BulkDelete = @"v1/files/batch/deleteByfileIds"; - public const string GetMetaData = @"v1/files/{0}/metadata"; - public const string GetRemoteData = @"v1/metadata?url={0}"; - public const string RemoveTags = @"v1/files/removeTags"; - public const string AddTags = @"v1/files/addTags"; - public const string RemoveAITags = @"v1/files/removeAITags"; - public const string CustomMetadataFields = @"v1/customMetadataFields?includeDeleted={0}"; - public const string CreareCustomMetaDataFields = @"v1/customMetadataFields"; - public const string DeleteCustomMetaDataFields = @"v1/customMetadataFields/{0}"; - public const string UpdateCustomMetadataFields = @"v1/customMetadataFields/{0}"; - public const string DeleteVesrion = @"v1/files/{0}/versions/{1}"; - public const string CopyFile = @"v1/files/copy"; - public const string MoveFile = @"v1/files/move"; - public const string RenameFile = @"v1/files/rename"; - public const string RestoreVesrion = @"v1/files/{0}/versions/{1}/restore"; - public const string CreateFolder = @"v1/folder/"; - public const string DeleteFolder = @"v1/folder/"; - public const string CopyFolder = @"v1/bulkJobs/copyFolder"; - public const string MoveFolder = @"v1/bulkJobs/moveFolder"; - public const string GetJobStatus = @"v1/bulkJobs/{0}"; - public const string GetFileVersion = @"v1/files/{0}/versions"; - public const string GetFileVersionDetail = @"v1/files/{0}/versions/{1}"; - public const string GetBoundaryString = "ImageKit-dLV9Wyq26L"; - } -} \ No newline at end of file diff --git a/Imagekit/Constant/errorMessages.cs b/Imagekit/Constant/errorMessages.cs deleted file mode 100644 index 3e24fa51..00000000 --- a/Imagekit/Constant/errorMessages.cs +++ /dev/null @@ -1,73 +0,0 @@ -// -// Copyright (c) PlaceholderCompany. All rights reserved. -// - -namespace Imagekit.Constant -{ - public static class ErrorMessages - { - public const string MandatoryInitializationMissing = "{ \"message\": \"Missing publicKey or privateKey or urlEndpoint during Imagekit initialization\", \"help\": \"\" }"; - public const string MandatoryPublicKeyMissing = "{ \"message\": \"Missing publicKey during Imagekit initialization\", \"help\": \"\" }"; - public const string PrivateKeyMissing = "{ \"message\": \"Missing privateKey during Imagekit initialization\", \"help\": \"\" }"; - public const string MandatoryUrlEndpointKeyMissing = "{ \"message\": \"Missing urlEndpoint during Imagekit initialization\", \"help\": \"\" }"; - public const string InvalidTransformationPosition = "{ \"message\": \"Invalid transformationPosition parameter\", \"help\": \"\" }"; - public const string CachePurgeUrlMissing = "{ \"message\": \"Missing URL parameter for this request\", \"help\": \"\" }"; - public const string CachePurgeStatusIdMissing = "{ message: \"Missing Request ID parameter for this request\", \"help\": \"\" }"; - public const string FileIdMissing = "{ \"message\": \"Missing File ID parameter for this request\", \"help\": \"\" }"; - public const string InvalidUri = "{ \"message\": \"Invalid URI\", \"help\": \"Only HTTP or HTTPS Type Absolute URL are valid.\" }"; - public const string UpdateDataMissing = "{ \"message\": \"Missing file update data for this request\", \"help\": \"\" }"; - public const string UpdateDataTagsInvalid = "{ \"message\": \"Invalid tags parameter for this request\", \"help\": \"tags should be passed as 'null', a string like 'tag1,tag2', or an array like (new string[] { 'tag1', 'tag2' })\" }"; - public const string UpdateDataCoordsInvalid = "{ \"message\": \"Invalid customCoordinates parameter for this request\", \"help\": \"customCoordinates should be passed as null or a string like 'x,y,width,height'\" }"; - public const string ListFilesInputMissing = "{ \"message\": \"Missing options for list files\", \"help\": \"If you do not want to pass any parameter for listing, pass an empty object\" }"; - public const string MissingUploadData = "{ \"message\": \"Missing data for upload\", \"help\": \"\" }"; - public const string MissingUploadFileParameter = "{ \"message\": \"Missing file parameter for upload\", \"help\": \"\" }"; - public const string InvalidPhashValue = "{ \"message: \"Invalid pHash value\", \"help\": \"Both pHash strings must be valid hexadecimal numbers\" }"; - public const string MissingPhashValue = "{ \"message: \"Missing pHash value\", \"help\": \"Please pass two pHash values\" }"; - public const string UnequalStringLength = "{ \"message: \"Unequal pHash string length\", \"help\": \"For distance calucation, the two pHash strings must have equal length\" }"; - public const string InvalidfileIdsValue = "{ \"message: \"Invalid value for fileId\", \"help\": \"fileIds should be an string array of fileId of the files to delete. The array should have atleast one fileId.\" }"; - public const string InvalidUrlValue = "{ \"message: \"Missing URL parameter for this request\", \"help\": \"\" }"; - public const string InvalidCopyValue = "{ \"message: \"sourceFilePath and DestinationFilePath both parameter are required\", \"help\": \"\" }"; - public const string InvalidJobValue = "{ \"message: \"JobId parameter are required\", \"help\": \"\" }"; - public const string InvalidFolderValue = "{ \"message: \"FilePath and NewFileName both parameter are required\", \"help\": \"\" }"; - - public const string MissingUploadFilenameParameter = "{ \"message\": \"Missing fileName parameter for upload\", \"help\": \"\" }"; - public const string InvalidMetaTagValue = "{ \"message: \"Invalid MetaData parameter for this request\", \"help\": \"\" }"; - public const string InvalidMetaTagNameValue = "{ \"message: \"Invalid MetaData name parameter for this request\", \"help\": \"\" }"; - - public const string InvalidMetaTagLabelValue = "{ \"message: \"Invalid MetaData label parameter for this request\", \"help\": \"\" }"; - public const string InvalidMetaTagSchemaValue = "{ \"message: \"Invalid MetaData Schema parameter for this request\", \"help\": \"\" }"; - public const string InvalidDelVerValue = "{ \"message: \"FieldId and versionId both parameters are required\", \"help\": \"\" }"; - - public const string InvalidFileUploadObjValue = "{ \"message: \"Missing data for upload\", \"help\": \"\" }"; - - public const string InvalidFileValue = "{ \"message: \"Missing file parameter for upload\", \"help\": \"\" }"; - public const string InvalidTagValue = "{ \"message: \"Invalid parameter for this request\", \"help\": \"\" }"; - - public const string InvalidTagParamValue = "{ \"message: \"Invalid value for tags\", \"help\": \"tags should be a non empty array of string like ['tag1', 'tag2'].\" }"; - public const string InvalidFiledParamValue = "{ \"message: \"Invalid value for fileIds\", \"help\": \"fileIds should be an array of fileId of the files. The array should have atleast one fileId.\" }"; - - public const string InvalidMetaTagIdValue = "{ \"message: \"Invalid MetaData Id parameter for this request\", \"help\": \"\" }"; - - public const string InvalidFieldIdDelVerValue = "{ \"message: \"Missing fileId parameter for this request\", \"help\": \"\" }"; - public const string InvalidversionIdDelVerValue = "{ \"message: \"Missing versionId parameter for this request\", \"help\": \"\" }"; - public const string InvalidMoveValue = "{ \"message: \"sourceFilePath and DestinationFilePath both parameter are required\", \"help\": \"\" }"; - public const string InvalidSourceValue = "{ \"message: \"Missing sourceFilePath parameter for this request\", \"help\": \"\" }"; - public const string InvalidDestinationValue = "{ \"message: \"Missing DestinationFilePath parameter for this request\", \"help\": \"\" }"; - public const string InvalidDelFolderValue = "{ \"message: \"FolderPath parameter are required\", \"help\": \"\" }"; - - public const string InvalidCreateFolderValue = "{ \"message: \"Missing folderName and FolderPath parameters\", \"help\": \"\" }"; - public const string InvalidfolderNameValue = "{ \"message: \"Missing folderName parameters\", \"help\": \"\" }"; - public const string InvalidFolderPathValue = "{ \"message: \"Missing FolderPath parameters\", \"help\": \"\" }"; - - public const string InvalidCopyFolderValue = "{ \"message: \"Missing folderName and FolderPath parameters\", \"help\": \"\" }"; - public const string InvalidCopysourceFolderPathValue = "{ \"message: \"Missing sourceFolderPath parameters\", \"help\": \"\" }"; - public const string InvalidCopydestinationPathValue = "{ \"message: \"Missing destinationPath parameters\", \"help\": \"\" }"; - - public const string InvalidRenameValue = "{ \"message: \"FilePath and NewFileName both parameters are required\", \"help\": \"\" }"; - public const string InvalidRenameFilePathValue = "{ \"message: \"Missing FilePath parameters\", \"help\": \"\" }"; - public const string InvalidRenameNewFileNameValue = "{ \"message: \"Missing NewFileName parameters\", \"help\": \"\" }"; - public const string InvalidKey = "{ \"message: \"Missing API Key parameters\", \"help\": \"\" }"; - public const string InvalidApiUrl = "{ \"message: \"Missing API URL parameters\", \"help\": \"\" }"; - public const string InvalidPurgeUrl = "{ \"message: \"Missing Purge Request URL parameters\", \"help\": \"\" }"; - } -} diff --git a/Imagekit/GlobalSuppressions.cs b/Imagekit/GlobalSuppressions.cs deleted file mode 100644 index e8ce5786..00000000 --- a/Imagekit/GlobalSuppressions.cs +++ /dev/null @@ -1,49 +0,0 @@ -// -// Copyright (c) PlaceholderCompany. All rights reserved. -// - -using System.Diagnostics.CodeAnalysis; - -[assembly: SuppressMessage("StyleCop.CSharp.DocumentationRules", "SA1600:Elements should be documented", Justification = "not needed", Scope = "member", Target = "~F:Imagekit.Models.DeleteFileVersionRequest.fileId")] -[assembly: SuppressMessage("StyleCop.CSharp.DocumentationRules", "SA1600:Elements should be documented", Justification = "not needed", Scope = "member", Target = "~M:Imagekit.Sdk.RestClient.MoveFile(MoveFileRequest)~ResponseMetaData")] -[assembly: SuppressMessage("StyleCop.CSharp.DocumentationRules", "SA1600:Elements should be documented", Justification = "not needed", Scope = "member", Target = "~M:Imagekit.Imagekit.#ctor(System.String,System.String,System.String,System.String)")] -[assembly: SuppressMessage("StyleCop.CSharp.DocumentationRules", "SA1601:Partial elements should be documented", Justification = "not needed", Scope = "type", Target = "~T:Imagekit.BaseImagekit`1")] -[assembly: SuppressMessage("StyleCop.CSharp.DocumentationRules", "SA1600:Elements should be documented", Justification = "not needed", Scope = "type", Target = "~T:ImagekitSample.Program")] -[assembly: SuppressMessage("StyleCop.CSharp.ReadabilityRules", "SA1117:Parameters should be on same line or separate lines", Justification = "not needed", Scope = "member", Target = "~M:Imagekit.Sdk.RestClient.PurgeCacheAsync(System.String)~System.Threading.Tasks.Task{ResponseMetaData}")] -[assembly: SuppressMessage("StyleCop.CSharp.ReadabilityRules", "SA1117:Parameters should be on same line or separate lines", Justification = "not needed", Scope = "member", Target = "~M:Imagekit.Sdk.RestClient.DeleteFileVersion(Imagekit.Models.DeleteFileVersionRequest)~ResponseMetaData")] -[assembly: SuppressMessage("StyleCop.CSharp.MaintainabilityRules", "SA1402:File may only contain a single type", Justification = "not needed", Scope = "type", Target = "~T:Imagekit.Helper.QueryMaker")] -[assembly: SuppressMessage("StyleCop.CSharp.DocumentationRules", "SA1600:Elements should be documented", Justification = "not needed", Scope = "member", Target = "~M:Imagekit.Sdk.ImagekitClient.GetRemoteFileMetadata(System.String)~ResponseMetaData")] -[assembly: SuppressMessage("StyleCop.CSharp.ReadabilityRules", "SA1117:Parameters should be on same line or separate lines", Justification = "not needed", Scope = "member", Target = "~M:Imagekit.Sdk.RestClient.DeleteFileVersionAsync(Imagekit.Models.DeleteFileVersionRequest)~System.Threading.Tasks.Task{ResponseMetaData}")] -[assembly: SuppressMessage("StyleCop.CSharp.DocumentationRules", "SA1600:Elements should be documented", Justification = "not needed", Scope = "member", Target = "~M:Imagekit.Sdk.RestClient.PurgeStatus(System.String)~ResponseMetaData")] -[assembly: SuppressMessage("StyleCop.CSharp.MaintainabilityRules", "SA1401:Fields should be private", Justification = "not needed", Scope = "member", Target = "~F:Imagekit.BaseImagekit`1.options")] -[assembly: SuppressMessage("StyleCop.CSharp.MaintainabilityRules", "SA1401:Fields should be private", Justification = "not needed", Scope = "member", Target = "~F:Transformation.nestedTransforms")] -[assembly: SuppressMessage("StyleCop.CSharp.MaintainabilityRules", "SA1401:Fields should be private", Justification = "not needed", Scope = "member", Target = "~F:Transformation.transformParams")] -[assembly: SuppressMessage("StyleCop.CSharp.MaintainabilityRules", "SA1401:Fields should be private", Justification = "not needed", Scope = "member", Target = "~F:Url.options")] -[assembly: SuppressMessage("StyleCop.CSharp.OrderingRules", "SA1201:Elements should appear in the correct order", Justification = "not needed", Scope = "member", Target = "~F:Transformation.transformParams")] -[assembly: SuppressMessage("StyleCop.CSharp.OrderingRules", "SA1201:Elements should appear in the correct order", Justification = "not needed", Scope = "member", Target = "~M:Imagekit.Sdk.ImagekitClient.#ctor(System.String,System.String,System.String)")] -[assembly: SuppressMessage("StyleCop.CSharp.OrderingRules", "SA1201:Elements should appear in the correct order", Justification = "not needed", Scope = "member", Target = "~M:Transformation.#ctor")] -[assembly: SuppressMessage("Compiler", "CS0108:Member hides inherited member; missing new keyword", Justification = "not needed", Scope = "member", Target = "~P:Imagekit.Models.Response.ResultMetaData.Raw")] -[assembly: SuppressMessage("CodeQuality", "IDE0051:Remove unused private members", Justification = "not needed", Scope = "member", Target = "~P:ResultCache.Help")] -[assembly: SuppressMessage("Compiler", "CS0108:Member hides inherited member; missing new keyword", Justification = "not needed", Scope = "member", Target = "~P:ResultCache.Raw")] -[assembly: SuppressMessage("CodeQuality", "IDE0051:Remove unused private members", Justification = "not needed", Scope = "member", Target = "~P:ResultCache.Raw")] -[assembly: SuppressMessage("CodeQuality", "IDE0051:Remove unused private members", Justification = "not needed", Scope = "member", Target = "~P:ResultCache.RequestId")] -[assembly: SuppressMessage("CodeQuality", "IDE0051:Remove unused private members", Justification = "not needed", Scope = "member", Target = "~P:ResultCacheStatus.Help")] -[assembly: SuppressMessage("Compiler", "CS0108:Member hides inherited member; missing new keyword", Justification = "not needed", Scope = "member", Target = "~P:ResultCacheStatus.Raw")] -[assembly: SuppressMessage("CodeQuality", "IDE0051:Remove unused private members", Justification = "not needed", Scope = "member", Target = "~P:ResultCacheStatus.Raw")] -[assembly: SuppressMessage("CodeQuality", "IDE0051:Remove unused private members", Justification = "not needed", Scope = "member", Target = "~P:ResultCacheStatus.Status")] -[assembly: SuppressMessage("CodeQuality", "IDE0051:Remove unused private members", Justification = "not needed", Scope = "member", Target = "~P:ResultCustomMetaDataField.Id")] -[assembly: SuppressMessage("CodeQuality", "IDE0051:Remove unused private members", Justification = "not needed", Scope = "member", Target = "~P:ResultCustomMetaDataField.Label")] -[assembly: SuppressMessage("CodeQuality", "IDE0051:Remove unused private members", Justification = "not needed", Scope = "member", Target = "~P:ResultCustomMetaDataField.Message")] -[assembly: SuppressMessage("CodeQuality", "IDE0051:Remove unused private members", Justification = "not needed", Scope = "member", Target = "~P:ResultCustomMetaDataField.Name")] -[assembly: SuppressMessage("CodeQuality", "IDE0051:Remove unused private members", Justification = "not needed", Scope = "member", Target = "~P:ResultCustomMetaDataField.Schema")] -[assembly: SuppressMessage("CodeQuality", "IDE0051:Remove unused private members", Justification = "not needed", Scope = "member", Target = "~P:ResultException.Help")] -[assembly: SuppressMessage("CodeQuality", "IDE0051:Remove unused private members", Justification = "not needed", Scope = "member", Target = "~P:ResultException.Message")] -[assembly: SuppressMessage("Compiler", "CS0108:Member hides inherited member; missing new keyword", Justification = "not needed", Scope = "member", Target = "~P:ResultFileDelete.Raw")] -[assembly: SuppressMessage("Compiler", "CS0108:Member hides inherited member; missing new keyword", Justification = "not needed", Scope = "member", Target = "~P:ResultList.Raw")] -[assembly: SuppressMessage("CodeQuality", "IDE0051:Remove unused private members", Justification = "not needed", Scope = "member", Target = "~P:ResultNoContent.ResponseMetaData")] -[assembly: SuppressMessage("StyleCop.CSharp.OrderingRules", "SA1202:Elements should be ordered by access", Justification = "not needed", Scope = "member", Target = "~M:Imagekit.Helper.GetJsonBody.GetBase64(System.Byte[])~System.String")] -[assembly: SuppressMessage("StyleCop.CSharp.OrderingRules", "SA1202:Elements should be ordered by access", Justification = "not needed", Scope = "member", Target = "~M:Transformation.ToString~System.String")] -[assembly: SuppressMessage("StyleCop.CSharp.ReadabilityRules", "SA1123:Do not place regions within elements", Justification = "not needed", Scope = "member", Target = "~M:ImagekitSample.Program.Main(System.String[])")] -[assembly: SuppressMessage("StyleCop.CSharp.MaintainabilityRules", "SA1400:Access modifier should be declared", Justification = "not needed", Scope = "member", Target = "~M:ImagekitSample.Program.Main(System.String[])")] -[assembly: SuppressMessage("StyleCop.CSharp.DocumentationRules", "SA1649:File name should match first type name", Justification = "not needed", Scope = "type", Target = "~T:Imagekit.Sdk.ImagekitClient")] -[assembly: SuppressMessage("StyleCop.CSharp.OrderingRules", "SA1204:Static elements should appear before instance elements", Justification = "not needed", Scope = "member", Target = "~M:Transformation.ToString(System.Object)~System.String")] diff --git a/Imagekit/Helper/GetJsonBody.cs b/Imagekit/Helper/GetJsonBody.cs deleted file mode 100644 index e7f4667e..00000000 --- a/Imagekit/Helper/GetJsonBody.cs +++ /dev/null @@ -1,423 +0,0 @@ -// -// Copyright (c) PlaceholderCompany. All rights reserved. -// - -namespace Imagekit.Helper -{ - using System; - using System.Collections.Generic; - using System.Diagnostics.CodeAnalysis; - using System.IO; - using System.Runtime.Serialization.Formatters.Binary; - using global::Imagekit.Models; - - [ExcludeFromCodeCoverage] - public static class GetJsonBody - { - public static string CreateCustomMetaDataBody(CustomMetaDataFieldCreateRequest customMetaDataFieldCreateRequest) - { - string body = string.Empty; - if (customMetaDataFieldCreateRequest.schema.isValueRequired) - { - if (customMetaDataFieldCreateRequest.schema.type == "Text") - { - body = @"{" + "\n" + - @" ""name"": " + AddDoubleQuotes(customMetaDataFieldCreateRequest.name) + "," + "\n" + - @" ""label"": " + AddDoubleQuotes(customMetaDataFieldCreateRequest.label) + "," + "\n" + - @" ""schema"": {" + "\n" + - @" ""type"": " + - AddDoubleQuotes(customMetaDataFieldCreateRequest.schema.type.ToString()) + "," + "\n" + - @" ""minLength"": " + - customMetaDataFieldCreateRequest.schema.minLength.ToString() + "," + "\n" + - @" ""maxLength"": " + - customMetaDataFieldCreateRequest.schema.maxLength.ToString() + "," + "\n" + - @" ""isValueRequired"": " + - customMetaDataFieldCreateRequest.schema.isValueRequired.ToString().ToLower() + "," + "\n" + - @" ""defaultValue"": " + - AddDoubleQuotesObject(customMetaDataFieldCreateRequest.schema.defaultValue) + "\n" + - @" }" + "\n" + - @"}"; - } - - if (customMetaDataFieldCreateRequest.schema.type == "Textarea") - { - body = @"{" + "\n" + - @" ""name"": " + AddDoubleQuotes(customMetaDataFieldCreateRequest.name) + "," + "\n" + - @" ""label"": " + AddDoubleQuotes(customMetaDataFieldCreateRequest.label) + "," + "\n" + - @" ""schema"": {" + "\n" + - @" ""type"": " + - AddDoubleQuotes(customMetaDataFieldCreateRequest.schema.type.ToString()) + "," + "\n" + - @" ""minLength"": " + - customMetaDataFieldCreateRequest.schema.minLength.ToString() + "," + "\n" + - @" ""maxLength"": " + - customMetaDataFieldCreateRequest.schema.maxLength.ToString() + "," + "\n" + - @" ""isValueRequired"": " + - customMetaDataFieldCreateRequest.schema.isValueRequired.ToString().ToLower() + "," + "\n" + - @" ""defaultValue"": " + - AddDoubleQuotesObject(customMetaDataFieldCreateRequest.schema.defaultValue) + "\n" + - @" }" + "\n" + - @"}"; - } - - if (customMetaDataFieldCreateRequest.schema.type == "Number") - { - body = @"{" + "\n" + - @" ""name"": " + AddDoubleQuotes(customMetaDataFieldCreateRequest.name) + "," + "\n" + - @" ""label"": " + AddDoubleQuotes(customMetaDataFieldCreateRequest.label) + "," + "\n" + - @" ""schema"": {" + "\n" + - @" ""type"": " + - AddDoubleQuotes(customMetaDataFieldCreateRequest.schema.type.ToString()) + "," + "\n" + - @" ""minValue"": " + - customMetaDataFieldCreateRequest.schema.minValue.ToString() + "," + "\n" + - @" ""maxValue"": " + - customMetaDataFieldCreateRequest.schema.maxValue.ToString() + "," + "\n" + - @" ""isValueRequired"": " + - customMetaDataFieldCreateRequest.schema.isValueRequired.ToString().ToLower() + "," + "\n" + - @" ""defaultValue"": " + - customMetaDataFieldCreateRequest.schema.defaultValue + "\n" + - - @" }" + "\n" + - @"}"; - } - - if (customMetaDataFieldCreateRequest.schema.type == "Date") - { - body = @"{" + "\n" + - @" ""name"": " + AddDoubleQuotes(customMetaDataFieldCreateRequest.name) + "," + "\n" + - @" ""label"": " + AddDoubleQuotes(customMetaDataFieldCreateRequest.label) + "," + "\n" + - @" ""schema"": {" + "\n" + - @" ""type"": " + - AddDoubleQuotes(customMetaDataFieldCreateRequest.schema.type.ToString()) + "," + "\n" + - @" ""minValue"": " + - AddDoubleQuotes(customMetaDataFieldCreateRequest.schema.minValue.ToString()) + "," + "\n" + - @" ""maxValue"": " + - AddDoubleQuotes(customMetaDataFieldCreateRequest.schema.maxValue.ToString()) + "," + "\n" + - @" ""isValueRequired"": " + - customMetaDataFieldCreateRequest.schema.isValueRequired.ToString().ToLower() + "," + "\n" + - @" ""defaultValue"": " + - AddDoubleQuotesObject(customMetaDataFieldCreateRequest.schema.defaultValue) + "\n" + - @" }" + "\n" + - @"}"; - } - - if (customMetaDataFieldCreateRequest.schema.type == "SingleSelect") - { - body = @"{" + "\n" + - @" ""name"": " + AddDoubleQuotes(customMetaDataFieldCreateRequest.name) + "," + "\n" + - @" ""label"": " + AddDoubleQuotes(customMetaDataFieldCreateRequest.label) + "," + "\n" + - @" ""schema"": {" + "\n" + - @" ""type"": " + - AddDoubleQuotes(customMetaDataFieldCreateRequest.schema.type.ToString()) + "," + "\n" + - @" ""selectOptions"": " + - AddBigQuotes(customMetaDataFieldCreateRequest.schema.selectOptions) + "," + "\n" + - @" ""isValueRequired"": " + - customMetaDataFieldCreateRequest.schema.isValueRequired.ToString().ToLower() + "," + "\n" + - @" ""defaultValue"": " + - AddDoubleQuotesObject(customMetaDataFieldCreateRequest.schema.defaultValue) + "\n" + - - @" }" + "\n" + - @"}"; - } - - if (customMetaDataFieldCreateRequest.schema.type == "MultiSelect") - { - body = @"{" + "\n" + - @" ""name"": " + AddDoubleQuotes(customMetaDataFieldCreateRequest.name) + "," + "\n" + - @" ""label"": " + AddDoubleQuotes(customMetaDataFieldCreateRequest.label) + "," + "\n" + - @" ""schema"": {" + "\n" + - @" ""type"": " + - AddDoubleQuotes(customMetaDataFieldCreateRequest.schema.type.ToString()) + "," + "\n" + - @" ""selectOptions"": " + - AddBigQuotes(customMetaDataFieldCreateRequest.schema.selectOptions) + "," + "\n" + - @" ""isValueRequired"": " + - customMetaDataFieldCreateRequest.schema.isValueRequired.ToString().ToLower() + "," + "\n" + - @" ""defaultValue"": " + - customMetaDataFieldCreateRequest.schema.defaultValue + "\n" + - - @" }" + "\n" + - @"}"; - } - } - else - { - if (customMetaDataFieldCreateRequest.schema.type == "Text") - { - body = @"{" + "\n" + - @" ""name"": " + AddDoubleQuotes(customMetaDataFieldCreateRequest.name) + "," + "\n" + - @" ""label"": " + AddDoubleQuotes(customMetaDataFieldCreateRequest.label) + "," + "\n" + - @" ""schema"": {" + "\n" + - @" ""type"": " + - AddDoubleQuotes(customMetaDataFieldCreateRequest.schema.type.ToString()) + "," + "\n" + - @" ""minLength"": " + - customMetaDataFieldCreateRequest.schema.minLength.ToString() + "," + "\n" + - @" ""maxLength"": " + - customMetaDataFieldCreateRequest.schema.maxLength.ToString() + "," + "\n" + - @" ""isValueRequired"": " + - customMetaDataFieldCreateRequest.schema.isValueRequired.ToString().ToLower() + "\n" + - @" }" + "\n" + - @"}"; - } - - if (customMetaDataFieldCreateRequest.schema.type == "Textarea") - { - body = @"{" + "\n" + - @" ""name"": " + AddDoubleQuotes(customMetaDataFieldCreateRequest.name) + "," + "\n" + - @" ""label"": " + AddDoubleQuotes(customMetaDataFieldCreateRequest.label) + "," + "\n" + - @" ""schema"": {" + "\n" + - @" ""type"": " + - AddDoubleQuotes(customMetaDataFieldCreateRequest.schema.type.ToString()) + "," + "\n" + - @" ""minLength"": " + - customMetaDataFieldCreateRequest.schema.minLength.ToString() + "," + "\n" + - @" ""maxLength"": " + - customMetaDataFieldCreateRequest.schema.maxLength.ToString() + "," + "\n" + - @" ""isValueRequired"": " + - customMetaDataFieldCreateRequest.schema.isValueRequired.ToString().ToLower() + "\n" + - - @" }" + "\n" + - @"}"; - } - - if (customMetaDataFieldCreateRequest.schema.type == "Number") - { - body = @"{" + "\n" + - @" ""name"": " + AddDoubleQuotes(customMetaDataFieldCreateRequest.name) + "," + "\n" + - @" ""label"": " + AddDoubleQuotes(customMetaDataFieldCreateRequest.label) + "," + "\n" + - @" ""schema"": {" + "\n" + - @" ""type"": " + - AddDoubleQuotes(customMetaDataFieldCreateRequest.schema.type.ToString()) + "," + "\n" + - @" ""minValue"": " + - customMetaDataFieldCreateRequest.schema.minValue.ToString() + "," + "\n" + - @" ""maxValue"": " + - customMetaDataFieldCreateRequest.schema.maxValue.ToString() + "," + "\n" + - @" ""isValueRequired"": " + - customMetaDataFieldCreateRequest.schema.isValueRequired.ToString().ToLower() + "\n" + - @" }" + "\n" + - @"}"; - } - - if (customMetaDataFieldCreateRequest.schema.type == "Date") - { - body = @"{" + "\n" + - @" ""name"": " + AddDoubleQuotes(customMetaDataFieldCreateRequest.name) + "," + "\n" + - @" ""label"": " + AddDoubleQuotes(customMetaDataFieldCreateRequest.label) + "," + "\n" + - @" ""schema"": {" + "\n" + - @" ""type"": " + - AddDoubleQuotes(customMetaDataFieldCreateRequest.schema.type.ToString()) + "," + "\n" + - @" ""minValue"": " + - AddDoubleQuotes(customMetaDataFieldCreateRequest.schema.minValue.ToString()) + "," + "\n" + - @" ""maxValue"": " + - AddDoubleQuotes(customMetaDataFieldCreateRequest.schema.maxValue.ToString()) + "," + "\n" + - @" ""isValueRequired"": " + - customMetaDataFieldCreateRequest.schema.isValueRequired.ToString().ToLower() + "\n" + - @" }" + "\n" + - @"}"; - } - - if (customMetaDataFieldCreateRequest.schema.type == "SingleSelect" || - customMetaDataFieldCreateRequest.schema.type == "MultiSelect") - { - body = @"{" + "\n" + - @" ""name"": " + AddDoubleQuotes(customMetaDataFieldCreateRequest.name) + "," + "\n" + - @" ""label"": " + AddDoubleQuotes(customMetaDataFieldCreateRequest.label) + "," + "\n" + - @" ""schema"": {" + "\n" + - @" ""type"": " + - AddDoubleQuotes(customMetaDataFieldCreateRequest.schema.type.ToString()) + "," + "\n" + - @" ""selectOptions"": " + - AddBigQuotes(customMetaDataFieldCreateRequest.schema.selectOptions) + "," + "\n" + - @" ""isValueRequired"": " + - customMetaDataFieldCreateRequest.schema.isValueRequired.ToString().ToLower() + "\n" + - @" }" + "\n" + - @"}"; - } - } - - return body; - } - - public static string UpdateCustomMetaDataBody(CustomMetaDataFieldUpdateRequest customMetaDataFieldCreateRequest) - { - string body = string.Empty; - if (customMetaDataFieldCreateRequest.schema.type == "Text") - { - body = @"{" + "\n" + - @" ""schema"": {" + "\n" + - @" ""type"": " + - AddDoubleQuotes(customMetaDataFieldCreateRequest.schema.type.ToString()) + "," + "\n" + - @" ""minLength"": " + - customMetaDataFieldCreateRequest.schema.minLength.ToString() + "," + "\n" + - @" ""maxLength"": " + - customMetaDataFieldCreateRequest.schema.maxLength.ToString() + "\n" + - @" }" + "\n" + - @"}"; - } - - if (customMetaDataFieldCreateRequest.schema.type == "Textarea") - { - body = @"{" + "\n" + - @" ""schema"": {" + "\n" + - @" ""type"": " + - AddDoubleQuotes(customMetaDataFieldCreateRequest.schema.type.ToString()) + "," + "\n" + - @" ""minLength"": " + - customMetaDataFieldCreateRequest.schema.minLength.ToString() + "," + "\n" + - @" ""maxLength"": " + - customMetaDataFieldCreateRequest.schema.maxLength.ToString() + "\n" + - @" }" + "\n" + - @"}"; - } - - if (customMetaDataFieldCreateRequest.schema.type == "Number") - { - body = @"{" + "\n" + - @" ""schema"": {" + "\n" + - @" ""type"": " + - AddDoubleQuotes(customMetaDataFieldCreateRequest.schema.type.ToString()) + "," + "\n" + - @" ""minValue"": " + - customMetaDataFieldCreateRequest.schema.minValue.ToString() + "," + "\n" + - @" ""maxValue"": " + - customMetaDataFieldCreateRequest.schema.maxValue.ToString() + "\n" + - @" }" + "\n" + - @"}"; - } - - if (customMetaDataFieldCreateRequest.schema.type == "Date") - { - body = @"{" + "\n" + - @" ""schema"": {" + "\n" + - @" ""type"": " + - AddDoubleQuotes(customMetaDataFieldCreateRequest.schema.type.ToString()) + "," + "\n" + - @" ""minValue"": " + - customMetaDataFieldCreateRequest.schema.minValue.ToString() + "," + "\n" + - @" ""maxValue"": " + - customMetaDataFieldCreateRequest.schema.maxValue.ToString() + "\n" + - @" }" + "\n" + - @"}"; - } - - if (customMetaDataFieldCreateRequest.schema.type == "SingleSelect") - { - body = @"{" + "\n" + - @" ""schema"": {" + "\n" + - @" ""type"": " + - AddDoubleQuotes(customMetaDataFieldCreateRequest.schema.type.ToString()) + "," + "\n" + - @" ""selectOptions"": " + AddBigQuotes(customMetaDataFieldCreateRequest.schema.selectOptions) + "\n" + - - @" }" + "\n" + - @"}"; - } - - return body; - } - - public static string DeleteFolderBody(DeleteFolderRequest deleteFolderRequest) - { - var body = @"{" + "\n" + - @" ""folderPath"" : " + AddDoubleQuotes(deleteFolderRequest.folderPath) + "\n" + - @"}"; - - return body; - } - - private static string AddDoubleQuotes(this string value) - { - return "\"" + value + "\""; - } - - private static string AddDoubleQuotesObject(this object value) - { - return "\"" + value + "\""; - } - - private static string AddBigQuotes(this string[] value) - { - var joinedNames = "\"" + string.Join("\", \"", value) + "\""; - - return "[" + joinedNames + "]"; - } - - public static string GetBase64(object imageArray) - { - string base64ImageRepresentation = Convert.ToBase64String((byte[])imageArray); - return base64ImageRepresentation; - } - - public static string GetBase64Uri(string imagePath) - { - var uri = new System.Uri(imagePath); - byte[] imageArray = System.IO.File.ReadAllBytes(uri.AbsolutePath); - string base64ImageRepresentation = Convert.ToBase64String(imageArray); - return base64ImageRepresentation; - } - - public static string GetFileRequestBody(GetFileListRequest getFileListRequest) - { - QueryMaker queryMaker = new QueryMaker(); - Dictionary options = new Dictionary(); - - if (getFileListRequest.Sort != null) - { - options.Add("sort", getFileListRequest.Sort); - } - - if (getFileListRequest.Path != null) - { - options.Add("path", getFileListRequest.Path); - } - - if (getFileListRequest.SearchQuery != null) - { - options.Add("searchQuery", getFileListRequest.SearchQuery); - } - - if (getFileListRequest.FileType != null) - { - options.Add("fileType", getFileListRequest.FileType); - } - - if (getFileListRequest.Limit > 0) - { - options.Add("limit", getFileListRequest.Limit.ToString()); - } - - if (getFileListRequest.Skip > 0) - { - options.Add("skip", getFileListRequest.Skip.ToString()); - } - - if (getFileListRequest.Name != null) - { - options.Add("name", getFileListRequest.Name.ToString()); - } - - foreach (KeyValuePair entry in options) - { - queryMaker.Add(string.Format("{0}={1}", entry.Key, entry.Value)); - } - - return queryMaker.Get(); - } - } - - public class QueryMaker - { - private string query; - - public void Add(string q) - { - if (this.query != null) - { - this.query += "&"; - } - else - { - this.query = string.Empty; - } - - this.query += q; - } - - public string Get() - { - return this.query; - } - } -} diff --git a/Imagekit/Helper/ImageKitException.cs b/Imagekit/Helper/ImageKitException.cs deleted file mode 100644 index 48f1e504..00000000 --- a/Imagekit/Helper/ImageKitException.cs +++ /dev/null @@ -1,26 +0,0 @@ -// -// Copyright (c) PlaceholderCompany. All rights reserved. -// - -namespace Imagekit.Helper -{ - using System; - - public class ImagekitException : Exception - { - public ImagekitException() - { - } - - public ImagekitException(string message) - : base(message) - { - throw new Exception(message); - } - - public ImagekitException(string message, Exception inner) - : base(message, inner) - { - } - } -} \ No newline at end of file diff --git a/Imagekit/Helper/ImagekitBase.cs b/Imagekit/Helper/ImagekitBase.cs deleted file mode 100644 index ef673522..00000000 --- a/Imagekit/Helper/ImagekitBase.cs +++ /dev/null @@ -1,83 +0,0 @@ -// -// Copyright (c) PlaceholderCompany. All rights reserved. -// - -namespace Imagekit -{ - using System; - using System.Collections.Generic; - using System.Diagnostics.CodeAnalysis; - using System.Text.RegularExpressions; - - [ExcludeFromCodeCoverage] - public abstract partial class BaseImagekit - where T : BaseImagekit - { - public Dictionary options = new Dictionary(); - - public BaseImagekit(string publicKey, string urlEndpoint, string transformationPosition = "path") - { - if (string.IsNullOrEmpty(publicKey)) - { - throw new ArgumentNullException(nameof(publicKey)); - } - - if (string.IsNullOrEmpty(urlEndpoint)) - { - throw new ArgumentNullException(nameof(urlEndpoint)); - } - - Regex rgx = new Regex("^(path|query)$"); - if (transformationPosition == null || !rgx.IsMatch(transformationPosition)) - { - throw new Exception(Constant.ErrorMessages.InvalidTransformationPosition); - } - - this.Add("publicKey", publicKey); - this.Add("urlEndpoint", urlEndpoint); - this.Add("transformationPosition", transformationPosition); - } - - public string Generate() - { - Transformation transformation = (Transformation)this.options["transformation"]; - string tranformationString = transformation.Generate(); - return new Url(this.options).UrlBuilder(tranformationString); - } - } - - public class ServerImagekit : BaseImagekit - { - public ServerImagekit( - string publicKey, - string privateKey, - string urlEndpoint, - string transformationPosition = "path") - : base(publicKey, urlEndpoint, transformationPosition) - { - if (string.IsNullOrEmpty(privateKey)) - { - throw new ArgumentNullException(nameof(privateKey)); - } - - this.Add("privateKey", privateKey); - } - } - - // Leaving this for backwards compatibility. - // Renaming the class: - // a) solves the issue where Imagekit must always be fully qualified since the name is the same as the assembly - // b) allows for clarification between a server-side imagekit and a client-side imagekit - [Obsolete("Use ServerImagekit")] - public class Imagekit : ServerImagekit - { - public Imagekit( - string publicKey, - string privateKey, - string urlEndpoint, - string transformationPosition = "path") - : base(publicKey, privateKey, urlEndpoint, transformationPosition) - { - } - } -} diff --git a/Imagekit/Helper/ImagekitParams.cs b/Imagekit/Helper/ImagekitParams.cs deleted file mode 100644 index 38b6f937..00000000 --- a/Imagekit/Helper/ImagekitParams.cs +++ /dev/null @@ -1,73 +0,0 @@ -// -// Copyright (c) PlaceholderCompany. All rights reserved. -// - -namespace Imagekit -{ - public partial class BaseImagekit - { - public T Path(string value) - { - return this.Add("path", value); - } - - public T Src(string value) - { - return this.Add("src", value); - } - - public T UrlEndpoint(string value) - { - return this.Add("urlEndpoint", value); - } - - public T Url(Transformation value) - { - return this.Add("transformation", value); - } - - public T QueryParameters(params string[] value) - { - return this.Add("queryParameters", value); - } - - public T TransformationPosition(string value) - { - return this.Add("transformationPosition", value); - } - - public T Signed(bool value = true) - { - return this.Add("signed", value); - } - - public T ExpireSeconds(int value) - { - return this.Add("expireSeconds", value); - } - - /// - /// Add transformation parameter. - /// - /// The name. - /// The value. - public T Add(string key, object value) - { - if (this.options.ContainsKey(key)) - { - this.options[key] = value; - if (key == "transformation") - { - this.options.Remove("path"); - this.options.Remove("src"); - } - } - else - { - this.options.Add(key, value); - } - - return (T)this; - } - } -} diff --git a/Imagekit/Helper/MultipartFormDataModel.cs b/Imagekit/Helper/MultipartFormDataModel.cs deleted file mode 100644 index cb670a75..00000000 --- a/Imagekit/Helper/MultipartFormDataModel.cs +++ /dev/null @@ -1,180 +0,0 @@ -namespace Imagekit.Helper -{ - using System; - using System.Net; - using System.Net.Http; - using System.Net.Http.Headers; - using global::Imagekit.Constant; - using global::Imagekit.Models; - using global::Imagekit.Util; - using Newtonsoft.Json; - using System.Collections.Generic; - - public static class MultipartFormDataModel - { - private static string boundary = UrlHandler.GetBoundaryString; - - public static MultipartFormDataContent Build(FileCreateRequest fileCreateRequest) - { - HttpContent content = new StringContent(string.Empty); - MultipartFormDataContent formdata = new MultipartFormDataContent(boundary); - formdata.Headers.Remove("Content-Type"); - formdata.Headers.TryAddWithoutValidation("Content-Type", "multipart/form-data; boundary=" + boundary); - formdata.Add(new StringContent(fileCreateRequest.fileName), "fileName"); - if (fileCreateRequest.file.GetType().Name == "Byte[]") - { - formdata.Add(new StringContent(GetJsonBody.GetBase64(fileCreateRequest.file)), "file"); - } - else - { - formdata.Add(new StringContent(fileCreateRequest.file.ToString()), "file"); - } - - if (fileCreateRequest.useUniqueFileName) - { - formdata.Add(new StringContent("true"), "useUniqueFileName"); - } - else - { - formdata.Add(new StringContent("false"), "useUniqueFileName"); - } - - if (fileCreateRequest.tags != null) - { - formdata.Add(new StringContent(Utils.ListToString(fileCreateRequest.tags)), "tags"); - } - - if (!string.IsNullOrEmpty(fileCreateRequest.folder)) - { - formdata.Add(new StringContent(fileCreateRequest.folder), "folder"); - } - - if (fileCreateRequest.isPrivateFile) - { - formdata.Add(new StringContent("true"), "isPrivateFile"); - } - - if (!string.IsNullOrEmpty(fileCreateRequest.customCoordinates)) - { - formdata.Add(new StringContent(fileCreateRequest.customCoordinates), "customCoordinates"); - } - - if (fileCreateRequest.responseFields != null) - { - formdata.Add(new StringContent(Utils.ListToString(fileCreateRequest.responseFields)), "responseFields"); - } - - if (fileCreateRequest.overwriteFile) - { - formdata.Add(new StringContent("true"), "overwriteFile"); - } - - if (fileCreateRequest.overwriteAITags) - { - formdata.Add(new StringContent("true"), "overwriteAITags"); - } - - if (fileCreateRequest.overwriteTags) - { - formdata.Add(new StringContent("true"), "overwriteTags"); - } - - if (fileCreateRequest.overwriteCustomMetadata) - { - formdata.Add(new StringContent("false"), "overwriteCustomMetadata"); - } - - if (fileCreateRequest.extensions != null) - { - var myContent = JsonConvert.SerializeObject( - fileCreateRequest.extensions, - new JsonSerializerSettings() - { - NullValueHandling = NullValueHandling.Ignore, - }); - formdata.Add(new StringContent(myContent), "extensions"); - } - - if (fileCreateRequest.webhookUrl != null) - { - formdata.Add(new StringContent(fileCreateRequest.webhookUrl), "webhookUrl"); - } - - if (fileCreateRequest.customMetadata != null) - { - string jsonResult = JsonConvert.SerializeObject(fileCreateRequest.customMetadata); - formdata.Add(new StringContent(jsonResult), "customMetadata"); - } - - if (fileCreateRequest.transformation != null) - { - string jsonResult = JsonConvert.SerializeObject(fileCreateRequest.transformation); - formdata.Add(new StringContent(jsonResult), "transformation"); - } - - if (fileCreateRequest.checks != null) - { - formdata.Add(new StringContent(fileCreateRequest.checks), "checks"); - } - - if (fileCreateRequest.isPublished.HasValue) - { - formdata.Add(new StringContent(fileCreateRequest.isPublished.Value.ToString().ToLower()), "isPublished"); - } - - return formdata; - } - - public static MultipartFormDataContent BuildUpdateFile(FileUpdateRequest fileCreateRequest) - { - MultipartFormDataContent formdata = new MultipartFormDataContent(boundary); - formdata.Headers.Remove("Content-Type"); - formdata.Headers.TryAddWithoutValidation("Content-Type", "multipart/form-data; boundary=" + boundary); - - if (fileCreateRequest.tags != null) - { - formdata.Add(new StringContent(Utils.ListToString(fileCreateRequest.tags)), "tags"); - } - - if (fileCreateRequest.removeAITags != null) - { - formdata.Add(new StringContent(Utils.ListToString(fileCreateRequest.removeAITags)), "removeAITags"); - } - - if (!string.IsNullOrEmpty(fileCreateRequest.customCoordinates)) - { - formdata.Add(new StringContent(fileCreateRequest.customCoordinates), "customCoordinates"); - } - - if (fileCreateRequest.extensions != null) - { - var myContent = JsonConvert.SerializeObject( - fileCreateRequest.extensions, - new JsonSerializerSettings() - { - NullValueHandling = NullValueHandling.Ignore, - }); - formdata.Add(new StringContent(myContent), "extensions"); - } - - if (fileCreateRequest.webhookUrl != null) - { - formdata.Add(new StringContent(fileCreateRequest.webhookUrl), "webhookUrl"); - } - - if (fileCreateRequest.customMetadata != null) - { - string jSONresult = JsonConvert.SerializeObject(fileCreateRequest.customMetadata); - formdata.Add(new StringContent(jSONresult), "customMetadata"); - } - - if (fileCreateRequest.publish != null) - { - string jSONresult = JsonConvert.SerializeObject(fileCreateRequest.publish); - formdata.Add(new StringContent(jSONresult), "publish"); - } - - return formdata; - } - } -} diff --git a/Imagekit/Helper/Transformation.cs b/Imagekit/Helper/Transformation.cs deleted file mode 100644 index cc5fa234..00000000 --- a/Imagekit/Helper/Transformation.cs +++ /dev/null @@ -1,281 +0,0 @@ -// -// Copyright (c) PlaceholderCompany. All rights reserved. -// - -using System; -using System.Collections.Generic; -using System.Globalization; -using System.Linq; - -public partial class Transformation -{ - public const string KeyNameRegex = "^\\$[a-zA-Z][a-zA-Z0-9]*$"; - public const string ChainTransformDelimiter = ":"; - public const string TransformDelimiter = ","; - public const string TransformKeyValueDelimiter = "-"; - - /// - /// Initializes a new instance of the class. - /// - /// - /// - public Transformation(Dictionary transformParams) - { - foreach (var key in transformParams.Keys) - { - transformParams.Add(key, transformParams[key]); - } - } - - /// - /// Initializes a new instance of the class. - /// Creates transformation object initialized with array of transformation parameters. - /// - /// List of transformation parameters represented as pairs 'name=value'. - public Transformation(params string[] transformParams) - { - foreach (var pair in transformParams) - { - string[] splittedPair = pair.Split('='); - if (splittedPair.Length != 2) - { - throw new Exception(string.Format("Couldn't parse '{0}'!", pair)); - } - - this.Add(splittedPair[0], splittedPair[1]); - } - } - - /// - /// Add transformation parameter. - /// - /// The name. - /// The value. - public Transformation Add(string key, object value) - { - if (this.transformParams.ContainsKey(key)) - { - this.transformParams[key] = value; - } - else - { - this.transformParams.Add(key, value); - } - - return this; - } - - /// - /// Initializes a new instance of the class. - /// Creates empty transformation object. - /// - public Transformation() - { - } - - /// - /// A dictionary of transformation parameters. - /// - protected Dictionary transformParams = new Dictionary(); - - /// - /// A list of nested transformations. - /// - protected List nestedTransforms = new List(); - - /// - /// Initializes a new instance of the class. - /// Creates transformation object chained with other transformations. - /// - /// List of transformations to chain with. - public Transformation(List transforms) - { - if (transforms != null) - { - this.nestedTransforms = transforms; - } - } - - /// - /// Initializes a new instance of the class. - /// - /// - /// - public Transformation(Dictionary[] dictionary) - { - for (int i = 0; i < dictionary.Length; i++) - { - if (i == dictionary.Length - 1) - { - this.transformParams = dictionary[i]; - } - else - { - this.nestedTransforms.Add(new Transformation(dictionary[i])); - } - } - } - - /// - /// Get the transformation parameters dictionary. - /// - public Dictionary Params - { - get { return this.transformParams; } - } - - /// - /// Get list of nested transformations. - /// - public List NestedTransforms - { - get { return this.nestedTransforms; } - } - - /// - /// Chain transformation. - /// - public Transformation Chain() - { - Transformation nested = this.Clone(); - nested.nestedTransforms = null; - this.nestedTransforms.Add(nested); - this.transformParams = new Dictionary(); - Transformation transform = new Transformation(this.nestedTransforms); - return transform; - } - - /// - /// Get a deep cloned copy of this transformation. - /// - /// A deep cloned copy of this transformation. - public Transformation Clone() - { - Transformation t = (Transformation)this.MemberwiseClone(); - - t.transformParams = new Dictionary(); - - foreach (var key in this.transformParams.Keys) - { - var value = this.transformParams[key]; - - if (value is Array) - { - t.Add(key, ((Array)value).Clone()); - } - else if (value is string || value is ValueType) - { - t.Add(key, value); - } - else if (value is Dictionary) - { - t.Add(key, new Dictionary((Dictionary)value)); - } - else - { - throw new Exception(string.Format("Couldn't clone parameter '{0}'!", key)); - } - } - - if (this.nestedTransforms != null) - { - t.nestedTransforms = new List(); - foreach (var nestedTransform in this.nestedTransforms) - { - t.nestedTransforms.Add(nestedTransform.Clone()); - } - } - - return t; - } - - /// - /// Get this transformation represented as string. - /// - /// The transformation represented as string. - public string Generate() - { - List parts = new List(this.nestedTransforms.Select(t => t.GetTrans()).ToList()); - - var thisTransform = this.GetTrans(); - if (!string.IsNullOrEmpty(thisTransform)) - { - parts.Add(thisTransform); - } - - return string.Join(ChainTransformDelimiter, parts.ToArray()); - } - - public string GetTrans() - { - List transformations = new List(); - List varParams = new List(); - - foreach (var key in this.transformParams.Keys) - { - string val = this.GetString(this.transformParams, key); - if (string.IsNullOrEmpty(val)) - { - varParams.Add($"{key}"); - } - else - { - if (key == "oi" || key == "di") - { - val = val.TrimStart('/').TrimEnd('/'); - val = val.Replace("/", "@@"); - } - - varParams.Add($"{key}-{val}"); - } - } - - if (varParams.Count > 0) - { - transformations.Add(string.Join(TransformDelimiter, varParams)); - } - - return string.Join(ChainTransformDelimiter, transformations.ToArray()); - } - - private string GetString(Dictionary options, string key) - { - if (options.ContainsKey(key)) - { - return ToString(options[key]); - } - else - { - return null; - } - } - - private static string ToString(object obj) - { - if (obj == null) - { - return null; - } - - if (obj is string) - { - return obj.ToString(); - } - - if (obj is float || obj is double) - { - return string.Format(CultureInfo.InvariantCulture, "{0:0.0#}", obj); - } - - return string.Format(CultureInfo.InvariantCulture, "{0}", obj); - } - - /// - /// Get this transformation represented as string. - /// - /// The transformation represented as string. - public override string ToString() - { - return this.Generate(); - } -} diff --git a/Imagekit/Helper/TransformationTypes.cs b/Imagekit/Helper/TransformationTypes.cs deleted file mode 100644 index bd796928..00000000 --- a/Imagekit/Helper/TransformationTypes.cs +++ /dev/null @@ -1,268 +0,0 @@ -// -// Copyright (c) PlaceholderCompany. All rights reserved. -// - -using System; -using System.Diagnostics.CodeAnalysis; - -[ExcludeFromCodeCoverage] -public partial class Transformation -{ - /// Width of a transformed image - /// - public Transformation Width(int value) - { - return this.Add("w", value); - } - - /// Height of a transformed image - /// - public Transformation Height(int value) - { - return this.Add("h", value); - } - - /// Aspect Ratio of a transformed image - /// - public Transformation AspectRatio(string value) - { - return this.Add("ar", value); - } - - /// - /// JPG compression quality. 1 is the lowest quality and 100 is the highest. The default is the - /// original image's quality or 80% if not available. - /// - /// - public Transformation Quality(int value) - { - return this.Add("q", value); - } - - /// Crop Transformation. - /// - public Transformation Crop(string value) - { - return this.Add("c", value); - } - - /// Crop Mode - /// - public Transformation CropMode(string value) - { - return this.Add("cm", value); - } - - /// - /// - public Transformation X(int value) - { - return this.Add("x", this.ConvertCoordinateParam(value)); - } - - /// - /// - public Transformation Y(int value) - { - return this.Add("y", this.ConvertCoordinateParam(value)); - } - - /// - /// - public Transformation Focus(string value) - { - return this.Add("fo", value); - } - - /// - /// - public Transformation Format(string value) - { - return this.Add("f", value); - } - - /// - /// - public Transformation Radius(object value) - { - return this.Add("r", value); - } - - /// - /// - public Transformation Background(string value) - { - return this.Add("bg", value); - } - - /// - /// - public Transformation Border(string value) - { - return this.Add("b", value); - } - - /// - /// - public Transformation Rotation(object value) - { - return this.Add("rt", value); - } - - /// - /// - public Transformation Rotate(object value) - { - return this.Add("rt", value); - } - - /// - /// - public Transformation Blur(int value) - { - return this.Add("bl", value); - } - - /// Add named transformation. - /// named transformation. - public Transformation Named(string value) - { - return this.Add("n", value); - } - - /// - /// - public Transformation Progressive(bool value) - { - return this.Add("pr", value.ToString().ToLower()); - } - - /// - /// - public Transformation Lossless(bool value) - { - return this.Add("lo", value.ToString().ToLower()); - } - - /// - /// - public Transformation Trim(int value) - { - return this.Add("t", value); - } - - /// - /// - public Transformation Metadata(bool value) - { - return this.Add("md", value.ToString().ToLower()); - } - - /// - /// - public Transformation ColorProfile(bool value) - { - return this.Add("cp", value.ToString().ToLower()); - } - - /// - /// - public Transformation DefaultImage(string value) - { - return this.Add("di", value); - } - - /// - /// - public Transformation Dpr(object value) - { - return this.Add("dpr", value); - } - - /// - public Transformation EffectSharpen() - { - return this.Add("e-sharpen", string.Empty); - } - - /// - /// - public Transformation EffectSharpen(int value) - { - return this.Add("e-sharpen", value); - } - - /// - /// - public Transformation EffectUsm(string value) - { - return this.Add("e-usm", value); - } - - /// - public Transformation EffectContrast() - { - return this.Add("e-contrast", string.Empty); - } - - /// - /// - public Transformation EffectContrast(object value) - { - return this.Add("e-contrast", value.ToString().ToLower()); - } - - /// - public Transformation EffectGray() - { - return this.Add("e-grayscale", "true"); - } - - /// - public Transformation EffectShadow() - { - return this.Add("e-shadow", string.Empty); - } - - /// - /// - public Transformation EffectShadow(string value) - { - return this.Add("e-shadow", value); - } - - /// - public Transformation EffectGradient() - { - return this.Add("e-gradient", string.Empty); - } - - /// - /// - public Transformation EffectGradient(string value) - { - return this.Add("e-gradient", value); - } - - /// - public Transformation Original() - { - return this.Add("orig", "true"); - } - - /// - /// Pass an raw transformation string (including chained transformations) - /// - /// A raw transformation string. - public Transformation Raw(string value) - { - return this.Add(value, string.Empty); - } - - private string ConvertCoordinateParam(int paramValue) - { - return paramValue < 0 - ? $"N{Math.Abs(paramValue)}" - : $"{paramValue}"; - } -} diff --git a/Imagekit/Helper/Url.cs b/Imagekit/Helper/Url.cs deleted file mode 100644 index fbf7b154..00000000 --- a/Imagekit/Helper/Url.cs +++ /dev/null @@ -1,184 +0,0 @@ -// -// Copyright (c) PlaceholderCompany. All rights reserved. -// - -using System; -using System.Collections.Generic; -using System.Diagnostics.CodeAnalysis; -using System.Text; -using System.Text.RegularExpressions; -using global::Imagekit.Util; - -[ExcludeFromCodeCoverage] -public class Url -{ - public Dictionary options = new Dictionary(); - - private bool isSrcParameterUsedForUrl; - private Uri parsedUrl; - private Uri parsedHost; - - public Url(Dictionary client) - { - this.options = client; - } - - public string UrlBuilder(string transformationString) - { - Dictionary urlObject = new Dictionary(); - - if (this.options.ContainsKey("path") && this.options.ContainsKey("src")) - { - throw new Exception("Either path or src is required."); - } - else if (this.options.ContainsKey("path")) - { - string path = this.AddLeadingSlash((string)this.options["path"]); - this.parsedUrl = new Uri((string)this.options["urlEndpoint"] + path); - this.parsedHost = new Uri((string)this.options["urlEndpoint"]); - urlObject.Add("protocol", this.parsedHost.Scheme); - urlObject.Add("host", this.options["urlEndpoint"].ToString().Replace(this.parsedHost.Scheme + "://", string.Empty)); - urlObject.Add("pathname", path.Split('?')[0]); - } - else if (this.options.ContainsKey("src")) - { - this.parsedUrl = new Uri((string)this.options["src"]); - this.isSrcParameterUsedForUrl = true; - urlObject.Add("protocol", this.parsedUrl.Scheme); - urlObject.Add("host", this.parsedUrl.Host); - urlObject.Add("pathname", this.parsedUrl.AbsolutePath); - } - else - { - throw new Exception("Either path or src is required."); - } - - // Create correct query parameters - List queryParameters = new List(); - - // Parse query params which are part of the URL - if (this.parsedUrl.Query != null && this.parsedUrl.Query.Length > 1) - { - string[] queryList = this.parsedUrl.Query.Split(new char[] { '&', '?' }); - foreach (var param in queryList) - { - if (string.IsNullOrEmpty(param)) - { - continue; - } - - int index = param.IndexOf('='); - if (index < 0) - { - continue; - } - - queryParameters.Add(this.GetParam(param.Substring(0, index), param.Substring(index + 1))); - } - } - - // parse param passed as queryParameters list - if (this.options.ContainsKey("queryParameters")) - { - foreach (var param in (string[])this.options["queryParameters"]) - { - if (string.IsNullOrEmpty(param)) - { - continue; - } - - int index = param.IndexOf('='); - if (index < 0) - { - throw new Exception(string.Format("Couldn't parse '{0}'!", param)); - } - - queryParameters.Add(this.GetParam(param.Substring(0, index), param.Substring(index + 1))); - } - } - - if (!string.IsNullOrEmpty(transformationString)) - { - if (this.isSrcParameterUsedForUrl || this.AddAsQueryParameter()) - { - queryParameters.Add(this.GetParam(Constants.TransformationParameter, transformationString)); - } - else - { - urlObject["pathname"] = "/tr:" + transformationString + urlObject["pathname"]; - } - } - - urlObject["host"] = this.RemoveTrailingSlash(urlObject["host"]); - - if (queryParameters.Count > 0) - { - urlObject["query"] = string.Join("&", queryParameters); - } - - if (this.options.ContainsKey("signed") && this.options["signed"].Equals(true)) - { - string expiryTimestamp = this.options.ContainsKey("expireSeconds") ? Utils.GetSignatureTimestamp((int)this.options["expireSeconds"]) : Constants.DefaultTimestamp; - if (expiryTimestamp != Constants.DefaultTimestamp) - { - queryParameters.Add(this.GetParam(Constants.TimestampParameter, expiryTimestamp)); - } - - string intermediateUrl = this.GenrateUrl(urlObject); - queryParameters.Add(this.GetParam(Constants.SignatureParameter, this.GetSignature(intermediateUrl, expiryTimestamp))); - - if (queryParameters.Count > 0) - { - urlObject["query"] = string.Join("&", queryParameters); - } - } - - return this.GenrateUrl(urlObject); - } - - public string GenrateUrl(Dictionary urlObject) - { - if (urlObject.ContainsKey("query")) - { - return urlObject["protocol"] + "://" + urlObject["host"] + urlObject["pathname"] + "?" + urlObject["query"]; - } - else - { - return urlObject["protocol"] + "://" + urlObject["host"] + urlObject["pathname"]; - } - } - - public string RemoveTrailingSlash(string str) - { - return str.TrimEnd(new[] { '/' }); - } - - public string AddLeadingSlash(string str) - { - str = str.TrimStart('/'); - str = "/" + str; - return str; - } - - public string GetParam(string key, string param) - { - return $"{Uri.EscapeDataString(key)}={Uri.EscapeDataString(param)}"; - } - - public bool AddAsQueryParameter() - { - if (this.options["transformationPosition"].ToString() == "query") - { - return true; - } - - return false; - } - - public string GetSignature(string url, string expiryTimestamp) - { - var endPoint = this.RemoveTrailingSlash((string)this.options["urlEndpoint"]); - string str = Regex.Replace(url, endPoint + "/", string.Empty) + expiryTimestamp; - return Utils.CalculateSignature(str, Encoding.ASCII.GetBytes((string)this.options["privateKey"])); - } -} diff --git a/Imagekit/Helper/ValidateParamater.cs b/Imagekit/Helper/ValidateParamater.cs deleted file mode 100644 index bbd86776..00000000 --- a/Imagekit/Helper/ValidateParamater.cs +++ /dev/null @@ -1,397 +0,0 @@ -// -// Copyright (c) PlaceholderCompany. All rights reserved. -// - -namespace Imagekit.Helper -{ - using System.Collections.Generic; - using global::Imagekit.Constant; - using global::Imagekit.Models; - - public static class ValidateParamater - { - public static string IsValidateUpload(FileCreateRequest obj) - { - string flag = ErrorMessages.InvalidFileValue; - if (obj == null) - { - flag = ErrorMessages.InvalidFileUploadObjValue; - return flag; - } - - if (string.IsNullOrEmpty(obj.fileName)) - { - flag = ErrorMessages.MissingUploadFilenameParameter; - return flag; - } - - if (obj.file != null) - { - flag = string.Empty; - return flag; - } - - return flag; - } - - public static bool IsValidateParam(string input) - { - bool flag = false; - - if (!string.IsNullOrEmpty(input)) - { - flag = true; - return flag; - } - - return flag; - } - - public static bool IsListCheck(List input) - { - bool flag = false; - - if (input.Count > 0) - { - flag = true; - return flag; - } - - return flag; - } - - public static string IsValidateTagRequest(TagsRequest obj) - { - string flag = string.Empty; - if (obj == null) - { - flag = ErrorMessages.InvalidTagValue; - return flag; - } - - if (obj.tags == null) - { - flag = ErrorMessages.InvalidTagParamValue; - return flag; - } - - if (obj.fileIds == null) - { - flag = ErrorMessages.InvalidFiledParamValue; - return flag; - } - - return flag; - } - - public static string IsValidateAiTagRequest(AITagsRequest obj) - { - string flag = string.Empty; - if (obj == null) - { - flag = ErrorMessages.InvalidTagValue; - return flag; - } - - if (obj.AITags == null) - { - flag = ErrorMessages.InvalidTagParamValue; - return flag; - } - - if (obj.fileIds == null) - { - flag = ErrorMessages.InvalidFiledParamValue; - return flag; - } - - return flag; - } - - public static string IsValidateCustomMetaDataFieldCreateRequest(CustomMetaDataFieldCreateRequest obj) - { - string flag = string.Empty; - if (obj == null) - { - flag = ErrorMessages.InvalidMetaTagValue; - return flag; - } - - if (obj.schema == null) - { - flag = ErrorMessages.InvalidMetaTagSchemaValue; - return flag; - } - - if (string.IsNullOrEmpty(obj.name)) - { - flag = ErrorMessages.InvalidMetaTagNameValue; - return flag; - } - - if (string.IsNullOrEmpty(obj.label)) - { - flag = ErrorMessages.InvalidMetaTagLabelValue; - return flag; - } - - return flag; - } - - public static string IsValidateCustomMetaDataFieldUpdateRequest(CustomMetaDataFieldUpdateRequest obj) - { - string flag = string.Empty; - if (obj == null) - { - flag = ErrorMessages.InvalidMetaTagValue; - return flag; - } - - if (obj.schema == null) - { - flag = ErrorMessages.InvalidMetaTagSchemaValue; - return flag; - } - - if (string.IsNullOrEmpty(obj.Id)) - { - flag = ErrorMessages.InvalidMetaTagIdValue; - return flag; - } - - return flag; - } - - public static string IsValidateDeleteFileVersionRequest(DeleteFileVersionRequest obj) - { - string flag = string.Empty; - if (obj == null) - { - flag = ErrorMessages.InvalidDelVerValue; - return flag; - } - - if (string.IsNullOrEmpty(obj.fileId)) - { - flag = ErrorMessages.InvalidFieldIdDelVerValue; - return flag; - } - - if (string.IsNullOrEmpty(obj.versionId)) - { - flag = ErrorMessages.InvalidversionIdDelVerValue; - return flag; - } - - return flag; - } - - public static string IsValidateCopyRequest(CopyFileRequest obj) - { - string flag = string.Empty; - if (obj == null) - { - flag = ErrorMessages.InvalidMoveValue; - return flag; - } - - if (string.IsNullOrEmpty(obj.sourceFilePath)) - { - flag = ErrorMessages.InvalidSourceValue; - return flag; - } - - if (string.IsNullOrEmpty(obj.destinationPath)) - { - flag = ErrorMessages.InvalidDestinationValue; - return flag; - } - - return flag; - } - - public static string IsValidateMoveRequest(MoveFileRequest obj) - { - string flag = string.Empty; - if (obj == null) - { - flag = ErrorMessages.InvalidMoveValue; - return flag; - } - - if (string.IsNullOrEmpty(obj.sourceFilePath)) - { - flag = ErrorMessages.InvalidSourceValue; - return flag; - } - - if (string.IsNullOrEmpty(obj.destinationPath)) - { - flag = ErrorMessages.InvalidDestinationValue; - return flag; - } - - return flag; - } - - public static string IsValidateRenameRequest(RenameFileRequest obj) - { - string flag = string.Empty; - if (obj == null) - { - flag = ErrorMessages.InvalidRenameValue; - return flag; - } - - if (string.IsNullOrEmpty(obj.filePath)) - { - flag = ErrorMessages.InvalidRenameFilePathValue; - return flag; - } - - if (string.IsNullOrEmpty(obj.newFileName)) - { - flag = ErrorMessages.InvalidRenameNewFileNameValue; - return flag; - } - - return flag; - } - - public static string IsValidateParam(string input, string versonid) - { - string flag = string.Empty; - - if (string.IsNullOrEmpty(input) && string.IsNullOrEmpty(versonid)) - { - flag = ErrorMessages.InvalidDelVerValue; - return flag; - } - - if (string.IsNullOrEmpty(input)) - { - flag = ErrorMessages.InvalidFieldIdDelVerValue; - return flag; - } - - if (string.IsNullOrEmpty(versonid)) - { - flag = ErrorMessages.InvalidversionIdDelVerValue; - return flag; - } - - return flag; - } - - public static string IsValidateFolder(CreateFolderRequest createFolderRequest) - { - string flag = string.Empty; - - if (createFolderRequest == null) - { - flag = ErrorMessages.InvalidCreateFolderValue; - return flag; - } - - if (string.IsNullOrEmpty(createFolderRequest.folderName)) - { - flag = ErrorMessages.InvalidfolderNameValue; - return flag; - } - - if (string.IsNullOrEmpty(createFolderRequest.parentFolderPath)) - { - flag = ErrorMessages.InvalidFolderPathValue; - return flag; - } - - return flag; - } - - public static bool IsValidateDeleteFolder(DeleteFolderRequest createFolderRequest) - { - bool flag = false; - - if (createFolderRequest == null) - { - return flag; - } - - if (!string.IsNullOrEmpty(createFolderRequest.folderPath)) - { - flag = true; - return flag; - } - - return flag; - } - - public static string IsValidateCopyFolder(CopyFolderRequest createFolderRequest) - { - string flag = string.Empty; - - if (createFolderRequest == null) - { - flag = ErrorMessages.InvalidCopyFolderValue; - return flag; - } - - if (string.IsNullOrEmpty(createFolderRequest.sourceFolderPath)) - { - flag = ErrorMessages.InvalidCopysourceFolderPathValue; - return flag; - } - - if (string.IsNullOrEmpty(createFolderRequest.destinationPath)) - { - flag = ErrorMessages.InvalidCopydestinationPathValue; - return flag; - } - - return flag; - } - - public static string IsValidateMoveFolder(MoveFolderRequest createFolderRequest) - { - string flag = string.Empty; - - if (createFolderRequest == null) - { - flag = ErrorMessages.InvalidCopyFolderValue; - return flag; - } - - if (string.IsNullOrEmpty(createFolderRequest.sourceFolderPath)) - { - flag = ErrorMessages.InvalidCopysourceFolderPathValue; - return flag; - } - - if (string.IsNullOrEmpty(createFolderRequest.destinationPath)) - { - flag = ErrorMessages.InvalidCopydestinationPathValue; - return flag; - } - - return flag; - } - - public static string IsValidateUpdateFile(FileUpdateRequest obj) - { - string flag = string.Empty; - if (obj == null) - { - flag = ErrorMessages.FileIdMissing; - return flag; - } - - if (string.IsNullOrEmpty(obj.fileId)) - { - flag = ErrorMessages.FileIdMissing; - return flag; - } - - return flag; - } - } -} diff --git a/Imagekit/IImageKit.cs b/Imagekit/IImageKit.cs deleted file mode 100644 index 9ef4ed94..00000000 --- a/Imagekit/IImageKit.cs +++ /dev/null @@ -1,62 +0,0 @@ -// -// Copyright (c) PlaceholderCompany. All rights reserved. -// - -namespace Imagekit.Sdk -{ - using System.Collections.Generic; - using global::Imagekit.Models; - - public interface IImagekit - { - ResponseMetaData AddTags(TagsRequest tagsRequest); - - ResponseMetaData BulkDeleteFiles(List fileIds); - - ResponseMetaData CopyFile(CopyFileRequest copyFileRequest); - - ResponseMetaData CopyFolder(CopyFolderRequest copyFolderRequest); - - ResponseMetaData CreateCustomMetaDataFields(CustomMetaDataFieldCreateRequest customMetaDataFieldCreateRequest); - - ResponseMetaData CreateFolder(CreateFolderRequest createFolderRequest); - - ResponseMetaData DeleteCustomMetaDataField(string id); - - ResponseMetaData DeleteFile(string fileId); - - ResponseMetaData DeleteFileVersion(DeleteFileVersionRequest deleteFileVersionRequest); - - ResponseMetaData DeleteFolder(DeleteFolderRequest deleteFolderRequest); - - ResponseMetaData GetBulkJobStatus(string jobId); - - ResponseMetaData GetCustomMetaDataFields(bool includeDeleted); - - ResponseMetaData GetFileDetail(string fileId); - - ResponseMetaData GetFileMetadata(string fileId); - - ResponseMetaData GetFileVersionDetails(string fileId, string versionId); - - ResponseMetaData GetFileVersions(string fileId); - - ResponseMetaData GetRemoteFileMetadata(string url); - - ResponseMetaData MoveFile(MoveFileRequest moveFileRequest); - - ResponseMetaData MoveFolder(MoveFolderRequest moveFolderRequest); - - ResponseMetaData RemoveAITags(AITagsRequest aITagsRequest); - - ResponseMetaData RemoveTags(TagsRequest tagsRequest); - - ResponseMetaData RenameFile(RenameFileRequest renameFileRequest); - - ResponseMetaData RestoreFileVersion(string fileId, string versionId); - - ResponseMetaData UpdateCustomMetaDataFields(CustomMetaDataFieldUpdateRequest customMetaDataFieldUpdateRequest); - - ResponseMetaData Upload(FileCreateRequest fileCreateRequest); - } -} \ No newline at end of file diff --git a/Imagekit/Imagekit.cs b/Imagekit/Imagekit.cs deleted file mode 100644 index e877c1f6..00000000 --- a/Imagekit/Imagekit.cs +++ /dev/null @@ -1,367 +0,0 @@ -// -// Copyright (c) PlaceholderCompany. All rights reserved. -// - -namespace Imagekit.Sdk -{ - using System; - using System.Collections.Generic; - using System.Text; - using System.Threading.Tasks; - using global::Imagekit.Models; - using global::Imagekit.Models.Response; - using global::Imagekit.Util; - - public class ImagekitClient : BaseImagekit - { - private readonly RestClient restClient; - private readonly string privateKey; - - public ImagekitClient(string publicKey, string privateKey, string urlEndPoint) - : base(privateKey, urlEndPoint, "path") - { - this.restClient = new RestClient(privateKey, urlEndPoint, new System.Net.Http.HttpClient()); - this.Add("privateKey", privateKey); - this.Add("publicKey", publicKey); - this.privateKey = privateKey; - } - - public Result Upload(FileCreateRequest fileCreateRequest) - { - return (Result)this.restClient.Upload(fileCreateRequest); - } - - public Result UpdateFileDetail(FileUpdateRequest fileUpdateRequest) - { - return (Result)this.restClient.UpdateFileDetail(fileUpdateRequest); - } - - public async Task UpdateFileDetailAsync(FileUpdateRequest fileUpdateRequest) - { - return (Result)await this.restClient.UpdateFileDetailAsync(fileUpdateRequest); - } - - public ResultCache PurgeCache(string url) - { - return (ResultCache)this.restClient.PurgeCache(url); - } - - public async Task PurgeCacheAsync(string url) - { - return (ResultCache)await this.restClient.PurgeCacheAsync(url); - } - - public ResultCacheStatus PurgeStatus(string purgeRequestId) - { - return (ResultCacheStatus)this.restClient.PurgeStatus(purgeRequestId); - } - - public async Task PurgeStatusAsync(string url) - { - return (ResultCacheStatus)await this.restClient.PurgeStatusAsync(url); - } - - public Result GetFileDetail(string url) - { - return (Result)this.restClient.GetFileDetail(url); - } - - public ResultList GetFileListRequest(GetFileListRequest getFileListRequest) - { - return (ResultList)this.restClient.GetFileListRequest(getFileListRequest); - } - - public ResultMetaData GetFileMetadata(string fileId) - { - return (ResultMetaData)this.restClient.GetFileMetaData(fileId); - } - - public ResultMetaData GetRemoteFileMetadata(string url) - { - return (ResultMetaData)this.restClient.GetRemoteFileMetaData(url); - } - - public ResultDelete DeleteFile(string fileId) - { - return (ResultDelete)this.restClient.DeleteFile(fileId); - } - - public ResultFileDelete BulkDeleteFiles(List fileIds) - { - return (ResultFileDelete)this.restClient.BulkDeleteFiles(fileIds); - } - - public ResultTags AddTags(TagsRequest tagsRequest) - { - return (ResultTags)this.restClient.ManageTags(tagsRequest, "addTags"); - } - - public void Clear() - { - throw new NotImplementedException(); - } - - public ResultTags RemoveAITags(AITagsRequest aITagsRequest) - { - return (ResultTags)this.restClient.RemoveAITags(aITagsRequest); - } - - public ResultTags RemoveTags(TagsRequest tagsRequest) - { - return (ResultTags)this.restClient.ManageTags(tagsRequest, "removeTags"); - } - - public ResultCustomMetaDataFieldList GetCustomMetaDataFields(bool includeDeleted) - { - return (ResultCustomMetaDataFieldList)this.restClient.GetCustomMetaDataFields(includeDeleted); - } - - public ResultCustomMetaDataField CreateCustomMetaDataFields( - CustomMetaDataFieldCreateRequest customMetaDataFieldCreateRequest) - { - return (ResultCustomMetaDataField)this.restClient.CreateCustomMetaDataFields(customMetaDataFieldCreateRequest); - } - - public ResultNoContent DeleteCustomMetaDataField(string id) - { - return (ResultNoContent)this.restClient.DeleteCustomMetaDataField(id); - } - - public ResultCustomMetaDataField UpdateCustomMetaDataFields( - CustomMetaDataFieldUpdateRequest customMetaDataFieldUpdateRequest) - { - return (ResultCustomMetaDataField)this.restClient.UpdateCustomMetaDataFields(customMetaDataFieldUpdateRequest); - } - - public ResultNoContent DeleteFileVersion(DeleteFileVersionRequest deleteFileVersionRequest) - { - return (ResultNoContent)this.restClient.DeleteFileVersion(deleteFileVersionRequest); - } - - public ResultNoContent CopyFile(CopyFileRequest copyFileRequest) - { - return (ResultNoContent)this.restClient.CopyFile(copyFileRequest); - } - - public ResultNoContent MoveFile(MoveFileRequest moveFileRequest) - { - return (ResultNoContent)this.restClient.MoveFile(moveFileRequest); - } - - public ResultRenameFile RenameFile(RenameFileRequest renameFileRequest) - { - return (ResultRenameFile)this.restClient.RenameFile(renameFileRequest); - } - - public Result RestoreFileVersion(string fileId, string versionId) - { - return (Result)this.restClient.RestoreFileVersion(fileId, versionId); - } - - public ResultEmptyBlock CreateFolder(CreateFolderRequest createFolderRequest) - { - return (ResultEmptyBlock)this.restClient.CreateFolder(createFolderRequest); - } - - public ResultNoContent DeleteFolder(DeleteFolderRequest deleteFolderRequest) - { - return (ResultNoContent)this.restClient.DeleteFolder(deleteFolderRequest); - } - - public ResultOfFolderActions CopyFolder(CopyFolderRequest copyFolderRequest) - { - return (ResultOfFolderActions)this.restClient.CopyFolder(copyFolderRequest); - } - - public ResultOfFolderActions MoveFolder(MoveFolderRequest moveFolderRequest) - { - return (ResultOfFolderActions)this.restClient.MoveFolder(moveFolderRequest); - } - - public ResultBulkJobStatus GetBulkJobStatus(string jobId) - { - return (ResultBulkJobStatus)this.restClient.GetBulkJobStatus(jobId); - } - - public ResultFileVersions GetFileVersions(string fileId) - { - return (ResultFileVersions)this.restClient.GetFileVersions(fileId); - } - - public ResultFileVersionDetails GetFileVersionDetails(string fileId, string versionId) - { - return (ResultFileVersionDetails)this.restClient.GetFileVersionDetails(fileId, versionId); - } - - public async Task UploadAsync(FileCreateRequest fileCreateRequest) - { - return (Result)await this.restClient.UploadAsync(fileCreateRequest); - } - - public async Task GetFileDetailAsync(string fileId) - { - return await this.restClient.GetFileDetailAsync(fileId); - } - - public async Task GetFileMetadataAsync(string fileId) - { - return (Result)await this.restClient.GetFileMetaDataAsync(fileId); - } - - public async Task GetRemoteFileMetadataAsync(string url) - { - return (ResultMetaData)await this.restClient.GetRemoteFileMetaDataAsync(url); - } - - public async Task DeleteFileAsync(string fileId) - { - return (ResultDelete)await this.restClient.DeleteFileAsync(fileId); - } - - public async Task BulkDeleteFilesAsync(List fileIds) - { - return (ResultFileDelete)await this.restClient.BulkDeleteFilesAsync(fileIds); - } - - public async Task AddTagsAsync(TagsRequest tagsRequest) - { - return (ResultTags)await this.restClient.ManageTagsAsync(tagsRequest, "addTags"); - } - - public async Task RemoveAITagsAsync(AITagsRequest aITagsRequest) - { - return (ResultTags)await this.restClient.RemoveAITagsAsync(aITagsRequest); - } - - public async Task RemoveTagsAsync(TagsRequest tagsRequest) - { - return (ResultTags)await this.restClient.ManageTagsAsync(tagsRequest, "removeTags"); - } - - public async Task GetCustomMetaDataFieldsAsync(bool includeDeleted) - { - return (ResultCustomMetaDataFieldList)await this.restClient.GetCustomMetaDataFieldsAsync(includeDeleted); - } - - public async Task CreateCustomMetaDataFieldsAsync( - CustomMetaDataFieldCreateRequest customMetaDataFieldCreateRequest) - { - return (ResultCustomMetaDataField)await this.restClient.CreateCustomMetaDataFieldsAsync(customMetaDataFieldCreateRequest); - } - - public async Task DeleteCustomMetaDataFieldAsync(string id) - { - return (ResultNoContent)await this.restClient.DeleteCustomMetaDataFieldAsync(id); - } - - public async Task UpdateCustomMetaDataFieldsAsync( - CustomMetaDataFieldUpdateRequest customMetaDataFieldUpdateRequest) - { - return (ResultCustomMetaDataField)await this.restClient.UpdateCustomMetaDataFieldsAsync(customMetaDataFieldUpdateRequest); - } - - public async Task DeleteFileVersionAsync(DeleteFileVersionRequest deleteFileVersionRequest) - { - return (ResultNoContent)await this.restClient.DeleteFileVersionAsync(deleteFileVersionRequest); - } - - public async Task CopyFileAsync(CopyFileRequest copyFileRequest) - { - return (ResultNoContent)await this.restClient.CopyFileAsync(copyFileRequest); - } - - public async Task MoveFileAsync(MoveFileRequest moveFileRequest) - { - return (ResultNoContent)await this.restClient.MoveFileAsync(moveFileRequest); - } - - public async Task RenameFileAsync(RenameFileRequest renameFileRequest) - { - return await this.restClient.RenameFileAsync(renameFileRequest); - } - - public async Task RestoreFileVersionAsync(string fileId, string versionId) - { - return (ResultRenameFile)await this.restClient.RestoreFileVersionAsync(fileId, versionId); - } - - public async Task CreateFolderAsync(CreateFolderRequest createFolderRequest) - { - return (ResultEmptyBlock)await this.restClient.CreateFolderAsync(createFolderRequest); - } - - public async Task DeleteFolderAsync(DeleteFolderRequest deleteFolderRequest) - { - return (ResultNoContent)await this.restClient.DeleteFolderAsync(deleteFolderRequest); - } - - public async Task CopyFolderAsync(CopyFolderRequest copyFolderRequest) - { - return (ResultOfFolderActions)await this.restClient.CopyFolderAsync(copyFolderRequest); - } - - public async Task MoveFolderAsync(MoveFolderRequest moveFolderRequest) - { - return await this.restClient.MoveFolderAsync(moveFolderRequest); - } - - public async Task GetBulkJobStatusAsync(string jobId) - { - return (ResultOfFolderActions)await this.restClient.GetBulkJobStatusAsync(jobId); - } - - public async Task GetFileVersionsAsync(string fileId) - { - return (ResultFileVersions)await this.restClient.GetFileVersionsAsync(fileId); - } - - public async Task GetFileVersionDetailsAsync(string fileId, string versionId) - { - return (ResultFileVersionDetails)await this.restClient.GetFileVersionDetailsAsync(fileId, versionId); - } - - public async Task GetFileListRequestAsync(GetFileListRequest getFileListRequest) - { - return (ResultList)await this.restClient.GetFileListRequestAsync(getFileListRequest); - } - - public int PHashDistance(string firstHex, string secondHex) - { - return Calculation.GetHammingDistance(firstHex, secondHex); - } - - /// - /// Generate Auth params for client-side upload - /// - /// Random Token String - /// Expire time for the token - /// Returns Authparams including token, expiry time and signature. - public AuthParamResponse GetAuthenticationParameters(string token = null, string expire = null) - { - var dEFAULT_TIME_DIFF = 60 * 30; - - AuthParamResponse authParameters = new AuthParamResponse(); - authParameters.token = token; - authParameters.expire = expire; - authParameters.signature = string.Empty; - string defaultExpire = Utils.GetSignatureTimestamp(dEFAULT_TIME_DIFF); - - if (string.IsNullOrEmpty(expire)) - { - expire = defaultExpire; - } - - if (string.IsNullOrEmpty(token)) - { - token = Guid.NewGuid().ToString(); - } - - string signature = Utils.CalculateSignature(token + expire, Encoding.ASCII.GetBytes((string)this.privateKey)); - authParameters.token = token; - authParameters.expire = expire; - authParameters.signature = signature; - - return authParameters; - } - } -} \ No newline at end of file diff --git a/Imagekit/Imagekit.csproj b/Imagekit/Imagekit.csproj deleted file mode 100644 index 013cc8ba..00000000 --- a/Imagekit/Imagekit.csproj +++ /dev/null @@ -1,124 +0,0 @@ - - - - Library - Imagekit - Imagekit - net7.0;net5.0;net6.0;netcoreapp3.1;netstandard2.0 - 8 - © Imagekit Private Limited 2019 - false - - https://github.com/imagekit-developer/imagekit-dotnet/blob/v2.x/LICENSE - Imagekit - https://imagekit.io - Image Resize Crop SmartCrop Rotate Quality Watermark Gif Jpg Jpeg Bitmap PNG Tiff Webp Webm Svg Optimization - Imagekit.io DotNet Library - Library to Integrate Imagekit.io Service. - Imagekit - true - 5.0.0 - true - false - 5.0.0 - git@github.com:imagekit-developer/imagekit-dotnet.git - true - -Fixes - false - - - - - 1701;1702;1591;NU5125;NU5048;NU1504;NU5125;SYSLIB0014; - $(WarningsAsErrors); - - - - 1701;1702;1591;NU5125;NU5048;NU1504;NU5125;SYSLIB0014; - $(WarningsAsErrors); - - - - 1701;1702;1591;NU5125;NU5048;NU1504;NU5125;SYSLIB0014; - $(WarningsAsErrors); - 4 - - - - 1701;1702;1591;NU5125;NU5048;NU1504;NU5125;SYSLIB0014; - $(WarningsAsErrors); - 4 - - - - 1701;1702;1591;NU5125;NU5048;NU1504;NU5125;SYSLIB0014; - $(WarningsAsErrors); - 4 - - - - 1701;1702;1591;NU5125;NU5048;NU1504;NU5125;SYSLIB0014; - $(WarningsAsErrors); - 4 - - - - 1701;1702;1591;NU5125;NU5048;NU1504;NU5125;SYSLIB0014; - $(WarningsAsErrors); - - - - 1701;1702;1591;NU5125;NU5048;NU1504;NU5125;SYSLIB0014; - $(WarningsAsErrors); - - - - 1701;1702;1591;NU5125;NU5048;NU1504;NU5125;SYSLIB0014; - $(WarningsAsErrors); - - - - 1701;1702;1591;NU5125;NU5048;NU1504;NU5125;SYSLIB0014; - $(WarningsAsErrors); - - - - - - - - - - - - all - runtime; build; native; contentfiles; analyzers; buildtransitive - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/Imagekit/Models/AITagsRequest.cs b/Imagekit/Models/AITagsRequest.cs deleted file mode 100644 index 4d1db13d..00000000 --- a/Imagekit/Models/AITagsRequest.cs +++ /dev/null @@ -1,23 +0,0 @@ -// -// Copyright (c) PlaceholderCompany. All rights reserved. -// - -namespace Imagekit -{ - using System.Collections.Generic; - - public class AITagsRequest - { - public List fileIds - { - get; - set; - } - - public List AITags - { - get; - set; - } - } -} \ No newline at end of file diff --git a/Imagekit/Models/AuthParamResponse.cs b/Imagekit/Models/AuthParamResponse.cs deleted file mode 100644 index 67e8f446..00000000 --- a/Imagekit/Models/AuthParamResponse.cs +++ /dev/null @@ -1,18 +0,0 @@ -namespace Imagekit.Models -{ - using System; - using System.Collections.Generic; - using System.Linq; - using System.Text; - using System.Threading.Tasks; - using Newtonsoft.Json; - - public class AuthParamResponse - { - public string token { get; set; } - - public string expire { get; set; } - - public string signature { get; set; } - } -} diff --git a/Imagekit/Models/CopyFileRequest.cs b/Imagekit/Models/CopyFileRequest.cs deleted file mode 100644 index 6dfb8bcf..00000000 --- a/Imagekit/Models/CopyFileRequest.cs +++ /dev/null @@ -1,15 +0,0 @@ -// -// Copyright (c) PlaceholderCompany. All rights reserved. -// - -namespace Imagekit.Models -{ - public class CopyFileRequest - { - public string sourceFilePath { get; set; } - - public string destinationPath { get; set; } - - public bool includeFileVersions { get; set; } - } -} \ No newline at end of file diff --git a/Imagekit/Models/CopyFolderRequest.cs b/Imagekit/Models/CopyFolderRequest.cs deleted file mode 100644 index 1e4b452c..00000000 --- a/Imagekit/Models/CopyFolderRequest.cs +++ /dev/null @@ -1,15 +0,0 @@ -// -// Copyright (c) PlaceholderCompany. All rights reserved. -// - -namespace Imagekit.Models -{ - public class CopyFolderRequest - { - public string sourceFolderPath { get; set; } - - public string destinationPath { get; set; } - - public bool includeFileVersions { get; set; } - } -} \ No newline at end of file diff --git a/Imagekit/Models/CreateFolderRequest.cs b/Imagekit/Models/CreateFolderRequest.cs deleted file mode 100644 index b308c51f..00000000 --- a/Imagekit/Models/CreateFolderRequest.cs +++ /dev/null @@ -1,13 +0,0 @@ -// -// Copyright (c) PlaceholderCompany. All rights reserved. -// - -namespace Imagekit.Models -{ - public class CreateFolderRequest - { - public string folderName { get; set; } - - public string parentFolderPath { get; set; } - } -} \ No newline at end of file diff --git a/Imagekit/Models/CustomMetaDataFieldCreateRequest.cs b/Imagekit/Models/CustomMetaDataFieldCreateRequest.cs deleted file mode 100644 index 7286fe48..00000000 --- a/Imagekit/Models/CustomMetaDataFieldCreateRequest.cs +++ /dev/null @@ -1,22 +0,0 @@ -// -// Copyright (c) PlaceholderCompany. All rights reserved. -// - -namespace Imagekit.Models -{ - public class CustomMetaDataFieldCreateRequest - { - public string name { get; set; } - - public string label { get; set; } - - public CustomMetaDataFieldSchemaObject schema { get; set; } - } - - public class CustomMetaDataFieldUploadRequest - { - public string name { get; set; } - - public CustomMetaDataFieldSchemaObject schema { get; set; } - } -} \ No newline at end of file diff --git a/Imagekit/Models/CustomMetaDataFieldSchemaObject.cs b/Imagekit/Models/CustomMetaDataFieldSchemaObject.cs deleted file mode 100644 index 385a7a02..00000000 --- a/Imagekit/Models/CustomMetaDataFieldSchemaObject.cs +++ /dev/null @@ -1,51 +0,0 @@ -// -// Copyright (c) PlaceholderCompany. All rights reserved. -// - -namespace Imagekit.Models -{ - using System.ComponentModel; - - public class CustomMetaDataFieldSchemaObject - { - public string type { get; set; } - - public string[] selectOptions { get; set; } - - public object defaultValue { get; set; } - - private bool IsValueRequired; - - [DefaultValue(false)] - public bool isValueRequired - { - get - { - return this.IsValueRequired; - } - - set - { - this.IsValueRequired = value; - } - } - - public object minValue { get; set; } - - public object maxValue { get; set; } - - public int minLength { get; set; } - - public int maxLength { get; set; } - - public enum CustomMetaDataTypeEnum - { - Text, - Textarea, - Number, - Date, - SingleSelect, - MultiSelect, - } - } -} \ No newline at end of file diff --git a/Imagekit/Models/CustomMetaDataFieldUpdateRequest.cs b/Imagekit/Models/CustomMetaDataFieldUpdateRequest.cs deleted file mode 100644 index 9d920e1b..00000000 --- a/Imagekit/Models/CustomMetaDataFieldUpdateRequest.cs +++ /dev/null @@ -1,13 +0,0 @@ -// -// Copyright (c) PlaceholderCompany. All rights reserved. -// - -namespace Imagekit.Models -{ - public class CustomMetaDataFieldUpdateRequest - { - public string Id { get; set; } - - public CustomMetaDataFieldSchemaObject schema { get; set; } - } -} \ No newline at end of file diff --git a/Imagekit/Models/DeleteFileVersionRequest.cs b/Imagekit/Models/DeleteFileVersionRequest.cs deleted file mode 100644 index c0aa7d78..00000000 --- a/Imagekit/Models/DeleteFileVersionRequest.cs +++ /dev/null @@ -1,13 +0,0 @@ -// -// Copyright (c) PlaceholderCompany. All rights reserved. -// - -namespace Imagekit.Models -{ - public class DeleteFileVersionRequest - { - public string fileId { get; set; } - - public string versionId { get; set; } - } -} \ No newline at end of file diff --git a/Imagekit/Models/DeleteFolderRequest.cs b/Imagekit/Models/DeleteFolderRequest.cs deleted file mode 100644 index dcfe9cff..00000000 --- a/Imagekit/Models/DeleteFolderRequest.cs +++ /dev/null @@ -1,11 +0,0 @@ -// -// Copyright (c) PlaceholderCompany. All rights reserved. -// - -namespace Imagekit.Models -{ - public class DeleteFolderRequest - { - public string folderPath { get; set; } - } -} \ No newline at end of file diff --git a/Imagekit/Models/ExtensionModel.cs b/Imagekit/Models/ExtensionModel.cs deleted file mode 100644 index 32b5f270..00000000 --- a/Imagekit/Models/ExtensionModel.cs +++ /dev/null @@ -1,32 +0,0 @@ -namespace Imagekit.Models -{ - using System.Collections.Generic; - - public class Extension - { - public string name { get; set; } - } - - public class options - { - public bool add_shadow { get; set; } - - public bool? semitransparency { get; set; } - - public string? bg_color { get; set; } - - public string? bg_image_url { get; set; } - } - - public class BackGroundImage : Extension - { - public options options { get; set; } - } - - public class AutoTags : Extension - { - public int? minConfidence { get; set; } - - public int? maxTags { get; set; } - } -} diff --git a/Imagekit/Models/FileCreateRequest.cs b/Imagekit/Models/FileCreateRequest.cs deleted file mode 100644 index 9787a6bc..00000000 --- a/Imagekit/Models/FileCreateRequest.cs +++ /dev/null @@ -1,47 +0,0 @@ -// -// Copyright (c) PlaceholderCompany. All rights reserved. -// - -using System; -using System.Collections; -using System.Collections.Generic; -using Imagekit.Models; - -public class FileCreateRequest -{ - public string fileName { get; set; } - - public bool useUniqueFileName { get; set; } - - public List tags { get; set; } - - public string folder { get; set; } - - public string customCoordinates { get; set; } - - public List responseFields { get; set; } - - public List extensions { get; set; } - - public string webhookUrl { get; set; } - - public bool overwriteFile { get; set; } - - public bool overwriteAITags { get; set; } - - public bool overwriteTags { get; set; } - - public bool overwriteCustomMetadata { get; set; } - - public Hashtable customMetadata { get; set; } - - public object file { get; set; } - - public bool isPrivateFile { get; set; } - - public UploadTransformation transformation { get; set; } - - public string checks { get; set; } - - public bool? isPublished { get; set; } -} \ No newline at end of file diff --git a/Imagekit/Models/FileUpdateRequest.cs b/Imagekit/Models/FileUpdateRequest.cs deleted file mode 100644 index 9d1bd552..00000000 --- a/Imagekit/Models/FileUpdateRequest.cs +++ /dev/null @@ -1,24 +0,0 @@ -namespace Imagekit.Models -{ - using System.Collections; - using System.Collections.Generic; - - public class FileUpdateRequest - { - public string fileId { get; set; } - - public List removeAITags { get; set; } - - public string webhookUrl { get; set; } - - public List extensions { get; set; } - - public List tags { get; set; } - - public string customCoordinates { get; set; } - - public Hashtable customMetadata { get; set; } - - public PublishStatus publish { get; set; } - } -} diff --git a/Imagekit/Models/GetFileListRequest.cs b/Imagekit/Models/GetFileListRequest.cs deleted file mode 100644 index 67da7164..00000000 --- a/Imagekit/Models/GetFileListRequest.cs +++ /dev/null @@ -1,27 +0,0 @@ -// -// Copyright (c) PlaceholderCompany. All rights reserved. -// - -namespace Imagekit.Models -{ - public class GetFileListRequest - { - public string Name { get; set; } - - public string Type { get; set; } - - public string Sort { get; set; } - - public string Path { get; set; } - - public string SearchQuery { get; set; } - - public string FileType { get; set; } - - public int Limit { get; set; } - - public int Skip { get; set; } - - public string[] Tags { get; set; } - } -} diff --git a/Imagekit/Models/MoveFileRequest.cs b/Imagekit/Models/MoveFileRequest.cs deleted file mode 100644 index 0b247186..00000000 --- a/Imagekit/Models/MoveFileRequest.cs +++ /dev/null @@ -1,10 +0,0 @@ -// -// Copyright (c) PlaceholderCompany. All rights reserved. -// - -public class MoveFileRequest -{ - public string sourceFilePath { get; set; } - - public string destinationPath { get; set; } -} \ No newline at end of file diff --git a/Imagekit/Models/MoveFolderRequest.cs b/Imagekit/Models/MoveFolderRequest.cs deleted file mode 100644 index 8cc3818c..00000000 --- a/Imagekit/Models/MoveFolderRequest.cs +++ /dev/null @@ -1,10 +0,0 @@ -// -// Copyright (c) PlaceholderCompany. All rights reserved. -// - -public class MoveFolderRequest -{ - public string sourceFolderPath { get; set; } - - public string destinationPath { get; set; } -} \ No newline at end of file diff --git a/Imagekit/Models/PublishStatus.cs b/Imagekit/Models/PublishStatus.cs deleted file mode 100644 index be11998e..00000000 --- a/Imagekit/Models/PublishStatus.cs +++ /dev/null @@ -1,11 +0,0 @@ -namespace Imagekit.Models -{ - using System.Collections.Generic; - - public class PublishStatus - { - public bool isPublished { get; set; } - public bool? includeFileVersions { get; set; } - } - -} diff --git a/Imagekit/Models/RenameFileRequest.cs b/Imagekit/Models/RenameFileRequest.cs deleted file mode 100644 index 6585492c..00000000 --- a/Imagekit/Models/RenameFileRequest.cs +++ /dev/null @@ -1,28 +0,0 @@ -// -// Copyright (c) PlaceholderCompany. All rights reserved. -// - -using System.ComponentModel; - -public class RenameFileRequest -{ - public string filePath { get; set; } - - public string newFileName { get; set; } - - private bool IspurgeCache; - - [DefaultValue(false)] - public bool purgeCache - { - get - { - return this.IspurgeCache; - } - - set - { - this.IspurgeCache = value; - } - } -} \ No newline at end of file diff --git a/Imagekit/Models/Response/MetaData.cs b/Imagekit/Models/Response/MetaData.cs deleted file mode 100644 index 2cf6288d..00000000 --- a/Imagekit/Models/Response/MetaData.cs +++ /dev/null @@ -1,30 +0,0 @@ -// -// Copyright (c) PlaceholderCompany. All rights reserved. -// - -namespace Imagekit.Models.Response -{ - using System.Diagnostics.CodeAnalysis; - - [ExcludeFromCodeCoverage] - public class MetaData - { - public float Height { get; set; } - - public float Width { get; set; } - - public float Size { get; set; } - - public string Format { get; set; } - - public bool HasColorProfile { get; set; } - - public float Quality { get; set; } - - public float Density { get; set; } - - public bool HasTransparency { get; set; } - - public string PHash { get; set; } - } -} diff --git a/Imagekit/Models/Response/Result.cs b/Imagekit/Models/Response/Result.cs deleted file mode 100644 index 42d86dac..00000000 --- a/Imagekit/Models/Response/Result.cs +++ /dev/null @@ -1,109 +0,0 @@ -// -// Copyright (c) PlaceholderCompany. All rights reserved. -// - -using System; -using System.Collections.Generic; -using System.Diagnostics.CodeAnalysis; -using Newtonsoft.Json; - -[ExcludeFromCodeCoverage] - -// Root myDeserializedClass = JsonConvert.DeserializeObject(myJsonResponse); -public class Exif -{ -} - -public class ExtensionStatus -{ - [JsonProperty("remove-bg")] - public string RemoveBg { get; set; } - - [JsonProperty("google-auto-tagging")] - public string GoogleAutoTagging { get; set; } -} - -public class Metadata -{ - public int height { get; set; } - - public int width { get; set; } - - public int size { get; set; } - - public string format { get; set; } - - public bool hasColorProfile { get; set; } - - public int quality { get; set; } - - public int density { get; set; } - - public bool hasTransparency { get; set; } - - public Exif exif { get; set; } - - public string pHash { get; set; } -} - -public class Result : ResponseMetaData -{ - public string fileId { get; set; } - - public string name { get; set; } - - public int size { get; set; } - - public VersionInfo versionInfo { get; set; } - - public string filePath { get; set; } - - public string url { get; set; } - - public string fileType { get; set; } - - public int height { get; set; } - - public int width { get; set; } - - public string thumbnailUrl { get; set; } - - public List tags { get; set; } - - public object AITags { get; set; } - - public bool isPrivateFile { get; set; } - - public string customCoordinates { get; set; } - - public Metadata metadata { get; set; } - - public ExtensionStatus extensionStatus { get; set; } -} - -public class VersionInfo -{ - public string id { get; set; } - - public string name { get; set; } -} - -public class CustomMetadata -{ -} - -public class EmbeddedMetadata -{ - public int XResolution { get; set; } - - public int YResolution { get; set; } - - public DateTime DateCreated { get; set; } - - public DateTime DateTimeCreated { get; set; } -} - -public class ResultDelete : ResponseMetaData -{ - public string fileId { get; set; } -} \ No newline at end of file diff --git a/Imagekit/Models/Response/ResultBulkJobStatus.cs b/Imagekit/Models/Response/ResultBulkJobStatus.cs deleted file mode 100644 index f2b34ca2..00000000 --- a/Imagekit/Models/Response/ResultBulkJobStatus.cs +++ /dev/null @@ -1,14 +0,0 @@ -// -// Copyright (c) PlaceholderCompany. All rights reserved. -// -using System.Diagnostics.CodeAnalysis; - -[ExcludeFromCodeCoverage] -public class ResultBulkJobStatus : ResponseMetaData -{ - public string JobId { get; set; } - - public string Type { get; set; } - - public string Status { get; set; } -} \ No newline at end of file diff --git a/Imagekit/Models/Response/ResultCache.cs b/Imagekit/Models/Response/ResultCache.cs deleted file mode 100644 index 23ce9589..00000000 --- a/Imagekit/Models/Response/ResultCache.cs +++ /dev/null @@ -1,13 +0,0 @@ -// -// Copyright (c) PlaceholderCompany. All rights reserved. -// - -using System.Diagnostics.CodeAnalysis; - -[ExcludeFromCodeCoverage] -public class ResultCache : ResponseMetaData -{ - public string Help { get; set; } - - public string RequestId { get; set; } -} \ No newline at end of file diff --git a/Imagekit/Models/Response/ResultCacheStatus.cs b/Imagekit/Models/Response/ResultCacheStatus.cs deleted file mode 100644 index db95f5b9..00000000 --- a/Imagekit/Models/Response/ResultCacheStatus.cs +++ /dev/null @@ -1,13 +0,0 @@ -// -// Copyright (c) PlaceholderCompany. All rights reserved. -// - -using System.Diagnostics.CodeAnalysis; - -[ExcludeFromCodeCoverage] -public class ResultCacheStatus : ResponseMetaData -{ - public string Help { get; set; } - - public string Status { get; set; } -} \ No newline at end of file diff --git a/Imagekit/Models/Response/ResultCustomMetaDataField.cs b/Imagekit/Models/Response/ResultCustomMetaDataField.cs deleted file mode 100644 index 12b807b5..00000000 --- a/Imagekit/Models/Response/ResultCustomMetaDataField.cs +++ /dev/null @@ -1,18 +0,0 @@ -// -// Copyright (c) PlaceholderCompany. All rights reserved. -// - -using System.Diagnostics.CodeAnalysis; -using Imagekit.Models; - -[ExcludeFromCodeCoverage] -public class ResultCustomMetaDataField : ResponseMetaData -{ - public string id { get; set; } - - public string name { get; set; } - - public string label { get; set; } - - public CustomMetaDataFieldSchemaObject Schema { get; set; } -} \ No newline at end of file diff --git a/Imagekit/Models/Response/ResultCustomMetaDataFieldList.cs b/Imagekit/Models/Response/ResultCustomMetaDataFieldList.cs deleted file mode 100644 index 6ad9b067..00000000 --- a/Imagekit/Models/Response/ResultCustomMetaDataFieldList.cs +++ /dev/null @@ -1,12 +0,0 @@ -// -// Copyright (c) PlaceholderCompany. All rights reserved. -// - -using System.Collections.Generic; -using System.Diagnostics.CodeAnalysis; - -[ExcludeFromCodeCoverage] -public class ResultCustomMetaDataFieldList : ResponseMetaData -{ - public List ResultCustomMetaDataFieldList1 { get; set; } = new List(); -} \ No newline at end of file diff --git a/Imagekit/Models/Response/ResultEmptyBlock.cs b/Imagekit/Models/Response/ResultEmptyBlock.cs deleted file mode 100644 index c3e53d5f..00000000 --- a/Imagekit/Models/Response/ResultEmptyBlock.cs +++ /dev/null @@ -1,9 +0,0 @@ -// -// Copyright (c) PlaceholderCompany. All rights reserved. -// -using System.Diagnostics.CodeAnalysis; - -[ExcludeFromCodeCoverage] -public class ResultEmptyBlock : ResponseMetaData -{ -} \ No newline at end of file diff --git a/Imagekit/Models/Response/ResultException.cs b/Imagekit/Models/Response/ResultException.cs deleted file mode 100644 index cd84c4d2..00000000 --- a/Imagekit/Models/Response/ResultException.cs +++ /dev/null @@ -1,12 +0,0 @@ -// -// Copyright (c) PlaceholderCompany. All rights reserved. -// -using System.Diagnostics.CodeAnalysis; - -[ExcludeFromCodeCoverage] -public class ResultException : ResponseMetaData -{ - private string Message { get; set; } - - private string Help { get; set; } -} \ No newline at end of file diff --git a/Imagekit/Models/Response/ResultFileDelete.cs b/Imagekit/Models/Response/ResultFileDelete.cs deleted file mode 100644 index 06da1f29..00000000 --- a/Imagekit/Models/Response/ResultFileDelete.cs +++ /dev/null @@ -1,16 +0,0 @@ -// -// Copyright (c) PlaceholderCompany. All rights reserved. -// - -using System.Collections.Generic; -using System.Diagnostics.CodeAnalysis; - -[ExcludeFromCodeCoverage] -public class ResultFileDelete : ResponseMetaData -{ - public string Help { get; set; } - - public List SuccessfullyDeletedfileIds { get; set; } - - public List MissingfileIds { get; set; } -} \ No newline at end of file diff --git a/Imagekit/Models/Response/ResultFileVersionDetails.cs b/Imagekit/Models/Response/ResultFileVersionDetails.cs deleted file mode 100644 index 4e2108fc..00000000 --- a/Imagekit/Models/Response/ResultFileVersionDetails.cs +++ /dev/null @@ -1,54 +0,0 @@ -// -// Copyright (c) PlaceholderCompany. All rights reserved. -// - -using System; -using System.Collections.Generic; -using System.Diagnostics.CodeAnalysis; -using Newtonsoft.Json.Linq; - -[ExcludeFromCodeCoverage] -public class ResultFileVersionDetails : ResponseMetaData -{ - public string type { get; set; } - - public string name { get; set; } - - public DateTime createdAt { get; set; } - - public DateTime updatedAt { get; set; } - - public string fileId { get; set; } - - public object tags { get; set; } - - public object AITags { get; set; } - - public VersionInfo versionInfo { get; set; } - - public EmbeddedMetadata embeddedMetadata { get; set; } - - public object customCoordinates { get; set; } - - public CustomMetadata customMetadata { get; set; } - - public bool isPrivateFile { get; set; } - - public string url { get; set; } - - public string thumbnail { get; set; } - - public string fileType { get; set; } - - public string filePath { get; set; } - - public int height { get; set; } - - public int width { get; set; } - - public int size { get; set; } - - public bool hasAlpha { get; set; } - - public string mime { get; set; } -} \ No newline at end of file diff --git a/Imagekit/Models/Response/ResultFileVersions.cs b/Imagekit/Models/Response/ResultFileVersions.cs deleted file mode 100644 index 14120fd3..00000000 --- a/Imagekit/Models/Response/ResultFileVersions.cs +++ /dev/null @@ -1,12 +0,0 @@ -// -// Copyright (c) PlaceholderCompany. All rights reserved. -// - -using System.Collections.Generic; -using System.Diagnostics.CodeAnalysis; - -[ExcludeFromCodeCoverage] -public class ResultFileVersions : ResponseMetaData -{ - public List ResultFileVersionDetailsList { get; set; } = new List(); -} \ No newline at end of file diff --git a/Imagekit/Models/Response/ResultList.cs b/Imagekit/Models/Response/ResultList.cs deleted file mode 100644 index 34aeb73c..00000000 --- a/Imagekit/Models/Response/ResultList.cs +++ /dev/null @@ -1,60 +0,0 @@ -// -// Copyright (c) PlaceholderCompany. All rights reserved. -// - -using System; -using System.Collections.Generic; -using System.Diagnostics.CodeAnalysis; - -[ExcludeFromCodeCoverage] -public class ResultList : ResponseMetaData -{ - public string Help { get; set; } - - public List FileList { get; set; } -} - -public class Root -{ - public string type { get; set; } - - public string name { get; set; } - - public DateTime createdAt { get; set; } - - public DateTime updatedAt { get; set; } - - public string fileId { get; set; } - - public List tags { get; set; } - - public object AITags { get; set; } - - public VersionInfo versionInfo { get; set; } - - public EmbeddedMetadata embeddedMetadata { get; set; } - - public string customCoordinates { get; set; } - - public CustomMetadata customMetadata { get; set; } - - public bool isPrivateFile { get; set; } - - public string url { get; set; } - - public string thumbnail { get; set; } - - public string fileType { get; set; } - - public string filePath { get; set; } - - public int height { get; set; } - - public int width { get; set; } - - public int size { get; set; } - - public bool hasAlpha { get; set; } - - public string mime { get; set; } -} diff --git a/Imagekit/Models/Response/ResultMetaData.cs b/Imagekit/Models/Response/ResultMetaData.cs deleted file mode 100644 index a2310f72..00000000 --- a/Imagekit/Models/Response/ResultMetaData.cs +++ /dev/null @@ -1,16 +0,0 @@ -// -// Copyright (c) PlaceholderCompany. All rights reserved. -// - -namespace Imagekit.Models.Response -{ - using System.Diagnostics.CodeAnalysis; - - [ExcludeFromCodeCoverage] - public class ResultMetaData : ResponseMetaData - { - public string Help { get; set; } - - public MetaData Results { get; set; } - } -} diff --git a/Imagekit/Models/Response/ResultNoContent.cs b/Imagekit/Models/Response/ResultNoContent.cs deleted file mode 100644 index 7c5b2a4e..00000000 --- a/Imagekit/Models/Response/ResultNoContent.cs +++ /dev/null @@ -1,10 +0,0 @@ -// -// Copyright (c) PlaceholderCompany. All rights reserved. -// -using System.Diagnostics.CodeAnalysis; - -[ExcludeFromCodeCoverage] -public class ResultNoContent : ResponseMetaData -{ - private ResponseMetaData ResponseMetaData { get; set; } = new ResponseMetaData(); -} \ No newline at end of file diff --git a/Imagekit/Models/Response/ResultOfFolderActions.cs b/Imagekit/Models/Response/ResultOfFolderActions.cs deleted file mode 100644 index be320ce0..00000000 --- a/Imagekit/Models/Response/ResultOfFolderActions.cs +++ /dev/null @@ -1,11 +0,0 @@ -// -// Copyright (c) PlaceholderCompany. All rights reserved. -// - -using System.Diagnostics.CodeAnalysis; - -[ExcludeFromCodeCoverage] -public class ResultOfFolderActions : ResponseMetaData -{ - public string JobId { get; set; } -} \ No newline at end of file diff --git a/Imagekit/Models/Response/ResultRenameFile.cs b/Imagekit/Models/Response/ResultRenameFile.cs deleted file mode 100644 index 4fc88224..00000000 --- a/Imagekit/Models/Response/ResultRenameFile.cs +++ /dev/null @@ -1,10 +0,0 @@ -// -// Copyright (c) PlaceholderCompany. All rights reserved. -// -using System.Diagnostics.CodeAnalysis; - -[ExcludeFromCodeCoverage] -public class ResultRenameFile : ResponseMetaData -{ - public string PurgeRequestId { get; set; } -} \ No newline at end of file diff --git a/Imagekit/Models/Response/ResultTags.cs b/Imagekit/Models/Response/ResultTags.cs deleted file mode 100644 index ef73cdb3..00000000 --- a/Imagekit/Models/Response/ResultTags.cs +++ /dev/null @@ -1,12 +0,0 @@ -// -// Copyright (c) PlaceholderCompany. All rights reserved. -// - -using System.Collections.Generic; -using System.Diagnostics.CodeAnalysis; - -[ExcludeFromCodeCoverage] -public class ResultTags : ResponseMetaData -{ - public List SuccessfullyUpDateTimeTimedfileIds { get; set; } -} \ No newline at end of file diff --git a/Imagekit/Models/ResponseMetaData.cs b/Imagekit/Models/ResponseMetaData.cs deleted file mode 100644 index 7e0f6e31..00000000 --- a/Imagekit/Models/ResponseMetaData.cs +++ /dev/null @@ -1,10 +0,0 @@ -// -// Copyright (c) PlaceholderCompany. All rights reserved. -// - -public class ResponseMetaData -{ - public string Raw { get; set; } - - public int HttpStatusCode { get; set; } -} \ No newline at end of file diff --git a/Imagekit/Models/TagsRequest.cs b/Imagekit/Models/TagsRequest.cs deleted file mode 100644 index 43622ea5..00000000 --- a/Imagekit/Models/TagsRequest.cs +++ /dev/null @@ -1,12 +0,0 @@ -// -// Copyright (c) PlaceholderCompany. All rights reserved. -// - -using System.Collections.Generic; - -public class TagsRequest -{ - public List fileIds { get; set; } - - public List tags { get; set; } -} diff --git a/Imagekit/Models/UploadTransformation.cs b/Imagekit/Models/UploadTransformation.cs deleted file mode 100644 index dadc45ec..00000000 --- a/Imagekit/Models/UploadTransformation.cs +++ /dev/null @@ -1,47 +0,0 @@ -namespace Imagekit.Models -{ - using System.Collections.Generic; - - public class PostTransformation - { - public string type { get; set; } - public string value { get; set; } - } - - public enum Protocol - { - hls, - dash - } - - public class TransformationObject : PostTransformation - { - public string type { get; } = "transformation"; - public string value { get; set; } - } - - public class GifToVideoObject : PostTransformation - { - public string type { get; } = "gif-to-video"; - public string? value { get; set; } - } - public class ThumbnailObject : PostTransformation - { - public string type { get; } = "thumbnail"; - public string? value { get; set; } - } - - public class AbsObject : PostTransformation - { - public string type { get; } = "abs"; - public string value { get; set; } - public Protocol protocol { get; set; } - } - - public class UploadTransformation - { - public string? pre { get; set; } - public List? post { get; set; } - } - -} diff --git a/Imagekit/Properties/AssemblyProperties.cs b/Imagekit/Properties/AssemblyProperties.cs deleted file mode 100644 index 7784aa5c..00000000 --- a/Imagekit/Properties/AssemblyProperties.cs +++ /dev/null @@ -1,5 +0,0 @@ -// -// Copyright (c) PlaceholderCompany. All rights reserved. -// - -[assembly: System.Runtime.CompilerServices.InternalsVisibleToAttribute("Imagekit.UnitTests")] \ No newline at end of file diff --git a/Imagekit/RestClient.cs b/Imagekit/RestClient.cs deleted file mode 100644 index ddced72b..00000000 --- a/Imagekit/RestClient.cs +++ /dev/null @@ -1,1876 +0,0 @@ -// -// Copyright (c) PlaceholderCompany. All rights reserved. -// - -using System; -using System.Collections.Generic; -using System.Net.Http; -using System.Text; -using System.Threading.Tasks; -using global::Imagekit.Constant; -using global::Imagekit.Helper; -using global::Imagekit.Models; -using global::Imagekit.Models.Response; -using global::Imagekit.Util; -using Imagekit; -using Newtonsoft.Json; -using Newtonsoft.Json.Linq; - -internal class RestClient -{ - private readonly string mediaAPIBaseUrl = UrlHandler.MediaAPIBaseUrl; - private readonly string uploadAPIBaseUrl = UrlHandler.UploadAPIBaseUrl; - private readonly HttpClient client; - - public RestClient(string privateKey, string mediaAPIBaseUrl, HttpClient httpClient) - { - if (string.IsNullOrEmpty(privateKey)) - { - throw new Exception(ErrorMessages.InvalidKey); - } - - if (string.IsNullOrEmpty(mediaAPIBaseUrl)) - { - throw new Exception(ErrorMessages.InvalidApiUrl); - } - - this.client = httpClient; - this.client.DefaultRequestHeaders.Add("Authorization", "Basic " + Utils.EncodeTo64(privateKey)); - } - - public ResponseMetaData GetFileListRequest(GetFileListRequest getFileListRequest) - { - try - { - ResultList model = new ResultList(); - string param = GetJsonBody.GetFileRequestBody(getFileListRequest); - string url = string.Format(this.mediaAPIBaseUrl + UrlHandler.GetFileRequest, param); - HttpResponseMessage response = this.client.GetAsync(url).Result; - string res = response.Content.ReadAsStringAsync().Result; - - Utils.PopulateResponseMetadata( - res, - model, - Convert.ToInt32(response.StatusCode), - responseHeaders: null); - return model; - } - catch (Exception ex) - { - throw new ImagekitException(ex.Message); - } - } - - public async Task GetFileListRequestAsync(GetFileListRequest getFileListRequest) - { - try - { - ResultList model = new ResultList(); - string param = GetJsonBody.GetFileRequestBody(getFileListRequest); - string url = string.Format(this.mediaAPIBaseUrl + UrlHandler.GetFileRequest, param); - - HttpResponseMessage response = await this.client.GetAsync(url); - string res = response.Content.ReadAsStringAsync().Result; - - if (res.Length > 2) - { - var token = JToken.Parse(res); - if (token is JArray) - { - model.FileList = JsonConvert.DeserializeObject>(res); - } - else - { - model = JsonConvert.DeserializeObject(res); - } - } - - Utils.PopulateResponseMetadata( - res, - model, - Convert.ToInt32(response.StatusCode), - responseHeaders: null); - return model; - } - catch (Exception ex) - { - throw new ImagekitException(ex.Message); - } - } - - public ResponseMetaData PurgeCache(string path) - { - try - { - ResultCache model = new ResultCache(); - if (!ValidateParamater.IsValidateParam(path)) - { - throw new Exception(ErrorMessages.InvalidUrlValue); - } - - string url = string.Format(this.mediaAPIBaseUrl + UrlHandler.GetPurge); - - object data = new - { - url = path, - }; - var content = JsonConvert.SerializeObject(data); - var stringContent = - new StringContent(content, Encoding.UTF8, - "application/json"); // use MediaTypeNames.Application.Json in Core 3.0+ and Standard 2.1+ - - HttpResponseMessage response = this.client.PostAsync(url, stringContent).Result; - string res = response.Content.ReadAsStringAsync().Result; - model = JsonConvert.DeserializeObject(res); - Utils.PopulateResponseMetadata( - res, - model, - Convert.ToInt32(response.StatusCode), - responseHeaders: null); - return model; - } - catch (Exception ex) - { - throw new ImagekitException(ex.Message); - } - } - - public async Task PurgeCacheAsync(string path) - { - try - { - ResultCache model = new ResultCache(); - if (!ValidateParamater.IsValidateParam(path)) - { - throw new Exception(ErrorMessages.InvalidUrlValue); - } - - string url = string.Format(this.mediaAPIBaseUrl + UrlHandler.GetPurge); - object data = new - { - url = path, - }; - var content = JsonConvert.SerializeObject(data); - var stringContent = - new StringContent(content: content, encoding: Encoding.UTF8, - mediaType: "application/json"); // use MediaTypeNames.Application.Json in Core 3.0+ and Standard 2.1+ - - HttpResponseMessage response = await this.client.PostAsync(url, stringContent); - string res = response.Content.ReadAsStringAsync().Result; - model = JsonConvert.DeserializeObject(res); - Utils.PopulateResponseMetadata( - res, - model, - Convert.ToInt32(response.StatusCode), - responseHeaders: null); - return model; - } - catch (Exception ex) - { - throw new ImagekitException(ex.Message); - } - } - - public ResponseMetaData PurgeStatus(string purgeRequestId) - { - try - { - ResultCacheStatus model = new ResultCacheStatus(); - if (!ValidateParamater.IsValidateParam(purgeRequestId)) - { - throw new Exception(ErrorMessages.InvalidPurgeUrl); - } - - string url = string.Format(this.mediaAPIBaseUrl + UrlHandler.GetPurgeStatus, purgeRequestId); - - HttpResponseMessage response = this.client.GetAsync(url).Result; - string res = response.Content.ReadAsStringAsync().Result; - model = JsonConvert.DeserializeObject(res); - Utils.PopulateResponseMetadata( - res, - model, - Convert.ToInt32(response.StatusCode), - responseHeaders: null); - return model; - } - catch (Exception ex) - { - throw new ImagekitException(ex.Message); - } - } - - public async Task PurgeStatusAsync(string purgeRequestId) - { - try - { - ResultCacheStatus model = new ResultCacheStatus(); - if (!ValidateParamater.IsValidateParam(purgeRequestId)) - { - throw new Exception(ErrorMessages.InvalidPurgeUrl); - } - - string url = string.Format(this.mediaAPIBaseUrl + UrlHandler.GetPurgeStatus, purgeRequestId); - - HttpResponseMessage response = await this.client.GetAsync(url); - string res = response.Content.ReadAsStringAsync().Result; - model = JsonConvert.DeserializeObject(res); - Utils.PopulateResponseMetadata( - res, - model, - Convert.ToInt32(response.StatusCode), - responseHeaders: null); - return model; - } - catch (Exception ex) - { - throw new ImagekitException(ex.Message); - } - } - - public ResponseMetaData GetFileDetail(string fileId) - { - try - { - Result model = new Result(); - if (!ValidateParamater.IsValidateParam(fileId)) - { - throw new Exception(ErrorMessages.FileIdMissing); - } - - string url = string.Format(this.mediaAPIBaseUrl + UrlHandler.GetFileDetails, fileId); - - HttpResponseMessage response = this.client.GetAsync(url).Result; - string res = response.Content.ReadAsStringAsync().Result; - model = JsonConvert.DeserializeObject(res); - Utils.PopulateResponseMetadata( - res, - model, - Convert.ToInt32(response.StatusCode), - responseHeaders: null); - return model; - } - catch (Exception ex) - { - throw new ImagekitException(ex.Message); - } - } - - public async Task GetFileDetailAsync(string fileId) - { - try - { - Result model = new Result(); - if (!ValidateParamater.IsValidateParam(fileId)) - { - throw new Exception(ErrorMessages.FileIdMissing); - } - - Dictionary headers = Utils.GetHeaders(); - string url = string.Format(this.mediaAPIBaseUrl + UrlHandler.GetFileDetails, fileId); - - HttpResponseMessage response = await this.client.GetAsync(url); - string res = response.Content.ReadAsStringAsync().Result; - - model = JsonConvert.DeserializeObject(res); - Utils.PopulateResponseMetadata( - res, - model, - Convert.ToInt32(response.StatusCode), - responseHeaders: null); - return model; - } - catch (Exception ex) - { - throw new ImagekitException(ex.Message); - } - } - - public ResponseMetaData Upload(FileCreateRequest fileCreateRequest) - { - try - { - Result model = new Result(); - string validate = ValidateParamater.IsValidateUpload(fileCreateRequest); - if (!string.IsNullOrEmpty(validate)) - { - throw new Exception(validate); - } - - string url = this.uploadAPIBaseUrl + UrlHandler.UploadFile; - Dictionary headers = Utils.GetHeaders(); - var formdata = MultipartFormDataModel.Build(fileCreateRequest); - HttpResponseMessage response = this.client.PostAsync(url, formdata).Result; - string res = response.Content.ReadAsStringAsync().Result; - model = JsonConvert.DeserializeObject(res); - Utils.PopulateResponseMetadata( - res, - model, - Convert.ToInt32(response.StatusCode), - responseHeaders: null); - return model; - } - catch (Exception ex) - { - throw new ImagekitException(ex.Message); - } - } - - /// - /// - /// - /// - /// A representing the result of the asynchronous operation. - public async Task UploadAsync(FileCreateRequest fileCreateRequest) - { - try - { - Result model = new Result(); - string validate = ValidateParamater.IsValidateUpload(fileCreateRequest); - if (!string.IsNullOrEmpty(validate)) - { - throw new Exception(validate); - } - - string url = this.uploadAPIBaseUrl + UrlHandler.UploadFile; - Dictionary headers = Utils.GetHeaders(); - var formdata = MultipartFormDataModel.Build(fileCreateRequest); - - HttpResponseMessage response = await this.client.PostAsync(url, formdata); - string res = response.Content.ReadAsStringAsync().Result; - - model = JsonConvert.DeserializeObject(res); - Utils.PopulateResponseMetadata( - res, - model, - Convert.ToInt32(response.StatusCode), - responseHeaders: null); - return model; - } - catch (Exception ex) - { - throw new ImagekitException(ex.Message); - } - } - - public ResponseMetaData UpdateFileDetail(FileUpdateRequest fileUpdateRequest) - { - try - { - Result model = new Result(); - string validate = ValidateParamater.IsValidateUpdateFile(fileUpdateRequest); - if (!string.IsNullOrEmpty(validate)) - { - throw new Exception(validate); - } - - string url = string.Format(this.mediaAPIBaseUrl + UrlHandler.UpdateFileRequest, fileUpdateRequest.fileId); - Dictionary headers = Utils.GetHeaders(); - - var content = JsonConvert.SerializeObject(fileUpdateRequest, - new JsonSerializerSettings() - { - NullValueHandling = NullValueHandling.Ignore, - }); - var stringContent = - new StringContent(content, Encoding.UTF8, - mediaType: "application/json"); - var request = new HttpRequestMessage - { - Method = new HttpMethod("PATCH"), - RequestUri = new Uri(url), - Content = stringContent, - }; - - HttpResponseMessage response = this.client.SendAsync(request).Result; - - string res = response.Content.ReadAsStringAsync().Result; - model = JsonConvert.DeserializeObject(res); - Utils.PopulateResponseMetadata( - res, - model, - Convert.ToInt32(response.StatusCode), - responseHeaders: null); - return model; - } - catch (Exception ex) - { - throw new ImagekitException(ex.Message); - } - } - - public async Task UpdateFileDetailAsync(FileUpdateRequest fileUpdateRequest) - { - try - { - Result model = new Result(); - string validate = ValidateParamater.IsValidateUpdateFile(fileUpdateRequest); - if (!string.IsNullOrEmpty(validate)) - { - throw new Exception(validate); - } - - string url = string.Format(this.mediaAPIBaseUrl + UrlHandler.UpdateFileRequest, fileUpdateRequest.fileId); - var content = JsonConvert.SerializeObject(fileUpdateRequest, - new JsonSerializerSettings() - { - NullValueHandling = NullValueHandling.Ignore, - }); - var stringContent = - new StringContent(content, Encoding.UTF8, - mediaType: "application/json"); - var request = new HttpRequestMessage - { - Method = new HttpMethod("PATCH"), - RequestUri = new Uri(url), - Content = stringContent, - }; - - HttpResponseMessage response = await this.client.SendAsync(request); - string res = response.Content.ReadAsStringAsync().Result; - model = JsonConvert.DeserializeObject(res); - Utils.PopulateResponseMetadata( - res, - model, - Convert.ToInt32(response.StatusCode), - responseHeaders: null); - return model; - } - catch (Exception ex) - { - throw new ImagekitException(ex.Message); - } - } - - public ResponseMetaData DeleteFile(string fileId) - { - try - { - ResultDelete model = new ResultDelete(); - if (!ValidateParamater.IsValidateParam(fileId)) - { - throw new Exception(ErrorMessages.FileIdMissing); - } - - string url = string.Format(this.mediaAPIBaseUrl + UrlHandler.DeleteFile, fileId); - - HttpResponseMessage response = this.client.DeleteAsync(url).Result; - string res = response.Content.ReadAsStringAsync().Result; - model.Raw = res; - model.fileId = fileId; - Utils.PopulateResponseMetadata( - res, - model, - Convert.ToInt32(response.StatusCode), - responseHeaders: null); - return model; - } - catch (Exception ex) - { - throw new ImagekitException(ex.Message); - } - } - - /// - /// - /// - /// - /// A representing the result of the asynchronous operation. - public async Task DeleteFileAsync(string fileId) - { - try - { - ResultDelete model = new ResultDelete(); - if (!ValidateParamater.IsValidateParam(fileId)) - { - throw new Exception(ErrorMessages.FileIdMissing); - } - - string url = string.Format(this.mediaAPIBaseUrl + UrlHandler.DeleteFile, fileId); - - HttpResponseMessage response = await this.client.DeleteAsync(url); - string res = response.Content.ReadAsStringAsync().Result; - model.Raw = res; - model.fileId = fileId; - Utils.PopulateResponseMetadata( - res, - model, - Convert.ToInt32(response.StatusCode), - responseHeaders: null); - return model; - } - catch (Exception ex) - { - throw new ImagekitException(ex.Message); - } - } - - public ResponseMetaData BulkDeleteFiles(List fileIds) - { - try - { - ResultFileDelete model = new ResultFileDelete(); - if (!ValidateParamater.IsListCheck(fileIds)) - { - throw new Exception(ErrorMessages.ListFilesInputMissing); - } - - string url = string.Format(this.mediaAPIBaseUrl + UrlHandler.BulkDelete); - - object data = new - { - fileIds = fileIds, - }; - var content = JsonConvert.SerializeObject(data); - var stringContent = - new StringContent(content, Encoding.UTF8, - "application/json"); // use MediaTypeNames.Application.Json in Core 3.0+ and Standard 2.1+ - - HttpResponseMessage response = this.client.PostAsync(url, stringContent).Result; - string res = response.Content.ReadAsStringAsync().Result; - model = JsonConvert.DeserializeObject(res); - Utils.PopulateResponseMetadata( - res, - model, - Convert.ToInt32(response.StatusCode), - responseHeaders: null); - return model; - } - catch (Exception ex) - { - throw new ImagekitException(ex.Message); - } - } - - /// - /// - /// - /// - /// A representing the result of the asynchronous operation. - public async Task BulkDeleteFilesAsync(List fileIds) - { - try - { - ResultFileDelete model = new ResultFileDelete(); - if (!ValidateParamater.IsListCheck(fileIds)) - { - throw new Exception(ErrorMessages.ListFilesInputMissing); - } - - string url = string.Format(this.mediaAPIBaseUrl + UrlHandler.BulkDelete); - - object data = new - { - fileIds = fileIds, - }; - var content = JsonConvert.SerializeObject(data); - var stringContent = - new StringContent(content, Encoding.UTF8, - mediaType: "application/json"); // use MediaTypeNames.Application.Json in Core 3.0+ and Standard 2.1+ - - HttpResponseMessage response = await this.client.PostAsync(url, stringContent); - string res = response.Content.ReadAsStringAsync().Result; - - model = JsonConvert.DeserializeObject(res); - Utils.PopulateResponseMetadata( - res, - model, - Convert.ToInt32(response.StatusCode), - responseHeaders: null); - return model; - } - catch (Exception ex) - { - throw new ImagekitException(ex.Message); - } - } - - public ResponseMetaData GetFileMetaData(string fileId) - { - try - { - ResultMetaData model = new ResultMetaData(); - if (!ValidateParamater.IsValidateParam(fileId)) - { - throw new Exception(ErrorMessages.FileIdMissing); - } - - string url = string.Format(this.mediaAPIBaseUrl + UrlHandler.GetMetaData, fileId); - - HttpResponseMessage response = this.client.GetAsync(url).Result; - string res = response.Content.ReadAsStringAsync().Result; - model = JsonConvert.DeserializeObject(res); - Utils.PopulateResponseMetadata( - res, - model, - Convert.ToInt32(response.StatusCode), - responseHeaders: null); - return model; - } - catch (Exception ex) - { - throw new ImagekitException(ex.Message); - } - } - - public async Task GetFileMetaDataAsync(string fileId) - { - try - { - ResultMetaData model = new ResultMetaData(); - if (!ValidateParamater.IsValidateParam(fileId)) - { - throw new Exception(ErrorMessages.FileIdMissing); - } - - string url = string.Format(this.mediaAPIBaseUrl + UrlHandler.GetMetaData, fileId); - - HttpResponseMessage response = await this.client.GetAsync(url); - string res = response.Content.ReadAsStringAsync().Result; - - model = JsonConvert.DeserializeObject(res); - Utils.PopulateResponseMetadata( - res, - model, - Convert.ToInt32(response.StatusCode), - responseHeaders: null); - return model; - } - catch (Exception ex) - { - throw new ImagekitException(ex.Message); - } - } - - public ResponseMetaData GetRemoteFileMetaData(string url) - { - try - { - ResultMetaData model = new ResultMetaData(); - if (!ValidateParamater.IsValidateParam(url)) - { - throw new Exception(ErrorMessages.InvalidUrlValue); - } - - string apIurl = string.Format(this.mediaAPIBaseUrl + UrlHandler.GetRemoteData, url); - - HttpResponseMessage response = this.client.GetAsync(apIurl).Result; - string res = response.Content.ReadAsStringAsync().Result; - model = JsonConvert.DeserializeObject(res); - Utils.PopulateResponseMetadata( - res, - model, - Convert.ToInt32(response.StatusCode), - responseHeaders: null); - return model; - } - catch (Exception ex) - { - throw new ImagekitException(ex.Message); - } - } - - public async Task GetRemoteFileMetaDataAsync(string url) - { - try - { - ResultMetaData model = new ResultMetaData(); - if (!ValidateParamater.IsValidateParam(url)) - { - throw new Exception(ErrorMessages.InvalidUrlValue); - } - - string apIurl = string.Format(this.mediaAPIBaseUrl + UrlHandler.GetRemoteData, url); - - HttpResponseMessage response = await this.client.GetAsync(apIurl); - string res = response.Content.ReadAsStringAsync().Result; - model = JsonConvert.DeserializeObject(res); - Utils.PopulateResponseMetadata( - res, - model, - Convert.ToInt32(response.StatusCode), - responseHeaders: null); - return model; - } - catch (Exception ex) - { - throw new ImagekitException(ex.Message); - } - } - - public ResponseMetaData ManageTags(TagsRequest tagsRequest, string action) - { - try - { - ResultTags model = new ResultTags(); - var validate = ValidateParamater.IsValidateTagRequest(tagsRequest); - if (!string.IsNullOrEmpty(validate)) - { - throw new Exception(validate); - } - - string url = string.Empty; - - if (action == "addTags") - { - url = this.mediaAPIBaseUrl + UrlHandler.AddTags; - } - else if (action == "removeTags") - { - url = this.mediaAPIBaseUrl + UrlHandler.RemoveTags; - } - - var content = JsonConvert.SerializeObject(tagsRequest); - var stringContent = new StringContent(content, Encoding.UTF8, "application/json"); - HttpResponseMessage response = this.client.PostAsync(url, stringContent).Result; - string res = response.Content.ReadAsStringAsync().Result; - model = JsonConvert.DeserializeObject(res); - Utils.PopulateResponseMetadata( - res, - model, - Convert.ToInt32(response.StatusCode), - responseHeaders: null); - return model; - } - catch (Exception ex) - { - throw new ImagekitException(ex.Message); - } - } - - public async Task ManageTagsAsync(TagsRequest tagsRequest, string action) - { - try - { - ResultTags model = new ResultTags(); - var validate = ValidateParamater.IsValidateTagRequest(tagsRequest); - if (!string.IsNullOrEmpty(validate)) - { - throw new Exception(validate); - } - - string url = string.Empty; - - if (action == "addTags") - { - url = this.uploadAPIBaseUrl + UrlHandler.AddTags; - } - else if (action == "removeTags") - { - url = this.uploadAPIBaseUrl + UrlHandler.RemoveTags; - } - - var content = JsonConvert.SerializeObject(tagsRequest); - var stringContent = new StringContent(content, Encoding.UTF8, "application/json"); - HttpResponseMessage response = await this.client.PostAsync(url, stringContent); - string res = response.Content.ReadAsStringAsync().Result; - model = JsonConvert.DeserializeObject(res); - Utils.PopulateResponseMetadata( - res, - model, - Convert.ToInt32(response.StatusCode), - responseHeaders: null); - return model; - } - catch (Exception ex) - { - throw new ImagekitException(ex.Message); - } - } - - public ResponseMetaData RemoveAITags(AITagsRequest aITagsRequest) - { - try - { - ResultTags model = new ResultTags(); - var validate = ValidateParamater.IsValidateAiTagRequest(aITagsRequest); - if (!string.IsNullOrEmpty(validate)) - { - throw new Exception(validate); - } - - // removeAITags - string url = string.Empty; - - url = this.mediaAPIBaseUrl + UrlHandler.RemoveAITags; - - var content = JsonConvert.SerializeObject(aITagsRequest); - var stringContent = new StringContent(content, Encoding.UTF8, "application/json"); - HttpResponseMessage response = this.client.PostAsync(url, stringContent).Result; - string res = response.Content.ReadAsStringAsync().Result; - - model = JsonConvert.DeserializeObject(res); - Utils.PopulateResponseMetadata( - res, - model, - Convert.ToInt32(response.StatusCode), - responseHeaders: null); - return model; - } - catch (Exception ex) - { - throw new ImagekitException(ex.Message); - } - } - - public async Task RemoveAITagsAsync(AITagsRequest aITagsRequest) - { - try - { - ResultTags model = new ResultTags(); - var validate = ValidateParamater.IsValidateAiTagRequest(aITagsRequest); - if (!string.IsNullOrEmpty(validate)) - { - throw new Exception(validate); - } - - // removeAITags - string url = string.Empty; - - url = this.uploadAPIBaseUrl + UrlHandler.RemoveAITags; - - var content = JsonConvert.SerializeObject(aITagsRequest); - var stringContent = new StringContent(content, Encoding.UTF8, "application/json"); - HttpResponseMessage response = await this.client.PostAsync(url, stringContent); - string res = response.Content.ReadAsStringAsync().Result; - - model = JsonConvert.DeserializeObject(res); - Utils.PopulateResponseMetadata( - res, - model, - Convert.ToInt32(response.StatusCode), - responseHeaders: null); - return model; - } - catch (Exception ex) - { - throw new ImagekitException(ex.Message); - } - } - - public ResponseMetaData GetCustomMetaDataFields(bool? includeDeleted = false) - { - try - { - ResultCustomMetaDataFieldList model = new ResultCustomMetaDataFieldList(); - string url = string.Format(this.mediaAPIBaseUrl + UrlHandler.CustomMetadataFields, includeDeleted); - - HttpResponseMessage response = this.client.GetAsync(url).Result; - string res = response.Content.ReadAsStringAsync().Result; - if (res.Length > 2) - { - var token = JToken.Parse(res); - if (token is JArray) - { - model.ResultCustomMetaDataFieldList1 = JsonConvert.DeserializeObject>(res); - } - else - { - model = JsonConvert.DeserializeObject(res); - } - } - - Utils.PopulateResponseMetadata( - res, - model, - Convert.ToInt32(response.StatusCode), - responseHeaders: null); - return model; - } - catch (Exception ex) - { - throw new ImagekitException(ex.Message); - } - } - - public async Task GetCustomMetaDataFieldsAsync(bool includeDeleted) - { - try - { - ResultCustomMetaDataFieldList model = new ResultCustomMetaDataFieldList(); - string url = string.Format(this.mediaAPIBaseUrl + UrlHandler.CustomMetadataFields, includeDeleted); - - HttpResponseMessage response = await this.client.GetAsync(url); - string res = response.Content.ReadAsStringAsync().Result; - - model = JsonConvert.DeserializeObject(res); - Utils.PopulateResponseMetadata( - res, - model, - Convert.ToInt32(response.StatusCode), - responseHeaders: null); - return model; - } - catch (Exception ex) - { - throw new ImagekitException(ex.Message); - } - } - - public ResponseMetaData CreateCustomMetaDataFields( - CustomMetaDataFieldCreateRequest customMetaDataFieldCreateRequest) - { - try - { - ResultCustomMetaDataField model = new ResultCustomMetaDataField(); - var validate = - ValidateParamater.IsValidateCustomMetaDataFieldCreateRequest(customMetaDataFieldCreateRequest); - if (!string.IsNullOrEmpty(validate)) - { - throw new Exception(validate); - } - - string url = string.Empty; - url = this.mediaAPIBaseUrl + UrlHandler.CreareCustomMetaDataFields; - - string body = GetJsonBody.CreateCustomMetaDataBody(customMetaDataFieldCreateRequest); - var stringContent = new StringContent(body, Encoding.UTF8, "application/json"); - HttpResponseMessage response = this.client.PostAsync(url, stringContent).Result; - string res = response.Content.ReadAsStringAsync().Result; - model = JsonConvert.DeserializeObject(res); - Utils.PopulateResponseMetadata( - res, - model, - Convert.ToInt32(response.StatusCode), - responseHeaders: null); - return model; - } - catch (Exception ex) - { - throw new ImagekitException(ex.Message); - } - } - - public async Task CreateCustomMetaDataFieldsAsync( - CustomMetaDataFieldCreateRequest customMetaDataFieldCreateRequest) - { - try - { - ResultCustomMetaDataField model = new ResultCustomMetaDataField(); - var validate = - ValidateParamater.IsValidateCustomMetaDataFieldCreateRequest(customMetaDataFieldCreateRequest); - if (!string.IsNullOrEmpty(validate)) - { - throw new Exception(validate); - } - - string url = string.Empty; - url = this.mediaAPIBaseUrl + UrlHandler.CreareCustomMetaDataFields; - - string body = GetJsonBody.CreateCustomMetaDataBody(customMetaDataFieldCreateRequest); - var stringContent = new StringContent(body, Encoding.UTF8, "application/json"); - HttpResponseMessage response = await this.client.PostAsync(url, stringContent); - string res = response.Content.ReadAsStringAsync().Result; - - model = JsonConvert.DeserializeObject(res); - Utils.PopulateResponseMetadata( - res, - model, - Convert.ToInt32(response.StatusCode), - responseHeaders: null); - return model; - } - catch (Exception ex) - { - throw new ImagekitException(ex.Message); - } - } - - public ResponseMetaData DeleteCustomMetaDataField(string id) - { - try - { - ResultNoContent model = new ResultNoContent(); - if (!ValidateParamater.IsValidateParam(id)) - { - throw new Exception(ErrorMessages.InvalidfileIdsValue); - } - - string url = string.Format(this.mediaAPIBaseUrl + UrlHandler.DeleteCustomMetaDataFields, id); - - HttpResponseMessage response = this.client.DeleteAsync(url).Result; - string res = response.Content.ReadAsStringAsync().Result; - model = JsonConvert.DeserializeObject(res); - Utils.PopulateResponseMetadata( - res, - model, - Convert.ToInt32(response.StatusCode), - responseHeaders: null); - return model; - } - catch (Exception ex) - { - throw new ImagekitException(ex.Message); - } - } - - public async Task DeleteCustomMetaDataFieldAsync(string id) - { - try - { - ResultNoContent model = new ResultNoContent(); - if (!ValidateParamater.IsValidateParam(id)) - { - throw new Exception(ErrorMessages.InvalidfileIdsValue); - } - - string url = string.Format(this.mediaAPIBaseUrl + UrlHandler.DeleteCustomMetaDataFields, id); - - HttpResponseMessage response = await this.client.DeleteAsync(url); - string res = response.Content.ReadAsStringAsync().Result; - model = JsonConvert.DeserializeObject(res); - Utils.PopulateResponseMetadata( - res, - model, - Convert.ToInt32(response.StatusCode), - responseHeaders: null); - return model; - } - catch (Exception ex) - { - throw new ImagekitException(ex.Message); - } - } - - public ResponseMetaData UpdateCustomMetaDataFields( - CustomMetaDataFieldUpdateRequest customMetaDataFieldUpdateRequest) - { - try - { - ResultCustomMetaDataField model = new ResultCustomMetaDataField(); - var validate = - ValidateParamater.IsValidateCustomMetaDataFieldUpdateRequest(customMetaDataFieldUpdateRequest); - if (!string.IsNullOrEmpty(validate)) - { - throw new Exception(validate); - } - - string url = string.Empty; - url = string.Format( - this.mediaAPIBaseUrl + UrlHandler.UpdateCustomMetadataFields, - customMetaDataFieldUpdateRequest.Id); - string body = GetJsonBody.UpdateCustomMetaDataBody(customMetaDataFieldUpdateRequest); - - var stringContent = - new StringContent(body, Encoding.UTF8, - mediaType: "application/json"); - var request = new HttpRequestMessage - { - Method = new HttpMethod("PATCH"), - RequestUri = new Uri(url), - Content = stringContent, - }; - HttpResponseMessage response = this.client.SendAsync(request).Result; - string res = response.Content.ReadAsStringAsync().Result; - model = JsonConvert.DeserializeObject(res); - Utils.PopulateResponseMetadata( - res, model, - Convert.ToInt32(response.StatusCode), - responseHeaders: null); - return model; - } - catch (Exception ex) - { - throw new ImagekitException(ex.Message); - } - } - - public async Task UpdateCustomMetaDataFieldsAsync( - CustomMetaDataFieldUpdateRequest customMetaDataFieldUpdateRequest) - { - try - { - ResultCustomMetaDataField model = new ResultCustomMetaDataField(); - var validate = - ValidateParamater.IsValidateCustomMetaDataFieldUpdateRequest(customMetaDataFieldUpdateRequest); - if (!string.IsNullOrEmpty(validate)) - { - throw new Exception(validate); - } - - string url = string.Empty; - url = string.Format( - this.mediaAPIBaseUrl + UrlHandler.UpdateCustomMetadataFields, - customMetaDataFieldUpdateRequest.Id); - string body = GetJsonBody.UpdateCustomMetaDataBody(customMetaDataFieldUpdateRequest); - - var stringContent = - new StringContent(body, Encoding.UTF8, - mediaType: "application/json"); - var request = new HttpRequestMessage - { - Method = new HttpMethod("PATCH"), - RequestUri = new Uri(url), - Content = stringContent, - }; - HttpResponseMessage response = await this.client.SendAsync(request); - string res = response.Content.ReadAsStringAsync().Result; - model = JsonConvert.DeserializeObject(res); - Utils.PopulateResponseMetadata( - res, model, - Convert.ToInt32(response.StatusCode), - responseHeaders: null); - return model; - } - catch (Exception ex) - { - throw new ImagekitException(ex.Message); - } - } - - public ResponseMetaData DeleteFileVersion(DeleteFileVersionRequest deleteFileVersionRequest) - { - try - { - ResultNoContent model = new ResultNoContent(); - var validate = ValidateParamater.IsValidateDeleteFileVersionRequest(deleteFileVersionRequest); - if (!string.IsNullOrEmpty(validate)) - { - throw new Exception(validate); - } - - string url = string.Format(this.mediaAPIBaseUrl + UrlHandler.DeleteVesrion, deleteFileVersionRequest.fileId, - deleteFileVersionRequest.versionId); - - HttpResponseMessage response = this.client.DeleteAsync(url).Result; - string res = response.Content.ReadAsStringAsync().Result; - model = JsonConvert.DeserializeObject(res); - - Utils.PopulateResponseMetadata( - res, - model, - Convert.ToInt32(response.StatusCode), - responseHeaders: null); - return model; - } - catch (Exception ex) - { - throw new ImagekitException(ex.Message); - } - } - - public async Task DeleteFileVersionAsync(DeleteFileVersionRequest deleteFileVersionRequest) - { - try - { - ResultNoContent model = new ResultNoContent(); - var validate = ValidateParamater.IsValidateDeleteFileVersionRequest(deleteFileVersionRequest); - if (!string.IsNullOrEmpty(validate)) - { - throw new Exception(validate); - } - - string url = string.Format(this.mediaAPIBaseUrl + UrlHandler.DeleteVesrion, deleteFileVersionRequest.fileId, - deleteFileVersionRequest.versionId); - - HttpResponseMessage response = await this.client.DeleteAsync(url); - string res = response.Content.ReadAsStringAsync().Result; - model = JsonConvert.DeserializeObject(res); - - Utils.PopulateResponseMetadata( - res, - model, - Convert.ToInt32(response.StatusCode), - responseHeaders: null); - return model; - } - catch (Exception ex) - { - throw new ImagekitException(ex.Message); - } - } - - public ResponseMetaData CopyFile(CopyFileRequest copyFileRequest) - { - try - { - ResultNoContent model = new ResultNoContent(); - string validate = ValidateParamater.IsValidateCopyRequest(copyFileRequest); - if (!string.IsNullOrEmpty(validate)) - { - throw new Exception(validate); - } - - string url = string.Empty; - url = string.Format(this.mediaAPIBaseUrl + UrlHandler.CopyFile); - var content = JsonConvert.SerializeObject(copyFileRequest); - var stringContent = new StringContent(content, Encoding.UTF8, "application/json"); - HttpResponseMessage response = this.client.PostAsync(url, stringContent).Result; - string res = response.Content.ReadAsStringAsync().Result; - - model = JsonConvert.DeserializeObject(res); - - Utils.PopulateResponseMetadata( - res, - model, - Convert.ToInt32(response.StatusCode), - responseHeaders: null); - return model; - } - catch (Exception ex) - { - throw new ImagekitException(ex.Message); - } - } - - public async Task CopyFileAsync(CopyFileRequest copyFileRequest) - { - try - { - ResultNoContent model = new ResultNoContent(); - string validate = ValidateParamater.IsValidateCopyRequest(copyFileRequest); - if (!string.IsNullOrEmpty(validate)) - { - throw new Exception(validate); - } - - string url = string.Empty; - url = string.Format(this.mediaAPIBaseUrl + UrlHandler.CopyFile); - var content = JsonConvert.SerializeObject(copyFileRequest); - var stringContent = new StringContent(content, Encoding.UTF8, "application/json"); - HttpResponseMessage response = await this.client.PostAsync(url, stringContent); - string res = response.Content.ReadAsStringAsync().Result; - - model = JsonConvert.DeserializeObject(res); - - Utils.PopulateResponseMetadata( - res, - model, - Convert.ToInt32(response.StatusCode), - responseHeaders: null); - return model; - } - catch (Exception ex) - { - throw new ImagekitException(ex.Message); - } - } - - public ResponseMetaData MoveFile(MoveFileRequest moveFileRequest) - { - try - { - ResultNoContent model = new ResultNoContent(); - string validate = ValidateParamater.IsValidateMoveRequest(moveFileRequest); - if (!string.IsNullOrEmpty(validate)) - { - throw new Exception(validate); - } - - string url = string.Empty; - url = string.Format(this.mediaAPIBaseUrl + UrlHandler.MoveFile); - var content = JsonConvert.SerializeObject(moveFileRequest); - var stringContent = new StringContent(content, Encoding.UTF8, "application/json"); - HttpResponseMessage response = this.client.PostAsync(url, stringContent).Result; - string res = response.Content.ReadAsStringAsync().Result; - model = JsonConvert.DeserializeObject(res); - - Utils.PopulateResponseMetadata( - res, - model, - Convert.ToInt32(response.StatusCode), - responseHeaders: null); - return model; - } - catch (Exception ex) - { - throw new ImagekitException(ex.Message); - } - } - - public async Task MoveFileAsync(MoveFileRequest moveFileRequest) - { - try - { - ResultNoContent model = new ResultNoContent(); - string validate = ValidateParamater.IsValidateMoveRequest(moveFileRequest); - if (!string.IsNullOrEmpty(validate)) - { - throw new Exception(validate); - } - - string url = string.Empty; - url = string.Format(this.mediaAPIBaseUrl + UrlHandler.MoveFile); - var content = JsonConvert.SerializeObject(moveFileRequest); - var stringContent = new StringContent(content, Encoding.UTF8, "application/json"); - HttpResponseMessage response = await this.client.PostAsync(url, stringContent); - string res = response.Content.ReadAsStringAsync().Result; - model = JsonConvert.DeserializeObject(res); - - Utils.PopulateResponseMetadata( - res, - model, - Convert.ToInt32(response.StatusCode), - responseHeaders: null); - return model; - } - catch (Exception ex) - { - throw new ImagekitException(ex.Message); - } - } - - public ResponseMetaData RenameFile(RenameFileRequest renameFileRequest) - { - try - { - ResultRenameFile model = new ResultRenameFile(); - var validate = ValidateParamater.IsValidateRenameRequest(renameFileRequest); - if (!string.IsNullOrEmpty(validate)) - { - throw new Exception(validate); - } - - string url = string.Empty; - url = string.Format(this.mediaAPIBaseUrl + UrlHandler.RenameFile); - var content = JsonConvert.SerializeObject(renameFileRequest); - var stringContent = new StringContent(content, Encoding.UTF8, "application/json"); - HttpResponseMessage response = this.client.PutAsync(url, stringContent).Result; - string res = response.Content.ReadAsStringAsync().Result; - model = JsonConvert.DeserializeObject(res); - Utils.PopulateResponseMetadata( - res, - model, - Convert.ToInt32(response.StatusCode), - responseHeaders: null); - return model; - } - catch (Exception ex) - { - throw new ImagekitException(ex.Message); - } - } - - public async Task RenameFileAsync(RenameFileRequest renameFileRequest) - { - try - { - ResultRenameFile model = new ResultRenameFile(); - var validate = ValidateParamater.IsValidateRenameRequest(renameFileRequest); - if (!string.IsNullOrEmpty(validate)) - { - throw new Exception(validate); - } - - string url = string.Empty; - url = string.Format(this.mediaAPIBaseUrl + UrlHandler.RenameFile); - var content = JsonConvert.SerializeObject(renameFileRequest); - var stringContent = new StringContent(content, Encoding.UTF8, "application/json"); - HttpResponseMessage response = await this.client.PutAsync(url, stringContent); - string res = response.Content.ReadAsStringAsync().Result; - model = JsonConvert.DeserializeObject(res); - Utils.PopulateResponseMetadata( - res, - model, - Convert.ToInt32(response.StatusCode), - responseHeaders: null); - return model; - } - catch (Exception ex) - { - throw new ImagekitException(ex.Message); - } - } - - public ResponseMetaData CreateFolder(CreateFolderRequest createFolderRequest) - { - try - { - ResultEmptyBlock model = new ResultEmptyBlock(); - var isValidateFolder = ValidateParamater.IsValidateFolder(createFolderRequest); - if (!string.IsNullOrEmpty(isValidateFolder)) - { - throw new Exception(isValidateFolder); - } - - string url = string.Empty; - url = string.Format(this.mediaAPIBaseUrl + UrlHandler.CreateFolder); - var content = JsonConvert.SerializeObject(createFolderRequest); - Console.WriteLine(content); - var stringContent = new StringContent(content, Encoding.UTF8, "application/json"); - HttpResponseMessage response = this.client.PostAsync(url, stringContent).Result; - string res = response.Content.ReadAsStringAsync().Result; - model = JsonConvert.DeserializeObject(res); - Utils.PopulateResponseMetadata( - res, - model, - Convert.ToInt32(response.StatusCode), - responseHeaders: null); - return model; - } - catch (Exception ex) - { - throw new ImagekitException(ex.Message); - } - } - - public async Task CreateFolderAsync(CreateFolderRequest createFolderRequest) - { - try - { - ResultEmptyBlock model = new ResultEmptyBlock(); - var isValidateFolder = ValidateParamater.IsValidateFolder(createFolderRequest); - if (!string.IsNullOrEmpty(isValidateFolder)) - { - throw new Exception(isValidateFolder); - } - - string url = string.Empty; - url = string.Format(this.mediaAPIBaseUrl + UrlHandler.CreateFolder); - var content = JsonConvert.SerializeObject(createFolderRequest); - var stringContent = new StringContent(content, Encoding.UTF8, "application/json"); - HttpResponseMessage response = await this.client.PostAsync(url, stringContent); - string res = response.Content.ReadAsStringAsync().Result; - model = JsonConvert.DeserializeObject(res); - Utils.PopulateResponseMetadata( - res, - model, - Convert.ToInt32(response.StatusCode), - responseHeaders: null); - return model; - } - catch (Exception ex) - { - throw new ImagekitException(ex.Message); - } - } - - public ResponseMetaData DeleteFolder(DeleteFolderRequest deleteFolderRequest) - { - try - { - ResultNoContent model = new ResultNoContent(); - if (!ValidateParamater.IsValidateDeleteFolder(deleteFolderRequest)) - { - throw new Exception(ErrorMessages.InvalidDelFolderValue); - } - - var body = GetJsonBody.DeleteFolderBody(deleteFolderRequest); - - string url = string.Format(this.mediaAPIBaseUrl + UrlHandler.DeleteFolder); - var request = new HttpRequestMessage - { - Method = HttpMethod.Delete, - RequestUri = new Uri(url), - Content = new StringContent(body, Encoding.UTF8, "application/json"), - }; - - HttpResponseMessage response = this.client.SendAsync(request).Result; - string res = response.Content.ReadAsStringAsync().Result; - model = JsonConvert.DeserializeObject(res); - Utils.PopulateResponseMetadata( - res, - model, - Convert.ToInt32(response.StatusCode), - responseHeaders: null); - return model; - } - catch (Exception ex) - { - throw new ImagekitException(ex.Message); - } - } - - public async Task DeleteFolderAsync(DeleteFolderRequest deleteFolderRequest) - { - try - { - ResultNoContent model = new ResultNoContent(); - if (!ValidateParamater.IsValidateDeleteFolder(deleteFolderRequest)) - { - throw new Exception(ErrorMessages.InvalidDelFolderValue); - } - - var body = GetJsonBody.DeleteFolderBody(deleteFolderRequest); - - string url = string.Format(this.mediaAPIBaseUrl + UrlHandler.DeleteFolder); - var request = new HttpRequestMessage - { - Method = HttpMethod.Delete, - RequestUri = new Uri(url), - Content = new StringContent(body, Encoding.UTF8, "application/json"), - }; - - HttpResponseMessage response = await this.client.SendAsync(request); - string res = response.Content.ReadAsStringAsync().Result; - model = JsonConvert.DeserializeObject(res); - Utils.PopulateResponseMetadata( - res, - model, - Convert.ToInt32(response.StatusCode), - responseHeaders: null); - return model; - } - catch (Exception ex) - { - throw new ImagekitException(ex.Message); - } - } - - public ResponseMetaData CopyFolder(CopyFolderRequest copyFolderRequest) - { - try - { - ResultOfFolderActions model = new ResultOfFolderActions(); - var validate = ValidateParamater.IsValidateCopyFolder(copyFolderRequest); - if (!string.IsNullOrEmpty(validate)) - { - throw new Exception(validate); - } - - string url = string.Format(this.mediaAPIBaseUrl + UrlHandler.CopyFolder); - var content = JsonConvert.SerializeObject(copyFolderRequest); - var stringContent = - new StringContent(content, Encoding.UTF8, - "application/json"); // use MediaTypeNames.Application.Json in Core 3.0+ and Standard 2.1+ - - HttpResponseMessage response = this.client.PostAsync(url, stringContent).Result; - string res = response.Content.ReadAsStringAsync().Result; - model = JsonConvert.DeserializeObject(res); - Utils.PopulateResponseMetadata( - res, - model, - Convert.ToInt32(response.StatusCode), - responseHeaders: null); - return model; - } - catch (Exception ex) - { - throw new ImagekitException(ex.Message); - } - } - - public async Task CopyFolderAsync(CopyFolderRequest copyFolderRequest) - { - try - { - ResultOfFolderActions model = new ResultOfFolderActions(); - var validate = ValidateParamater.IsValidateCopyFolder(copyFolderRequest); - if (!string.IsNullOrEmpty(validate)) - { - throw new Exception(validate); - } - - string url = string.Format(this.mediaAPIBaseUrl + UrlHandler.CopyFolder); - var content = JsonConvert.SerializeObject(copyFolderRequest); - var stringContent = - new StringContent(content, Encoding.UTF8, - "application/json"); // use MediaTypeNames.Application.Json in Core 3.0+ and Standard 2.1+ - - HttpResponseMessage response = await this.client.PostAsync(url, stringContent); - string res = response.Content.ReadAsStringAsync().Result; - - model = JsonConvert.DeserializeObject(res); - Utils.PopulateResponseMetadata( - res, - model, - Convert.ToInt32(response.StatusCode), - responseHeaders: null); - return model; - } - catch (Exception ex) - { - throw new ImagekitException(ex.Message); - } - } - - public ResponseMetaData MoveFolder(MoveFolderRequest moveFolderRequest) - { - try - { - ResultOfFolderActions model = new ResultOfFolderActions(); - var validate = ValidateParamater.IsValidateMoveFolder(moveFolderRequest); - if (!string.IsNullOrEmpty(validate)) - { - throw new Exception(validate); - } - - string url = string.Format(this.mediaAPIBaseUrl + UrlHandler.MoveFolder); - var content = JsonConvert.SerializeObject(moveFolderRequest); - var stringContent = - new StringContent(content, Encoding.UTF8, - "application/json"); // use MediaTypeNames.Application.Json in Core 3.0+ and Standard 2.1+ - - HttpResponseMessage response = this.client.PostAsync(url, stringContent).Result; - string res = response.Content.ReadAsStringAsync().Result; - - model = JsonConvert.DeserializeObject(res); - Utils.PopulateResponseMetadata( - res, - model, - Convert.ToInt32(response.StatusCode), - responseHeaders: null); - return model; - } - catch (Exception ex) - { - throw new ImagekitException(ex.Message); - } - } - - public async Task MoveFolderAsync(MoveFolderRequest moveFolderRequest) - { - try - { - ResultOfFolderActions model = new ResultOfFolderActions(); - - var validate = ValidateParamater.IsValidateMoveFolder(moveFolderRequest); - if (!string.IsNullOrEmpty(validate)) - { - throw new Exception(validate); - } - - string url = string.Format(this.mediaAPIBaseUrl + UrlHandler.MoveFolder); - var content = JsonConvert.SerializeObject(moveFolderRequest); - var stringContent = - new StringContent(content, Encoding.UTF8, - "application/json"); // use MediaTypeNames.Application.Json in Core 3.0+ and Standard 2.1+ - - HttpResponseMessage response = await this.client.PostAsync(url, stringContent); - string res = response.Content.ReadAsStringAsync().Result; - model = JsonConvert.DeserializeObject(res); - Utils.PopulateResponseMetadata( - res, - model, - Convert.ToInt32(response.StatusCode), - responseHeaders: null); - return model; - } - catch (Exception ex) - { - throw new ImagekitException(ex.Message); - } - } - - public ResponseMetaData GetBulkJobStatus(string jobId) - { - try - { - ResultBulkJobStatus model = new ResultBulkJobStatus(); - if (!ValidateParamater.IsValidateParam(jobId)) - { - throw new Exception(ErrorMessages.InvalidJobValue); - } - - string url = string.Format(this.mediaAPIBaseUrl + UrlHandler.GetJobStatus, jobId); - - HttpResponseMessage response = this.client.GetAsync(url).Result; - string res = response.Content.ReadAsStringAsync().Result; - model = JsonConvert.DeserializeObject(res); - Utils.PopulateResponseMetadata( - res, - model, - Convert.ToInt32(response.StatusCode), - responseHeaders: null); - return model; - } - catch (Exception ex) - { - throw new ImagekitException(ex.Message); - } - } - - public async Task GetBulkJobStatusAsync(string jobId) - { - try - { - ResultBulkJobStatus model = new ResultBulkJobStatus(); - if (!ValidateParamater.IsValidateParam(jobId)) - { - throw new Exception(ErrorMessages.InvalidJobValue); - } - - string url = string.Format(this.mediaAPIBaseUrl + UrlHandler.GetJobStatus, jobId); - - HttpResponseMessage response = await this.client.GetAsync(url); - string res = response.Content.ReadAsStringAsync().Result; - - model = JsonConvert.DeserializeObject(res); - Utils.PopulateResponseMetadata( - res, - model, - Convert.ToInt32(response.StatusCode), - responseHeaders: null); - return model; - } - catch (Exception ex) - { - throw new ImagekitException(ex.Message); - } - } - - public ResponseMetaData GetFileVersions(string fileId) - { - try - { - ResultFileVersions model = new ResultFileVersions(); - if (!ValidateParamater.IsValidateParam(fileId)) - { - throw new Exception(ErrorMessages.FileIdMissing); - } - - string url = string.Format(this.mediaAPIBaseUrl + UrlHandler.GetFileVersion, fileId); - HttpResponseMessage response = this.client.GetAsync(url).Result; - string res = response.Content.ReadAsStringAsync().Result; - var token = JToken.Parse(res); - if (token is JArray) - { - model.ResultFileVersionDetailsList = JsonConvert.DeserializeObject>(res); - } - - Utils.PopulateResponseMetadata( - res, - model, - Convert.ToInt32(response.StatusCode), - responseHeaders: null); - return model; - } - catch (Exception ex) - { - throw new ImagekitException(ex.Message); - } - } - - public async Task GetFileVersionsAsync(string fileId) - { - try - { - ResultFileVersions model = new ResultFileVersions(); - if (!ValidateParamater.IsValidateParam(fileId)) - { - throw new Exception(ErrorMessages.FileIdMissing); - } - - string url = string.Format(this.mediaAPIBaseUrl + UrlHandler.GetFileVersion, fileId); - HttpResponseMessage response = this.client.GetAsync(url).Result; - string res = await response.Content.ReadAsStringAsync(); - var token = JToken.Parse(res); - if (token is JArray) - { - model.ResultFileVersionDetailsList = JsonConvert.DeserializeObject>(res); - } - - Utils.PopulateResponseMetadata( - res, - model, - Convert.ToInt32(response.StatusCode), - responseHeaders: null); - return model; - } - catch (Exception ex) - { - throw new ImagekitException(ex.Message); - } - } - - public ResponseMetaData GetFileVersionDetails(string fileId, string versionId) - { - try - { - ResultFileVersionDetails model = new ResultFileVersionDetails(); - var validate = ValidateParamater.IsValidateParam(fileId, versionId); - if (!string.IsNullOrEmpty(validate)) - { - throw new Exception(validate); - } - - string url = string.Format(this.mediaAPIBaseUrl + UrlHandler.GetFileVersionDetail, fileId, versionId); - HttpResponseMessage response = this.client.GetAsync(url).Result; - string res = response.Content.ReadAsStringAsync().Result; - model = JsonConvert.DeserializeObject(res); - Utils.PopulateResponseMetadata( - res, - model, - Convert.ToInt32(response.StatusCode), - responseHeaders: null); - return model; - } - catch (Exception ex) - { - throw new ImagekitException(ex.Message); - } - } - - public async Task GetFileVersionDetailsAsync(string fileId, string versionId) - { - try - { - ResultFileVersionDetails model = new ResultFileVersionDetails(); - var validate = ValidateParamater.IsValidateParam(fileId, versionId); - if (!string.IsNullOrEmpty(validate)) - { - throw new Exception(validate); - } - - string url = string.Format(this.mediaAPIBaseUrl + UrlHandler.GetFileVersionDetail, fileId, versionId); - HttpResponseMessage response = await this.client.GetAsync(url); - string res = response.Content.ReadAsStringAsync().Result; - model = JsonConvert.DeserializeObject(res); - Utils.PopulateResponseMetadata( - res, - model, - Convert.ToInt32(response.StatusCode), - responseHeaders: null); - return model; - } - catch (Exception ex) - { - throw new ImagekitException(ex.Message); - } - } - - public ResponseMetaData RestoreFileVersion(string fileId, string versionId) - { - try - { - Result model = new Result(); - var validate = ValidateParamater.IsValidateParam(fileId, versionId); - if (!string.IsNullOrEmpty(validate)) - { - throw new Exception(validate); - } - - string url = string.Format(this.mediaAPIBaseUrl + UrlHandler.RestoreVesrion, fileId, versionId); - HttpResponseMessage response = this.client.PutAsync(url, null).Result; - string res = response.Content.ReadAsStringAsync().Result; - model = JsonConvert.DeserializeObject(res); - Utils.PopulateResponseMetadata( - res, - model, - Convert.ToInt32(response.StatusCode), - responseHeaders: null); - return model; - } - catch (Exception ex) - { - throw new ImagekitException(ex.Message); - } - } - - public async Task RestoreFileVersionAsync(string fileId, string versionId) - { - try - { - Result model = new Result(); - var validate = ValidateParamater.IsValidateParam(fileId, versionId); - if (!string.IsNullOrEmpty(validate)) - { - throw new Exception(validate); - } - - string url = string.Format(this.mediaAPIBaseUrl + UrlHandler.RestoreVesrion, fileId, versionId); - HttpResponseMessage response = await this.client.PutAsync(url, null); - string res = response.Content.ReadAsStringAsync().Result; - model = JsonConvert.DeserializeObject(res); - Utils.PopulateResponseMetadata( - res, - model, - Convert.ToInt32(response.StatusCode), - responseHeaders: null); - return model; - } - catch (Exception ex) - { - throw new ImagekitException(ex.Message); - } - } -} \ No newline at end of file diff --git a/Imagekit/Util/Calculation.cs b/Imagekit/Util/Calculation.cs deleted file mode 100644 index 03a86129..00000000 --- a/Imagekit/Util/Calculation.cs +++ /dev/null @@ -1,47 +0,0 @@ -namespace Imagekit.Util -{ - using System; - using System.Collections.Generic; - using System.Globalization; - using System.Linq; - using System.Numerics; - using System.Text; - using System.Text.RegularExpressions; - using System.Threading.Tasks; - - public class Calculation - { - public static int GetHammingDistance(string firstHex, string secondHex) - { - if (!(IsValidHex(firstHex) && IsValidHex(secondHex))) - { - throw new Exception("Both argument should be hexadecimal."); - } - - if (firstHex.Length != secondHex.Length) - { - throw new Exception("Both argument are not equal in length."); - } - - BigInteger b1 = BigInteger.Parse(firstHex, NumberStyles.HexNumber); - BigInteger b2 = BigInteger.Parse(secondHex, NumberStyles.HexNumber); - BigInteger xor = b1 ^ b2; - - int count = 0; - for (int i = 0; i < xor.ToString().Length; i++) - { - if (xor.ToString()[i] == '1') - { - count += 1; - } - } - - return count; - } - - private static bool IsValidHex(string hex) - { - return System.Text.RegularExpressions.Regex.IsMatch(hex, @"^[0-9a-fA-F]+$"); - } - } -} diff --git a/Imagekit/Util/Constants.cs b/Imagekit/Util/Constants.cs deleted file mode 100644 index 07007431..00000000 --- a/Imagekit/Util/Constants.cs +++ /dev/null @@ -1,26 +0,0 @@ -// -// Copyright (c) PlaceholderCompany. All rights reserved. -// - -namespace Imagekit.Util -{ - public static class Constants - { - public const string TransformationParameter = "tr"; - public const string SignatureParameter = "ik-s"; - public const string TimestampParameter = "ik-t"; - public const string ChainTransformDelimiter = ":"; - public const string TransformDelimiter = ","; - public const string TransformKeyValueDelimiter = "-"; - public const string DefaultTimestamp = "9999999999"; - public const string ProtocolQuery = @"/http[s]?\:\/\//"; - - public const string HttpsProtocol = "https://"; - public const string HttpProtocol = "http://"; - public const string ApiHost = "api.imagekit.io"; - public const string UploadApiHost = "dasdasd.sadsdasd.io"; - public const string FileApi = "/v1/files"; - public const string UploadApi = "/api/v1/files/upload"; - public const string SdkVersion = "5.0.0"; - } -} \ No newline at end of file diff --git a/Imagekit/Util/Utils.cs b/Imagekit/Util/Utils.cs deleted file mode 100644 index 321c510b..00000000 --- a/Imagekit/Util/Utils.cs +++ /dev/null @@ -1,86 +0,0 @@ -// -// Copyright (c) PlaceholderCompany. All rights reserved. -// - -namespace Imagekit.Util -{ - using System; - using System.Collections.Generic; - using System.Diagnostics.CodeAnalysis; - using System.IO; - using System.Linq; - using System.Security.Cryptography; - using System.Text; - - [ExcludeFromCodeCoverage] - public static class Utils - { - public static string ListToString(List list) - { - return string.Join(",", list); - } - - public static string ListToString(string[] list) - { - return string.Join(",", list); - } - - public static Dictionary GetHeaders() - { - Dictionary headers = new Dictionary - { - { "Accept-Encoding", "application/json" }, - { "Content-Type", "application/json" }, - { "Authorization", "Basic " + "private_FguYxKgB8/Jm9Xs5ZyyLfwIBSFU=" }, - }; - return headers; - } - - public static ResponseMetaData PopulateResponseMetadata( - string respBody, - ResponseMetaData responseMetadata, - int responseCode, - Dictionary> responseHeaders) - { - if (responseMetadata == null) - { - responseMetadata = new ResponseMetaData(); - } - - responseMetadata.Raw = respBody; - responseMetadata.HttpStatusCode = responseCode; - return responseMetadata; - } - - public static long ToUnixTime(DateTime dateTime) - { - return (int)dateTime.ToUniversalTime().Subtract(new DateTime(1970, 1, 1)).TotalSeconds; - } - - public static string EncodeTo64(string toEncode) - { - var plainTextBytes = Encoding.UTF8.GetBytes(toEncode + ":"); - string returnValue = Convert.ToBase64String(plainTextBytes); - return returnValue; - } - - public static string GetSignatureTimestamp(int seconds) - { - if (seconds <= 0) - { - return Constants.DefaultTimestamp; - } - - var timeStamp = ToUnixTime(DateTime.UtcNow); - return (timeStamp + seconds).ToString(); - } - - public static string CalculateSignature(string input, byte[] key) - { - HMACSHA1 myhmacsha1 = new HMACSHA1(key); - byte[] byteArray = Encoding.ASCII.GetBytes(input); - MemoryStream stream = new MemoryStream(byteArray); - return myhmacsha1.ComputeHash(stream).Aggregate(string.Empty, (s, e) => s + string.Format("{0:x2}", e), s => s); - } - } -} \ No newline at end of file diff --git a/Imagekit/stylecop.json b/Imagekit/stylecop.json deleted file mode 100644 index 2bb8814b..00000000 --- a/Imagekit/stylecop.json +++ /dev/null @@ -1,14 +0,0 @@ -{ - // ACTION REQUIRED: This file was automatically added to your project, but it - // will not take effect until additional steps are taken to enable it. See the - // following page for additional informations: - // - // https://github.com/DotNetAnalyzers/StyleCopAnalyzers/blob/master/documentation/EnableConfiguration.md - - "$schema": "https://raw.githubusercontent.com/DotNetAnalyzers/StyleCopAnalyzers/master/StyleCop.Analyzers/StyleCop.Analyzers/Settings/stylecop.schema.json", - "settings": { - "documentationRules": { - "companyName": "Imagekit" - } - } -} \ No newline at end of file diff --git a/LICENSE b/LICENSE index 1247a613..e7a4d160 100644 --- a/LICENSE +++ b/LICENSE @@ -1,22 +1,201 @@ -MIT License + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ -Copyright (c) 2017 Imagekit + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: + 1. Definitions. -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright 2025 Image Kit + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/README.md b/README.md index 7442f66c..22709ca0 100644 --- a/README.md +++ b/README.md @@ -1,962 +1,102 @@ -[ImageKit.io](https://imagekit.io) +# Image Kit C# API Library -## DotNET (NET45/Standard/Core) SDK for ImageKit +> [!NOTE] +> The Image Kit C# API Library is currently in **beta** and we're excited for you to experiment with it! +> +> This library has not yet been exhaustively tested in production environments and may be missing some features you'd expect in a stable release. As we continue development, there may be breaking changes that require updates to your code. +> +> **We'd love your feedback!** Please share any suggestions, bug reports, feature requests, or general thoughts by [filing an issue](https://www.github.com/imagekit-developer/imagekit-dotnet/issues/new). -[![CI Pipeline](https://github.com/imagekit-developer/imagekit-dotnet/workflows/CI%20Pipeline/badge.svg?branch=master)](https://github.com/imagekit-developer/imagekit-dotnet) [![NuGet](https://img.shields.io/nuget/v/imagekit.svg)](https://www.nuget.org/packages/Imagekit) [![codecov](https://codecov.io/gh/imagekit-developer/imagekit-dotnet/branch/master/graph/badge.svg)](https://codecov.io/gh/imagekit-developer/imagekit-dotnet) [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT) [![Twitter Follow](https://img.shields.io/twitter/follow/imagekitio?label=Follow&style=social)](https://twitter.com/ImagekitIo) +The Image Kit C# SDK provides convenient access to the [Image Kit REST API](https://imagekit.io/docs) from applications written in C#. -ImageKit DotNET SDK allows you to use [image resizing](https://docs.imagekit.io/features/image-transformations), [optimization](https://docs.imagekit.io/features/image-optimization), [file uploading](https://docs.imagekit.io/api-reference/upload-file-api) and other [ImageKit APIs](https://docs.imagekit.io/api-reference/api-introduction) from applications written in server-side C#. +It is generated with [Stainless](https://www.stainless.com/). -##### Table of contents - -* [Installation](#installation) -* [Initialization](#initialization) -* [URL generation](#url-generation) -* [File Upload](#file-upload) -* [File Management](#file-management) -* [Tags](#tags-management) -* [Manage Folder](#folder-management) -* [Bulk Job Status](#job-management) -* [Purge](#purge) -* [Meta Data](#metadata) -* [Utility functions](#utility-functions) -* [Support](#support) -* [Links](#links) +The REST API documentation can be found on [imagekit.io](https://imagekit.io/docs). ## Installation -Package Manager - -```cs -Install-Package Imagekit -``` - -PackageReference - -```html - - +```bash +git clone git@github.com:imagekit-developer/imagekit-dotnet.git +dotnet add reference imagekit-dotnet/src/Imagekit ``` -.Net CLI +## Requirements -```cs -dotnet add package Imagekit --version 4.0.1 -``` - -Open up your project, navigate to the Nuget package manager console, and add the Imagekit package. -Also, you can search for [Imagekit](https://www.nuget.org/packages/Imagekit) in Nuget GUI. - -## Initialization +This library requires .NET 8 or later. -Add this reference where you want to use imagekit.io services: - -```cs -using Imagekit; - -ImageKitClient imagekit = new ImageKitClient(publicKey, privateKey, urlEndPoint); -``` - -**Note**: You can get the `apiKey`, `apiSecret`, and ImagekitId from your [Imagekit.io dashboard](https://imagekit.io/dashboard). - -## Demo application - -The fastest way to get started is by running the demo application in the [ImageKitSample](/ImageKitSample) folder. +> [!NOTE] +> The library is currently in **beta**. The requirements will be lowered in the future. ## Usage -You can use this DotNET SDK for three different functions: URL generation, file uploads, and file management. The usage of the SDK has been explained below. - -### URL Generation - -**1\. Using image path and image hostname or endpoint** - -This method allows you to create a URL using the `path` where the image exists and the URL endpoint (`urlEndpoint`) you want to use to access the image. You can refer to the documentation [here](https://docs.imagekit.io/integration/url-endpoints) to read more about URL endpoints in ImageKit and the section about [image origins](https://docs.imagekit.io/integration/configure-origin) to understand paths with different kinds of origins. - -```cs -string path = "/default_image.jpg"; -Transformation trans = new Transformation() -.Width(400) -.Height(300) -.AspectRatio("4-3") -.Quality(40) -.Crop("force") -.CropMode("extract") -.Focus("left") -.Format("jpeg") -.Raw("l-text,i-Imagekit,fs-50,l-end"); - -string imageURL = imagekit.Url(trans).Path(path).TransformationPosition("query").Generate(); -``` - -This results in a URL like - -```plaintext -https://ik.imagekit.io/your_imagekit_id/default_image.jpg?tr=w-400%2Ch-300%2Car-4-3%2Cq-40%2Cc-force%2Ccm-extract%2Cfo-left%2Cf-jpeg%2Cl-text%2Ci-Imagekit%2Cfs-50%2Cl-end -``` - -**2\. Using full image URL** - -This method allows you to add transformation parameters to an existing, complete URL that is already mapped to ImageKit using the `src` parameter. This method should be used if you have the complete URL mapped to ImageKit stored in your database. - -```cs -string imageURL = imagekit.Url(new Transformation().Width(400).Height(300)) - .Src("https://ik.imagekit.io/your_imagekit_id/endpoint/default_image.jpg") - .Generate(); -``` - -This results in a URL like - -```plaintext -https://ik.imagekit.io/your_imagekit_id/endpoint/default_image.jpg?tr=h-300,w-400 -``` - -The `.Url()` method accepts the following parameters. - -| Option | Description | -| --- | --- | -| urlEndpoint | Optional. The base URL has to be appended before the path of the image. If not specified, the URL Endpoint specified at the time of SDK initialization is used. For example, `https://ik.imagekit.io/your_imagekit_id/endpoint/` | -| path | Conditional. This is the path on which the image exists. For example, `/path/to/image.jpg`. Either the `path` or `src` parameter needs to be specified for URL generation. | -| src | Conditional. This is the complete URL of an image already mapped to ImageKit. For example, `https://ik.imagekit.io/your_imagekit_id/endpoint/path/to/image.jpg`. Either the `path` or `src` parameter needs to be specified for URL generation. | -| transformation | Optional. An array of objects specifying the transformation to be applied in the URL. The transformation name and the value should be specified as a key-value pair in the object. Different steps of a [chained transformation](https://docs.imagekit.io/features/image-transformations/chained-transformations) can be specified as the array's different objects. The complete list of supported transformations in the SDK and some examples of using them are given later. If you use a transformation name that is not specified in the SDK, it gets applied as it is in the URL. | -| transformationPosition | Optional. The default value is `path` that places the transformation string as a URL path parameter. It can also be specified as `query`, which adds the transformation string as the URL's query parameter `tr`. If you use the `src` parameter to create the URL, then the transformation string is always added as a query parameter. | -| queryParameters | Optional. These are the other query parameters that you want to add to the final URL. These can be any query parameters and not necessarily related to ImageKit. Especially useful if you want to add some versioning parameters to your URLs. | -| signed | Optional. Boolean. Default is `false`. If set to `false`, the SDK generates a signed image URL by adding the image signature to the image URL. This can only be used if you create the URL with the `urlEndpoint` and `path` parameters, not with the `src` parameter. | -| expireSeconds | Optional. Integer. It is meant to be used along with the `signed` parameter to specify the time in seconds from now when the URL should expire. If specified, the URL contains the expiry timestamp in the URL, and the image signature is modified accordingly. | - -#### Examples of generating URLs - -**1\. Chained Transformations as a query parameter** - -```cs -Transformation transformation = new Transformation() - .Width(400).Height(300) - .Chain() - .Rotation(90); - -string imageURL = imagekit.Url(transformation) - .Path("/default_image.jpg") - .UrlEndpoint("https://ik.imagekit.io/your_imagekit_id/endpoint") - .TransformationPosition("query") - .Generate(); -``` - -```plaintext -https://ik.imagekit.io/your_imagekit_id/endpoint/default_image.jpg?tr=h-300,w-400:rt-90 -``` - -**2\. Sharpening, contrast adjustment, shadow and gradient transformations, along with a progressive JPEG format image.** - -There are some transforms like [Sharpening](https://docs.imagekit.io/features/image-transformations/image-enhancement-and-color-manipulation) that can be added to the URL with or without any other value. - -```cs -string src = "https://ik.imagekit.io/your_imagekit_id/endpoint/default-image.jpg"; - -Transformation trans = new Transformation() - .Format("jpg") - .Progressive(false) - .EffectSharpen() - .EffectContrast(1) - .EffectShadow() - .EffectGradient(); - -string imageURL = imagekit.Url(trans) - .Src(src) - .Generate(); -``` - -**Note**: Because `src` parameter was used, the transformation string gets added as a query parameter `tr`. - -```plaintext -https://ik.imagekit.io/your_imagekit_id/endpoint/default-image.jpg?tr=f-jpg%2Cpr-false%2Ce-sharpen%2Ce-contrast-1%2Ce-shadow%2Ce-gradient -``` - -**3\. Signed URL that expires in 600 seconds with the default URL endpoint and other query parameters** - -```cs -Transformation trans = new Transformation() - .Height(300).Width(400); -string[] queryParams = { "v = 123" }; - -string imageURL = imagekit.Url(trans) - .Path("/default-image.jpg") - .QueryParameters(queryParams) - .Signed(false).ExpireSeconds(600) - .Generate(); -``` - -```plaintext -https://ik.imagekit.io/your_imagekit_id/tr:h-300,w-400/default-image.jpg?v=123&ik-t=1567358667&ik-s=f2c7cdacbe7707b71a83d49cf1c6110e3d701054 -``` - -**4. Adding overlays** - -ImageKit.io enables you to apply overlays to [images](https://docs.imagekit.io/features/image-transformations/overlay-using-layers) and [videos](https://docs.imagekit.io/features/video-transformation/overlay) using the raw parameter with the concept of [layers](https://docs.imagekit.io/features/image-transformations/overlay-using-layers#layers). The raw parameter facilitates incorporating transformations directly in the URL. A layer is a distinct type of transformation that allows you to define an asset to serve as an overlay, along with its positioning and additional transformations. - -**Text as overlays** - -You can add any text string over a base video or image using a text layer (l-text). - -For example: - -```cs -string path = "/default_image.jpg"; -Transformation trans = new Transformation() -.Width(400) -.Height(300) -.Raw("l-text,i-Imagekit,fs-50,l-end"); - -string imageURL = imagekit.Url(trans).Path(path).TransformationPosition("query").Generate(); -``` -**Sample Result URL** -``` -https://ik.imagekit.io/your_imagekit_id/default-image.jpg?tr=h-300,w-400,l-text,i-Imagekit,fs-50,l-end -``` - -**Image as overlays** - -You can add an image over a base video or image using an image layer (l-image). - -For example: - -```cs -string path = "/default_image.jpg"; -Transformation trans = new Transformation() -.Width(400) -.Height(300) -.Raw("l-image,i-default-image.jpg,w-100,b-10_CDDC39,l-end"); - -string imageURL = imagekit.Url(trans).Path(path).TransformationPosition("query").Generate(); -``` -**Sample Result URL** -``` -https://ik.imagekit.io/your_imagekit_id/default-image.jpg?tr=h-300,w-400,l-image,i-default-image.jpg,w-100,b-10_CDDC39,l-end -``` - -**Solid color blocks as overlays** - -You can add solid color blocks over a base video or image using an image layer (l-image). - -For example: - -```cs -string path = "/img/sample-video.mp4"; -Transformation trans = new Transformation() -.Width(400) -.Height(300) -.Raw("l-image,i-ik_canvas,bg-FF0000,w-300,h-100,l-end"); - -string imageURL = imagekit.Url(trans).Path(path).TransformationPosition("query").Generate(); -``` -**Sample Result URL** -``` -https://ik.imagekit.io/your_imagekit_id/img/sample-video.mp4?tr=h-300,w-400,l-image,i-ik_canvas,bg-FF0000,w-300,h-100,l-end -``` - -#### List of supported transformations - -The complete list of transformations supported and their usage in ImageKit can be found [here](https://docs.imagekit.io/features/image-transformations). The SDK gives a name to each transformation parameter, making the code simpler and more readable. If a transformation is supported in ImageKit, but a name for it cannot be found in the table below, then use the transformation code from ImageKit docs as the name when using the `url` function. - -| Supported Transformation Name | Translates to parameters | -| --- | --- | -| Height | h | -| Width | w | -| AspectRatio | ar | -| Quality | q | -| Crop | c | -| CropMode | cm | -| X | x | -| Y | y | -| Focus | fo | -| Format | f | -| Radius | r | -| Background | bg | -| Border | b | -| Rotation | rt | -| Blur | bl | -| Named | n | -| Progressive | pr | -| Lossless | lo | -| Trim | t | -| Metadata | md | -| ColorProfile | cp | -| DefaultImage | di | -| Dpr | dpr | -| EffectSharpen | e-sharpen | -| EffectUSM | e-usm | -| EffectContrast | e-contrast | -| EffectGray | e-grayscale | -| EffectShadow | e-shadow | -| EffectGradient | e-gradient | -| Original | orig | -| Raw | `replaced by the parameter value` | - -### File Upload - -The SDK provides a simple interface using the `.upload()` method to upload files to the ImageKit Media Library. It accepts all the parameters supported by the [ImageKit Upload API](https://docs.imagekit.io/api-reference/upload-file-api/server-side-file-upload). - -The `upload()` method requires at least the `file` and the `fileName` parameter to upload a file. You can pass other parameters supported by the ImageKit upload API using the same parameter name as specified in the upload API documentation. For example, to specify tags for a file at the time of upload, use the `tags` parameter as specified in the [documentation here](https://docs.imagekit.io/api-reference/upload-file-api/server-side-file-upload). - -Sample usage - -```cs - // Upload By URI -FileCreateRequest request = new FileCreateRequest -{ - file = "http://www.google.com/images/logos/ps_logo2.png", - fileName = "file_name.jpg", -}; -Result resp1 = imagekit.Upload(request); - -// Upload by bytes -byte[] bytes = System.IO.File.ReadAllBytes(@"image file path"); - -FileCreateRequest ob = new FileCreateRequest -{ - file = bytes, - fileName = Guid.NewGuid().ToString() -}; -List tags = new List -{ - "Software", - "Developer", - "Engineer" -}; -ob.tags = tags; - -string customCoordinates = "10,10,20,20"; -ob.customCoordinates = customCoordinates; -List responseFields = new List -{ - "isPrivateFile", - "tags", - "customCoordinates" -}; -ob.responseFields = responseFields; -List ext = new List(); -BackGroundImage bck1 = new BackGroundImage -{ - name = "remove-bg", - options = new options() - { add_shadow = true, semitransparency = false, bg_image_url = "http://www.google.com/images/logos/ps_logo2.png" } -}; -AutoTags autoTags = new AutoTags -{ - name = "google-auto-tagging", - maxTags = 5, - minConfidence = 95 -}; -ext.Add(bck1); -ext.Add(autoTags); -TransformationObject transformationObject = new TransformationObject -{ - value = "w-100" -}; -List postTransformations = new List(); -postTransformations.Add(transformationObject); -UploadTransformation uploadTransformation = new UploadTransformation -{ - pre = "l-text,i-Imagekit,fs-50,l-end", - post = postTransformations, -}; -ob.extensions = ext; -ob.webhookUrl = "https://webhook.site/c78d617f_33bc_40d9_9e61_608999721e2e"; -ob.useUniqueFileName = true; -ob.folder = "dummy_folder"; -ob.isPrivateFile = false; -ob.overwriteFile = true; -ob.overwriteAITags = true; -ob.overwriteTags = true; -ob.overwriteCustomMetadata = true; -ob.checks = "'file.size' < '1mb'" // To run server side checks before uploading files. Notice the quotes around file.size and 1mb. -ob.isPublished = true; -Result resp2 = imagekit.Upload(ob); - -//Get Base64 -byte[] imageArray = System.IO.File.ReadAllBytes(@"image file path"); -string base64ImageRepresentation = Convert.ToBase64String(imageArray); -// Upload by Base64 -FileCreateRequest ob2 = new FileCreateRequest -{ - file=base64ImageRepresentation, - fileName = Guid.NewGuid().ToString() -}; -Result resp = imagekit.Upload(ob2); -``` - -### File Management - -The SDK provides a simple interface for all the [media APIs mentioned here](https://docs.imagekit.io/api-reference/media-afile-uploadpi) to manage your files. - -**1 . List & Search Files** - -Accepts an object specifying the parameters to be used to list and search files. All parameters specified in the [documentation here](https://docs.imagekit.io/api-reference/media-api/list-and-search-files) can be passed as it is with the correct values to get the results. - -#### Applying Filters -Filter out the files by specifying the parameters. - -```cs -GetFileListRequest model = new GetFileListRequest -{ - Name = "file_name.jpg", - Type = "file", - Limit = 10, - Skip = 0, - Sort = "ASC_CREATED", - FileType = "image", - Tags = new string[] { "tag1", "tag2" } -}; -ResultList res = await imagekit.GetFileListRequestAsync(model); -``` - -#### Advance Search -In addition, you can fine-tune your query by specifying various filters by generating a query string in a Lucene-like syntax and providing this generated string as the value of the `SearchQuery`. - -```cs -GetFileListRequest model = new GetFileListRequest -{ - SearchQuery = "createdAt >= '2d' OR size < '2mb' OR format='png'", -}; -ResultList res = await imagekit.GetFileListRequestAsync(model); -``` - -Detailed documentation can be found here for [advance search queries](https://docs.imagekit.io/api-reference/media-api/list-and-search-files#advanced-search-queries). - -**2\. Get File Details** - -Accepts the file ID and fetches the details as per the [API documentation here](https://docs.imagekit.io/api-reference/media-api/get-file-details). - -```cs -Result resp = await imagekit.GetFileDetail(file_Id); -``` - -**3\. File Update** - -Accepts an object of class `FileUpdateRequest` specifying the parameters to be used to update file details. All parameters specified in the \[documentation here\] (https://docs.imagekit.io/api-reference/media-api/update-file-details) can be passed via their setter functions to get the results. - -```cs -FileUpdateRequest updateob = new FileUpdateRequest -{ - fileId = "fileId", -}; -List updatetags = new List -{ - "Software", - "Developer", - "Engineer" -}; -updateob.tags = updatetags; -string updatecustomCoordinates = "10,10,20,20"; -updateob.customCoordinates = updatecustomCoordinates; -List updateresponseFields = new List -{ - "isPrivateFile", - "tags", - "customCoordinates" -}; - -List extModel = new List(); -BackGroundImage bck = new BackGroundImage -{ - name = "remove-bg", - options = new options() { add_shadow = true, semitransparency = false, bg_color = "green" } -}; -extModel.Add(bck); -updateob.extensions = extModel; -updateob.webhookUrl = "https://webhook.site/c78d617f_33bc_40d9_9e61_608999721e2e"; -Result updateresp = imagekit.UpdateFileDetail(updateob); -``` - -**Update publish status** - -If `publish` is included in the update options, no other parameters are allowed. - -```cs -FileUpdateRequest updateob = new FileUpdateRequest -{ - fileId = "fileId", -}; -PublishStatus publishStatus = new PublishStatus -{ - isPublished = false -}; -updateob.publish = publishStatus; -Result updateresp = imagekit.UpdateFileDetail(updateob); -``` - -**4\. Delete File** - -Accept the file ID and delete a file as per the [API documentation here](https://docs.imageKit.io/api-reference/media-api/delete-file). - -```cs -String fileId = "file_Id"; -ResultDelete result = imageKit.deleteFile(fileId); -``` - -**5\. Delete files (bulk)** - -Accepts the file IDs to delete files as per the [API documentation here](https://docs.imageKit.io/api-reference/media-api/delete-files-bulk). - -```cs -List ob3 = new List(); -ob3.Add("fileId_1"); -ob3.Add("fileId_2"); -ResultFileDelete resultFileDelete = imagekit.BulkDeleteFiles(ob3); -``` - -**6\. Copy file** - -Accepts an object of class `CopyFileRequest` specifying the parameters to be used to copy a file. All parameters specified in the [documentation here](https://docs.imageKit.io/api-reference/media-api/copy-file) can be passed via their setter functions to get the results. - -```cs -CopyFileRequest cpyRequest = new CopyFileRequest -{ - sourceFilePath = "path_1", - destinationPath = "path_2", - includeFileVersions = true -}; -ResultNoContent resultNoContent = imagekit.CopyFile(cpyRequest); -``` - -**7\. Move file** - -Accepts an object of class `MoveFileRequest` specifying the parameters to be used to move a file. All parameters specified in the [documentation here](https://docs.imageKit.io/api-reference/media-api/move-file) can be passed via their setter functions to get the results. - -```cs -MoveFileRequest moveFile = new MoveFileRequest -{ - sourceFilePath = "path_1", - destinationPath = "path_2" -}; -ResultNoContent resultNoContentMoveFile = imagekit.MoveFile(moveFile); -``` - -**8\. Rename file** - -Accepts an object of class `RenameFileRequest` specifying the parameters to be used to rename a file. All parameters specified in the [documentation here](https://docs.imageKit.io/api-reference/media-api/rename-file) can be passed via their setter functions to get the results. - -```cs -RenameFileRequest renameFileRequest = new RenameFileRequest -{ - filePath = "path_1", - newFileName = "file_name", - purgeCache = false -}; -ResultRenameFile resultRenameFile = imagekit.RenameFile(renameFileRequest); -``` - -### Tags Management - -The SDK provides a simple interface to manage your tags. - -**9\. Add tags** - -Accepts an object of class `TagsRequest` specifying the parameters to be used to add tags. All parameters specified in the [documentation here](https://docs.imageKit.io/api-reference/media-api/add-tags-bulk) can be passed via their setter functions to get the results. - -```cs -TagsRequest tagsRequest = new TagsRequest -{ - tags = new List - { - "tag_1", - "tag_2" - }, - fileIds = new List - { - "fileId_1", - }, -}; -ResultTags resultTags = imagekit.AddTags(tagsRequest); -``` - -**10\. Remove tags** - -Accepts an object of class `TagsRequest` specifying the parameters to be used to remove tags. All parameters specified in the [documentation here](https://docs.imageKit.io/api-reference/media-api/remove-tags-bulk) can be passed via their setter functions to get the results. - -```cs -TagsRequest removeTagsRequest = new TagsRequest -{ - tags = new List - { - "tag_1", - "tag_2" - }, - fileIds = new List - { - "fileId_1", - }, -}; -ResultTags removeTags = imagekit.RemoveTags(removeTagsRequest); -``` - -**11\. Remove AI tags** - -Accepts an object of class `AITagsRequest` specifying the parameters to be used to remove AI tags. All parameters specified in the [documentation here](https://docs.imageKit.io/api-reference/media-api/remove-aitags-bulk) can be passed via their setter functions to get the results. - -```cs -AITagsRequest removeAITagsRequest = new AITagsRequest -{ - AITags = new List - { - "tag_1", - "tag_2" - }, - fileIds = new List - { - "fileId_1", - } -}; -ResultTags removeAITags = imagekit.RemoveAITags(removeAITagsRequest); -``` - -**12\. Get File Versions** - -Accepts the file ID and fetches the details as per the [API documentation here](https://docs.imagekit.io/api-reference/media-api/get-file-versions). - -```cs -String fileId = "file_id_1"; -ResultFileVersions resultFileVersions = imageKit.getFileVersions(fileId); -``` - -**13\. Get File Version details** +See the [`examples`](examples) directory for complete and runnable examples. -Accepts the file ID and version ID and fetches the details as per the [API documentation here](https://docs.imagekit.io/api-reference/media-api/get-file-version-details). - -```cs -String fileId = "file_Id"; -String versionId = "version_Id"; -ResultFileVersionDetails resultFileVersionDetails = imageKit.getFileVersionDetails(fileId, versionId); -``` - -**14\. Delete FileVersion** - -Accepts an object of class `DeleteFileVersionRequest` specifying the parameters to be used to delete the file version. All parameters specified in the [documentation here](https://docs.imageKit.io/api-reference/media-api/delete-file-version) can be passed via their setter functions to get the results. - -```cs -DeleteFileVersionRequest delRequest = new DeleteFileVersionRequest -{ - fileId = "file_Id", - versionId = "version_Id" -}; -ResultNoContent resultNoContent1 = imagekit.DeleteFileVersion(delRequest); -``` - -**15\. Restore file Version** - -Accepts the fileId and versionId to restore the file version as per the [API documentation here](https://docs.imageKit.io/api-reference/media-api/restore-file-version). - -```cs -Result result = imagekit.RestoreFileVersion("file_Id", "version_Id"); -``` - -### Folder Management - -**16\. Create Folder** - -Accepts an object of class `CreateFolderRequest` specifying the parameters to be used to create a folder. All parameters specified in the [documentation here](https://docs.imageKit.io/api-reference/media-api/create-folder) can be passed via their setter functions to get the results. - -```cs -CreateFolderRequest createFolderRequest = new CreateFolderRequest -{ - folderName = "folder_name", - parentFolderPath = "source/folder/path" -}; -ResultEmptyBlock resultEmptyBlock = imagekit.CreateFolder(createFolderRequest); -``` - -**17\. Copy Folder** - -Accepts an object of class `CopyFolderRequest` specifying the parameters to be used to copy a folder. All parameters specified in the [documentation here](https://docs.imageKit.io/api-reference/media-api/copy-folder) can be passed via their setter functions to get the results. - -```cs -CopyFolderRequest cpyFolderRequest = new CopyFolderRequest -{ - sourceFolderPath = "path_1", - destinationPath = "path_2", - includeFileVersions = true -}; - -ResultOfFolderActions resultOfFolderActions = imagekit.CopyFolder(cpyFolderRequest); -``` - -**18\. Move Folder** - -Accepts an object of class `MoveFolderRequest` specifying the parameters to be used to move a folder. All parameters specified in the [documentation here](https://docs.imageKit.io/api-reference/media-api/move-folder) can be passed via their setter functions to get the results. - -```cs -MoveFolderRequest moveFolderRequest = new MoveFolderRequest -{ - sourceFolderPath="path_1", - destinationPath="path_2" -}; - -ResultOfFolderActions resultOfFolderActions1 = imagekit.MoveFolder(moveFolderRequest); -``` - -**19\. Delete Folder** +```csharp +using System; +using Imagekit; +using Imagekit.Models.Files; -Accepts an object of class `DeleteFolderRequest` specifying the parameters to be used to delete a folder. All parameters specified in the [documentation here](https://docs.imageKit.io/api-reference/media-api/delete-folder) can be passed via their setter functions to get the results. +// Configured using the IMAGEKIT_PRIVATE_API_KEY, OPTIONAL_IMAGEKIT_IGNORES_THIS, IMAGEKIT_WEBHOOK_SECRET and IMAGE_KIT_BASE_URL environment variables +ImageKitClient client = new(); -```cs -DeleteFolderRequest deleteFolderRequest = new DeleteFolderRequest +FileUploadParams parameters = new() { - folderPath="source/folder/path/folder_name", + File = "a value", + FileName = "file-name.jpg", }; -ResultNoContent resultNoContent2 = imagekit.DeleteFolder(deleteFolderRequest); -``` - -### Job Management - -**20\. Get Bulk Job Status** -Accepts the jobId to get bulk job status as per the [API documentation here](https://docs.imageKit.io/api-reference/media-api/copy-move-folder-status). +var response = await client.Files.Upload(parameters); -```cs -String jobId = "job_Id"; -ResultBulkJobStatus resultBulkJobStatus = imageKit.getBulkJobStatus(jobId); +Console.WriteLine(response); ``` -### Purge +## Client Configuration -**21\. Purge Cache** +Configure the client using environment variables: -Accepts a full URL of the file for which the cache has to be cleared as per the [API documentation here](https://docs.imageKit.io/api-reference/media-api/purge-cache). - -```cs -ResultCache result = imageKit.purgeCache("https://ik.imageKit.io/imagekit-id/default-image.jpg"); -``` - -**22\. Purge Cache Status** - -Accepts a request ID and fetch purge cache status as per the [API documentation here](https://docs.imageKit.io/api-reference/media-api/purge-cache-status) - -```cs -String requestId = "cache_request_Id"; -ResultCacheStatus result = imageKit.getPurgeCacheStatus(requestId); -``` - -### Metadata - -Accepts the file ID and fetches the metadata as per the [API documentation here](https://docs.imageKit.io/api-reference/metadata-api/get-image-metadata-for-uploaded-media-files) - -**23\. Get File Metadata** - -```cs -String fileId = "file_id"; -ResultMetaData result = imageKit.getFileMetadata(fileId); -``` - -Another way to get metadata from a remote file URL as per the [API documentation here](https://docs.imageKit.io/api-reference/metadata-api/get-image-metadata-from-remote-url). This file should be accessible over the imageKit.io URL-endpoint. - -```cs -String url = "Remote File URL"; -ResultMetaData result = imageKit.getRemoteFileMetadata(url); -``` - -**24\. Create Custom MetaData Fields** - -Accepts an object of class `CustomMetaDataFieldCreateRequest` specifying the parameters to be used to create cusomMetaDataFields. All parameters specified in the [documentation here](https://docs.imageKit.io/api-reference/custom-metadata-fields-api/create-custom-metadata-field) can be passed as-is with the correct values to get the results. - -Check for the [Allowed Values In The Schema](https://docs.imageKit.io/api-reference/custom-metadata-fields-api/create-custom-metadata-field#allowed-values-in-the-schema-object). - -#### Examples: - -```cs -CustomMetaDataFieldCreateRequest requestModel = new CustomMetaDataFieldCreateRequest -{ - name = "custom-meta-1", - label = "Testmeta" -}; -CustomMetaDataFieldSchemaObject schema = new CustomMetaDataFieldSchemaObject -{ - type = "Number", - minValue = 2000, - maxValue = 3000, - isValueRequired = true, - defaultValue = "2500" -}; - -requestModel.schema = schema; -ResultCustomMetaDataField resultCustomMetaDataField1 = imagekit.CreateCustomMetaDataFields(requestModel); -``` - -* Date type Example: - -```cs -CustomMetaDataFieldCreateRequest requestModelDate = new CustomMetaDataFieldCreateRequest -{ - name = "custom_meta_Date", - label = "TestmetaDate" -}; -CustomMetaDataFieldSchemaObject schemaDate = new CustomMetaDataFieldSchemaObject -{ - type = "Date", - minValue = "2022-11-30T10:11:10+00:00", - maxValue = "2022-12-30T10:11:10+00:00" -}; -requestModelDate.schema = schemaDate; -ResultCustomMetaDataField resultCustomMetaDataFieldDate = imagekit.CreateCustomMetaDataFields(requestModelDate); -``` - -**25\. Get CustomMetaDataFields** - -Accepts the includeDeleted boolean and fetches the metadata as per the [API documentation here](https://docs.imageKit.io/api-reference/custom-metadata-fields-api/get-custom-metadata-field) +```csharp +using Imagekit; -```cs -bool includeDeleted = true; -ResultCustomMetaDataFieldList resultCustomMetaDataFieldList = imageKit.getCustomMetaDataFields(includeDeleted); +// Configured using the IMAGEKIT_PRIVATE_API_KEY, OPTIONAL_IMAGEKIT_IGNORES_THIS, IMAGEKIT_WEBHOOK_SECRET and IMAGE_KIT_BASE_URL environment variables +ImageKitClient client = new(); ``` -**26\. Edit Custom MetaData Fields** +Or manually: -Accepts an ID of customMetaDataField and an object of class `CustomMetaDataFieldUpdateRequest` specifying the parameters to be used to edit cusomMetaDataFields as per the [API documentation here](https://docs.imageKit.io/api-reference/custom-metadata-fields-api/update-custom-metadata-field). +```csharp +using Imagekit; -```cs -CustomMetaDataFieldUpdateRequest requestUpdateModel = new CustomMetaDataFieldUpdateRequest -{ - Id = "field_id", -}; -CustomMetaDataFieldSchemaObject updateschema = new CustomMetaDataFieldSchemaObject +ImageKitClient client = new() { - type = "Number", - minValue = 8000, - maxValue = 3000 + PrivateAPIKey = "My Private API Key", + Password = "My Password", }; - -requestUpdateModel.schema = updateschema; -ResultCustomMetaDataField resultCustomMetaDataFieldUpdate = imagekit.UpdateCustomMetaDataFields(requestUpdateModel); -``` - -**27\. Delete Custom MetaData Fields** - -Accepts the id to delete the customMetaDataFields as per the [API documentation here](https://docs.imageKit.io/api-reference/custom-metadata-fields-api/delete-custom-metadata-field). - -```cs -ResultNoContent resultNoContent = imageKit.DeleteCustomMetaDataField("field_id"); -``` - -## Utility functions - -We have included the following commonly used utility functions in this library. - -### Authentication Parameter Generation - -If you are looking to implement client-side file upload, you will need a token, expiry timestamp, and a valid signature for that upload. The SDK provides a simple method that you can use in your code to generate these authentication parameters for you. - -_Note: The Private API Key should never be exposed in any client-side code. You must always generate these authentication parameters on the server-side_ - -```cs -AuthParamResponse resp = imageKit.GetAuthenticationParameters(); -``` - -Returns - -```javascript -{ - "token" : "unique_token", - "expire" : "valid_expiry_timestamp", - "signature" : "generated_signature" -} -``` - -Both the `token` and `expire` parameters are optional. If not specified, the SDK uses the [uuid](https://www.npmjs.com/package/uuid) package to generate a random token and also generates a valid expiry timestamp internally. The value of the `token` and `expire` used to generate the signature is always returned in the response, no matter if they are provided as an input to this method or not. - -### Distance calculation between two pHash values - -Perceptual hashing allows you to construct a hash value that uniquely identifies an input image based on an image's contents. [imageKit.io metadata API](https://docs.imageKit.io/api-reference/metadata-api) returns the pHash value of an image in the response. You can use this value to [find a duplicate (or similar) image](https://docs.imageKit.io/api-reference/metadata-api#using-phash-to-find-similar-or-duplicate-images) by calculating the distance between the two images' pHash value. - -This SDK exposes `PHashDistance` function to calculate the distance between two pHash values. It accepts two pHash hexadecimal strings and returns a numeric value indicative of the level of difference between the two images. - -```cs -public static int CalculateDistance() { - // asynchronously fetch metadata of two uploaded image files - // ... - // Extract pHash strings from both: say 'firstHash' and 'secondHash' - // ... - // Calculate the distance between them: - int distance = imageKit.PHashDistance(firstHash, secondHash); - return distance; -} -``` - -#### Distance calculation examples - -```cs -imageKit.PHashDistance('firstHash', 'secondHash'); -// output: 0 (same image) - -imageKit.PHashDistance('firstHash', 'secondHash'); -// output: 17 (similar images) - -imageKit.PHashDistance('firstHash', 'secondHash'); -// output: 37 (dissimilar images) ``` -## Handling errors +Or using a combination of the two approaches. -Catch and respond to invalid data, internal problems, and more. +See this table for the available options: -Imagekit .Net SDK raises exceptions for many reasons, such as being not found, invalid parameters, authentication errors, and internal server errors. We recommend writing code that gracefully handles all possible API exceptions. +| Property | Environment variable | Required | Default value | +| --------------- | -------------------------------- | -------- | --------------------------- | +| `PrivateAPIKey` | `IMAGEKIT_PRIVATE_API_KEY` | true | - | +| `Password` | `OPTIONAL_IMAGEKIT_IGNORES_THIS` | false | `"do_not_set"` | +| `WebhookSecret` | `IMAGEKIT_WEBHOOK_SECRET` | false | - | +| `BaseUrl` | `IMAGE_KIT_BASE_URL` | true | `"https://api.imagekit.io"` | -#### Example: +## Requests and responses -```cs -try -{ - // Use ImageKit's SDK to make requests... -} -catch (InvalidOperationException ex) -{ - Console.Write("Invalid operation. Please try again."); -} -catch (FormatException ex) -{ - Console.Write("Not a valid format. Please try again."); -} -catch (WebServiceException webEx) -{ - /* - webEx.StatusCode = 400 - webEx.StatusDescription = ArgumentNullException - webEx.ErrorCode = ArgumentNullException - webEx.ErrorMessage = Value cannot be null. Parameter name: Name - webEx.StackTrace = (your Server Exception StackTrace - in DebugMode) - webEx.ResponseDto = (your populated Response DTO) - webEx.ResponseStatus = (your populated Response Status DTO) - webEx.GetFieldErrors() = (individual errors for each field if any) - */ -} -``` - -## Access request-id, other response headers and HTTP status code - -You can access success or error object to access the HTTP status code and response headers. - -```cs -// Success -var response = await imagekit.PurgeStatus(requestId); -console.Write(response.statusCode); // 200 -// {'content-type': 'application/json', 'x-request-id': 'ee560df4-d44f-455e-a48e-29dfda49aec5'} -console.Write(response.Raw); -try -{ - await imagekit.PurgeStatus(requestId); -} -catch (Exception ex) -{ - console.Write(ex.Message); - // {'content-type': 'application/json', 'x-request-id': 'ee560df4-d44f-455e-a48e-29dfda49aec5'} -} -``` +To send a request to the Image Kit API, build an instance of some `Params` class and pass it to the corresponding client method. When the response is received, it will be deserialized into an instance of a C# class. -## Support +For example, `client.Files.Upload` should be called with an instance of `FileUploadParams`, and it will return an instance of `Task`. -For any feedback or to report any issues or general implementation support, please reach out to [support@imageKit.io](mailto:support@imageKit.io) +## Semantic versioning -## Links +This package generally follows [SemVer](https://semver.org/spec/v2.0.0.html) conventions, though certain backwards-incompatible changes may be released as minor versions: -* [Documentation](https://docs.imageKit.io) -* [Main website](https://imageKit.io) +1. Changes to library internals which are technically public but not intended or documented for external use. _(Please open a GitHub issue to let us know if you are relying on such internals.)_ +2. Changes that we do not expect to impact the vast majority of users in practice. -## License +We take backwards-compatibility seriously and work hard to ensure you can rely on a smooth upgrade experience. -This project is licensed under the MIT License - see the [LICENSE](LICENSE) File for details \ No newline at end of file +We are keen for your feedback; please open an [issue](https://www.github.com/imagekit-developer/imagekit-dotnet/issues) with questions, bugs, or suggestions. diff --git a/SECURITY.md b/SECURITY.md new file mode 100644 index 00000000..8e64327a --- /dev/null +++ b/SECURITY.md @@ -0,0 +1,27 @@ +# Security Policy + +## Reporting Security Issues + +This SDK is generated by [Stainless Software Inc](http://stainless.com). Stainless takes security seriously, and encourages you to report any security vulnerability promptly so that appropriate action can be taken. + +To report a security issue, please contact the Stainless team at security@stainless.com. + +## Responsible Disclosure + +We appreciate the efforts of security researchers and individuals who help us maintain the security of +SDKs we generate. If you believe you have found a security vulnerability, please adhere to responsible +disclosure practices by allowing us a reasonable amount of time to investigate and address the issue +before making any information public. + +## Reporting Non-SDK Related Security Issues + +If you encounter security issues that are not directly related to SDKs but pertain to the services +or products provided by Image Kit, please follow the respective company's security reporting guidelines. + +### Image Kit Terms and Policies + +Please contact developer@imagekit.io for any questions or concerns regarding the security of our services. + +--- + +Thank you for helping us keep the SDKs and systems they interact with secure. diff --git a/codecov.yml b/codecov.yml deleted file mode 100644 index 52dd98c0..00000000 --- a/codecov.yml +++ /dev/null @@ -1,15 +0,0 @@ -# Team Yaml -coverage: - round: down - precision: 5 - -# Repository Yaml -coverage: - round: up - range: 0..10 - -# Used in Codecov after updating -coverage: - round: up - range: 0..10 - precision: 5 diff --git a/examples/ImagekitExample/ImagekitExample.csproj b/examples/ImagekitExample/ImagekitExample.csproj new file mode 100644 index 00000000..00114bda --- /dev/null +++ b/examples/ImagekitExample/ImagekitExample.csproj @@ -0,0 +1,12 @@ + + + + + + Exe + net8.0 + ImagekitExample + enable + disable + + diff --git a/release-please-config.json b/release-please-config.json new file mode 100644 index 00000000..66eb8d5c --- /dev/null +++ b/release-please-config.json @@ -0,0 +1,71 @@ +{ + "packages": { + ".": {} + }, + "$schema": "https://raw.githubusercontent.com/stainless-api/release-please/main/schemas/config.json", + "include-v-in-tag": true, + "include-component-in-tag": false, + "versioning": "prerelease", + "prerelease": true, + "bump-minor-pre-major": true, + "bump-patch-for-minor-pre-major": false, + "pull-request-header": "Automated Release PR", + "pull-request-title-pattern": "release: ${version}", + "changelog-sections": [ + { + "type": "feat", + "section": "Features" + }, + { + "type": "fix", + "section": "Bug Fixes" + }, + { + "type": "perf", + "section": "Performance Improvements" + }, + { + "type": "revert", + "section": "Reverts" + }, + { + "type": "chore", + "section": "Chores" + }, + { + "type": "docs", + "section": "Documentation" + }, + { + "type": "style", + "section": "Styles" + }, + { + "type": "refactor", + "section": "Refactors" + }, + { + "type": "test", + "section": "Tests", + "hidden": true + }, + { + "type": "build", + "section": "Build System" + }, + { + "type": "ci", + "section": "Continuous Integration", + "hidden": true + } + ], + "release-type": "simple", + "extra-files": [ + "README.md", + { + "type": "xml", + "path": "src/Imagekit/Imagekit.csproj", + "xpath": "//Project/PropertyGroup/VersionPrefix" + } + ] +} \ No newline at end of file diff --git a/scripts/bootstrap b/scripts/bootstrap new file mode 100755 index 00000000..2527407d --- /dev/null +++ b/scripts/bootstrap @@ -0,0 +1,8 @@ +#!/usr/bin/env bash + +set -e + +cd "$(dirname "$0")/.." + +echo "==> Running dotnet tool restore" +dotnet tool restore diff --git a/scripts/build b/scripts/build new file mode 100755 index 00000000..3ce1e776 --- /dev/null +++ b/scripts/build @@ -0,0 +1,8 @@ +#!/usr/bin/env bash + +set -e + +cd "$(dirname "$0")/.." + +echo "==> Running dotnet build" +dotnet build diff --git a/scripts/format b/scripts/format new file mode 100755 index 00000000..52057e25 --- /dev/null +++ b/scripts/format @@ -0,0 +1,8 @@ +#!/usr/bin/env bash + +set -e + +cd "$(dirname "$0")/.." + +echo "==> Running dotnet csharpier format" +dotnet csharpier format . diff --git a/scripts/lint b/scripts/lint new file mode 100755 index 00000000..c7ef3cb9 --- /dev/null +++ b/scripts/lint @@ -0,0 +1,9 @@ +#!/usr/bin/env bash + +set -e + +cd "$(dirname "$0")/.." + +echo "==> Running dotnet format" +dotnet format style --severity info --verify-no-changes +dotnet format analyzers --severity info --verify-no-changes diff --git a/scripts/mock b/scripts/mock new file mode 100755 index 00000000..0b28f6ea --- /dev/null +++ b/scripts/mock @@ -0,0 +1,41 @@ +#!/usr/bin/env bash + +set -e + +cd "$(dirname "$0")/.." + +if [[ -n "$1" && "$1" != '--'* ]]; then + URL="$1" + shift +else + URL="$(grep 'openapi_spec_url' .stats.yml | cut -d' ' -f2)" +fi + +# Check if the URL is empty +if [ -z "$URL" ]; then + echo "Error: No OpenAPI spec path/url provided or found in .stats.yml" + exit 1 +fi + +echo "==> Starting mock server with URL ${URL}" + +# Run prism mock on the given spec +if [ "$1" == "--daemon" ]; then + npm exec --package=@stainless-api/prism-cli@5.15.0 -- prism mock "$URL" &> .prism.log & + + # Wait for server to come online + echo -n "Waiting for server" + while ! grep -q "✖ fatal\|Prism is listening" ".prism.log" ; do + echo -n "." + sleep 0.1 + done + + if grep -q "✖ fatal" ".prism.log"; then + cat .prism.log + exit 1 + fi + + echo +else + npm exec --package=@stainless-api/prism-cli@5.15.0 -- prism mock "$URL" +fi diff --git a/scripts/test b/scripts/test new file mode 100755 index 00000000..a562fa22 --- /dev/null +++ b/scripts/test @@ -0,0 +1,56 @@ +#!/usr/bin/env bash + +set -e + +cd -- "$(dirname -- "$0")/.." + +RED='\033[0;31m' +GREEN='\033[0;32m' +YELLOW='\033[0;33m' +NC='\033[0m' # No Color + +function prism_is_running() { + curl --silent "http://localhost:4010" >/dev/null 2>&1 +} + +kill_server_on_port() { + pids=$(lsof -t -i tcp:"$1" || echo "") + if [ "$pids" != "" ]; then + kill "$pids" + echo "Stopped $pids." + fi +} + +function is_overriding_api_base_url() { + [ -n "$TEST_API_BASE_URL" ] +} + +if ! is_overriding_api_base_url && ! prism_is_running ; then + # When we exit this script, make sure to kill the background mock server process + trap 'kill_server_on_port 4010' EXIT + + # Start the dev server + ./scripts/mock --daemon +fi + +if is_overriding_api_base_url ; then + echo -e "${GREEN}✔ Running tests against ${TEST_API_BASE_URL}${NC}" + echo +elif ! prism_is_running ; then + echo -e "${RED}ERROR:${NC} The test suite will not run without a mock Prism server" + echo -e "running against your OpenAPI spec." + echo + echo -e "To run the server, pass in the path or url of your OpenAPI" + echo -e "spec to the prism command:" + echo + echo -e " \$ ${YELLOW}npm exec --package=@stainless-api/prism-cli@5.15.0 -- prism mock path/to/your.openapi.yml${NC}" + echo + + exit 1 +else + echo -e "${GREEN}✔ Mock prism server is running with your OpenAPI spec${NC}" + echo +fi + +echo "==> Running tests" +dotnet test diff --git a/src/Imagekit.Tests/Imagekit.Tests.csproj b/src/Imagekit.Tests/Imagekit.Tests.csproj new file mode 100644 index 00000000..cc370ddc --- /dev/null +++ b/src/Imagekit.Tests/Imagekit.Tests.csproj @@ -0,0 +1,20 @@ + + + net8.0 + false + true + disable + + $(NoWarn),xUnit1004 + + + + + + + + + + + + diff --git a/src/Imagekit.Tests/Services/Accounts/AccountServiceTest.cs b/src/Imagekit.Tests/Services/Accounts/AccountServiceTest.cs new file mode 100644 index 00000000..7be4ff92 --- /dev/null +++ b/src/Imagekit.Tests/Services/Accounts/AccountServiceTest.cs @@ -0,0 +1,3 @@ +namespace Imagekit.Tests.Services.Accounts; + +public class AccountServiceTest : TestBase { } diff --git a/src/Imagekit.Tests/Services/Accounts/Origins/OriginServiceTest.cs b/src/Imagekit.Tests/Services/Accounts/Origins/OriginServiceTest.cs new file mode 100644 index 00000000..596ba623 --- /dev/null +++ b/src/Imagekit.Tests/Services/Accounts/Origins/OriginServiceTest.cs @@ -0,0 +1,73 @@ +using System.Threading.Tasks; +using Imagekit.Models.Accounts.Origins.OriginRequestProperties; + +namespace Imagekit.Tests.Services.Accounts.Origins; + +public class OriginServiceTest : TestBase +{ + [Fact(Skip = "Prism tests are disabled")] + public async Task Create_Works() + { + var originResponse = await this.client.Accounts.Origins.Create( + new() + { + Origin = new S3() + { + AccessKey = "AKIATEST123", + Bucket = "test-bucket", + Name = "My S3 Origin", + SecretKey = "secrettest123", + BaseURLForCanonicalHeader = "https://cdn.example.com", + IncludeCanonicalHeader = false, + Prefix = "images", + }, + } + ); + originResponse.Validate(); + } + + [Fact(Skip = "Prism tests are disabled")] + public async Task Update_Works() + { + var originResponse = await this.client.Accounts.Origins.Update( + new() + { + ID = "id", + Origin = new S3() + { + AccessKey = "AKIATEST123", + Bucket = "test-bucket", + Name = "My S3 Origin", + SecretKey = "secrettest123", + BaseURLForCanonicalHeader = "https://cdn.example.com", + IncludeCanonicalHeader = false, + Prefix = "images", + }, + } + ); + originResponse.Validate(); + } + + [Fact(Skip = "Prism tests are disabled")] + public async Task List_Works() + { + var originResponses = await this.client.Accounts.Origins.List(); + foreach (var item in originResponses) + { + item.Validate(); + } + } + + [Fact(Skip = "Prism tests are disabled")] + public async Task Delete_Works() + { + await this.client.Accounts.Origins.Delete(new() { ID = "id" }); + } + + [Fact(Skip = "Prism tests are disabled")] + public async Task Get_Works() + { + var originResponse = await this.client.Accounts.Origins.Get(new() { ID = "id" }); + originResponse.Validate(); + } +} diff --git a/src/Imagekit.Tests/Services/Accounts/URLEndpoints/URLEndpointServiceTest.cs b/src/Imagekit.Tests/Services/Accounts/URLEndpoints/URLEndpointServiceTest.cs new file mode 100644 index 00000000..e02ba52f --- /dev/null +++ b/src/Imagekit.Tests/Services/Accounts/URLEndpoints/URLEndpointServiceTest.cs @@ -0,0 +1,47 @@ +using System.Threading.Tasks; + +namespace Imagekit.Tests.Services.Accounts.URLEndpoints; + +public class URLEndpointServiceTest : TestBase +{ + [Fact(Skip = "Prism tests are disabled")] + public async Task Create_Works() + { + var urlEndpointResponse = await this.client.Accounts.URLEndpoints.Create( + new() { Description = "My custom URL endpoint" } + ); + urlEndpointResponse.Validate(); + } + + [Fact(Skip = "Prism tests are disabled")] + public async Task Update_Works() + { + var urlEndpointResponse = await this.client.Accounts.URLEndpoints.Update( + new() { ID = "id", Description = "My custom URL endpoint" } + ); + urlEndpointResponse.Validate(); + } + + [Fact(Skip = "Prism tests are disabled")] + public async Task List_Works() + { + var urlEndpointResponses = await this.client.Accounts.URLEndpoints.List(); + foreach (var item in urlEndpointResponses) + { + item.Validate(); + } + } + + [Fact(Skip = "Prism tests are disabled")] + public async Task Delete_Works() + { + await this.client.Accounts.URLEndpoints.Delete(new() { ID = "id" }); + } + + [Fact(Skip = "Prism tests are disabled")] + public async Task Get_Works() + { + var urlEndpointResponse = await this.client.Accounts.URLEndpoints.Get(new() { ID = "id" }); + urlEndpointResponse.Validate(); + } +} diff --git a/src/Imagekit.Tests/Services/Accounts/Usage/UsageServiceTest.cs b/src/Imagekit.Tests/Services/Accounts/Usage/UsageServiceTest.cs new file mode 100644 index 00000000..5c9fec8f --- /dev/null +++ b/src/Imagekit.Tests/Services/Accounts/Usage/UsageServiceTest.cs @@ -0,0 +1,20 @@ +using System; +using System.Threading.Tasks; + +namespace Imagekit.Tests.Services.Accounts.Usage; + +public class UsageServiceTest : TestBase +{ + [Fact(Skip = "Prism tests are disabled")] + public async Task Get_Works() + { + var usage = await this.client.Accounts.Usage.Get( + new() + { + EndDate = DateOnly.Parse("2019-12-27"), + StartDate = DateOnly.Parse("2019-12-27"), + } + ); + usage.Validate(); + } +} diff --git a/src/Imagekit.Tests/Services/Assets/AssetServiceTest.cs b/src/Imagekit.Tests/Services/Assets/AssetServiceTest.cs new file mode 100644 index 00000000..c069b40c --- /dev/null +++ b/src/Imagekit.Tests/Services/Assets/AssetServiceTest.cs @@ -0,0 +1,16 @@ +using System.Threading.Tasks; + +namespace Imagekit.Tests.Services.Assets; + +public class AssetServiceTest : TestBase +{ + [Fact(Skip = "Prism tests are disabled")] + public async Task List_Works() + { + var assets = await this.client.Assets.List(); + foreach (var item in assets) + { + item.Validate(); + } + } +} diff --git a/src/Imagekit.Tests/Services/Beta/BetaServiceTest.cs b/src/Imagekit.Tests/Services/Beta/BetaServiceTest.cs new file mode 100644 index 00000000..df0194f8 --- /dev/null +++ b/src/Imagekit.Tests/Services/Beta/BetaServiceTest.cs @@ -0,0 +1,3 @@ +namespace Imagekit.Tests.Services.Beta; + +public class BetaServiceTest : TestBase { } diff --git a/src/Imagekit.Tests/Services/Beta/V2/Files/FileServiceTest.cs b/src/Imagekit.Tests/Services/Beta/V2/Files/FileServiceTest.cs new file mode 100644 index 00000000..e37025dd --- /dev/null +++ b/src/Imagekit.Tests/Services/Beta/V2/Files/FileServiceTest.cs @@ -0,0 +1,15 @@ +using System.Threading.Tasks; + +namespace Imagekit.Tests.Services.Beta.V2.Files; + +public class FileServiceTest : TestBase +{ + [Fact(Skip = "Prism tests are disabled")] + public async Task Upload_Works() + { + var response = await this.client.Beta.V2.Files.Upload( + new() { File = "a value", FileName = "fileName" } + ); + response.Validate(); + } +} diff --git a/src/Imagekit.Tests/Services/Beta/V2/V2ServiceTest.cs b/src/Imagekit.Tests/Services/Beta/V2/V2ServiceTest.cs new file mode 100644 index 00000000..1b31bb9d --- /dev/null +++ b/src/Imagekit.Tests/Services/Beta/V2/V2ServiceTest.cs @@ -0,0 +1,3 @@ +namespace Imagekit.Tests.Services.Beta.V2; + +public class V2ServiceTest : TestBase { } diff --git a/src/Imagekit.Tests/Services/Cache/CacheServiceTest.cs b/src/Imagekit.Tests/Services/Cache/CacheServiceTest.cs new file mode 100644 index 00000000..879b9a6b --- /dev/null +++ b/src/Imagekit.Tests/Services/Cache/CacheServiceTest.cs @@ -0,0 +1,3 @@ +namespace Imagekit.Tests.Services.Cache; + +public class CacheServiceTest : TestBase { } diff --git a/src/Imagekit.Tests/Services/Cache/Invalidation/InvalidationServiceTest.cs b/src/Imagekit.Tests/Services/Cache/Invalidation/InvalidationServiceTest.cs new file mode 100644 index 00000000..ef5f184f --- /dev/null +++ b/src/Imagekit.Tests/Services/Cache/Invalidation/InvalidationServiceTest.cs @@ -0,0 +1,24 @@ +using System.Threading.Tasks; + +namespace Imagekit.Tests.Services.Cache.Invalidation; + +public class InvalidationServiceTest : TestBase +{ + [Fact(Skip = "Prism tests are disabled")] + public async Task Create_Works() + { + var invalidation = await this.client.Cache.Invalidation.Create( + new() { URL = "https://ik.imagekit.io/your_imagekit_id/default-image.jpg" } + ); + invalidation.Validate(); + } + + [Fact(Skip = "Prism tests are disabled")] + public async Task Get_Works() + { + var invalidation = await this.client.Cache.Invalidation.Get( + new() { RequestID = "requestId" } + ); + invalidation.Validate(); + } +} diff --git a/src/Imagekit.Tests/Services/CustomMetadataFields/CustomMetadataFieldServiceTest.cs b/src/Imagekit.Tests/Services/CustomMetadataFields/CustomMetadataFieldServiceTest.cs new file mode 100644 index 00000000..645b10df --- /dev/null +++ b/src/Imagekit.Tests/Services/CustomMetadataFields/CustomMetadataFieldServiceTest.cs @@ -0,0 +1,59 @@ +using System.Threading.Tasks; +using Imagekit.Models.CustomMetadataFields.CustomMetadataFieldCreateParamsProperties.SchemaProperties; + +namespace Imagekit.Tests.Services.CustomMetadataFields; + +public class CustomMetadataFieldServiceTest : TestBase +{ + [Fact(Skip = "Prism tests are disabled")] + public async Task Create_Works() + { + var customMetadataField = await this.client.CustomMetadataFields.Create( + new() + { + Label = "label", + Name = "name", + Schema = new() + { + Type = Type.Text, + DefaultValue = "string", + IsValueRequired = true, + MaxLength = 0, + MaxValue = "string", + MinLength = 0, + MinValue = "string", + SelectOptions = ["small", "medium", "large", 30, 40, true], + }, + } + ); + customMetadataField.Validate(); + } + + [Fact(Skip = "Prism tests are disabled")] + public async Task Update_Works() + { + var customMetadataField = await this.client.CustomMetadataFields.Update( + new() { ID = "id" } + ); + customMetadataField.Validate(); + } + + [Fact(Skip = "Prism tests are disabled")] + public async Task List_Works() + { + var customMetadataFields = await this.client.CustomMetadataFields.List(); + foreach (var item in customMetadataFields) + { + item.Validate(); + } + } + + [Fact(Skip = "Prism tests are disabled")] + public async Task Delete_Works() + { + var customMetadataField = await this.client.CustomMetadataFields.Delete( + new() { ID = "id" } + ); + customMetadataField.Validate(); + } +} diff --git a/src/Imagekit.Tests/Services/Files/Bulk/BulkServiceTest.cs b/src/Imagekit.Tests/Services/Files/Bulk/BulkServiceTest.cs new file mode 100644 index 00000000..76a30ceb --- /dev/null +++ b/src/Imagekit.Tests/Services/Files/Bulk/BulkServiceTest.cs @@ -0,0 +1,40 @@ +using System.Threading.Tasks; + +namespace Imagekit.Tests.Services.Files.Bulk; + +public class BulkServiceTest : TestBase +{ + [Fact(Skip = "Prism tests are disabled")] + public async Task Delete_Works() + { + var bulk = await this.client.Files.Bulk.Delete(new() { FileIDs = ["string"] }); + bulk.Validate(); + } + + [Fact(Skip = "Prism tests are disabled")] + public async Task AddTags_Works() + { + var response = await this.client.Files.Bulk.AddTags( + new() { FileIDs = ["string"], Tags = ["string"] } + ); + response.Validate(); + } + + [Fact(Skip = "Prism tests are disabled")] + public async Task RemoveAITags_Works() + { + var response = await this.client.Files.Bulk.RemoveAITags( + new() { AITags = ["string"], FileIDs = ["string"] } + ); + response.Validate(); + } + + [Fact(Skip = "Prism tests are disabled")] + public async Task RemoveTags_Works() + { + var response = await this.client.Files.Bulk.RemoveTags( + new() { FileIDs = ["string"], Tags = ["string"] } + ); + response.Validate(); + } +} diff --git a/src/Imagekit.Tests/Services/Files/FileServiceTest.cs b/src/Imagekit.Tests/Services/Files/FileServiceTest.cs new file mode 100644 index 00000000..9241f04d --- /dev/null +++ b/src/Imagekit.Tests/Services/Files/FileServiceTest.cs @@ -0,0 +1,70 @@ +using System.Threading.Tasks; + +namespace Imagekit.Tests.Services.Files; + +public class FileServiceTest : TestBase +{ + [Fact(Skip = "Prism tests are disabled")] + public async Task Update_Works() + { + var file = await this.client.Files.Update(new() { FileID = "fileId" }); + file.Validate(); + } + + [Fact(Skip = "Prism tests are disabled")] + public async Task Delete_Works() + { + await this.client.Files.Delete(new() { FileID = "fileId" }); + } + + [Fact(Skip = "Prism tests are disabled")] + public async Task Copy_Works() + { + var response = await this.client.Files.Copy( + new() + { + DestinationPath = "/folder/to/copy/into/", + SourceFilePath = "/path/to/file.jpg", + } + ); + response.Validate(); + } + + [Fact(Skip = "Prism tests are disabled")] + public async Task Get_Works() + { + var file = await this.client.Files.Get(new() { FileID = "fileId" }); + file.Validate(); + } + + [Fact(Skip = "Prism tests are disabled")] + public async Task Move_Works() + { + var response = await this.client.Files.Move( + new() + { + DestinationPath = "/folder/to/move/into/", + SourceFilePath = "/path/to/file.jpg", + } + ); + response.Validate(); + } + + [Fact(Skip = "Prism tests are disabled")] + public async Task Rename_Works() + { + var response = await this.client.Files.Rename( + new() { FilePath = "/path/to/file.jpg", NewFileName = "newFileName.jpg" } + ); + response.Validate(); + } + + [Fact(Skip = "Prism tests are disabled")] + public async Task Upload_Works() + { + var response = await this.client.Files.Upload( + new() { File = "a value", FileName = "fileName" } + ); + response.Validate(); + } +} diff --git a/src/Imagekit.Tests/Services/Files/Metadata/MetadataServiceTest.cs b/src/Imagekit.Tests/Services/Files/Metadata/MetadataServiceTest.cs new file mode 100644 index 00000000..ae2f33d1 --- /dev/null +++ b/src/Imagekit.Tests/Services/Files/Metadata/MetadataServiceTest.cs @@ -0,0 +1,22 @@ +using System.Threading.Tasks; + +namespace Imagekit.Tests.Services.Files.Metadata; + +public class MetadataServiceTest : TestBase +{ + [Fact(Skip = "Prism tests are disabled")] + public async Task Get_Works() + { + var metadata = await this.client.Files.Metadata.Get(new() { FileID = "fileId" }); + metadata.Validate(); + } + + [Fact(Skip = "Prism tests are disabled")] + public async Task GetFromURL_Works() + { + var metadata = await this.client.Files.Metadata.GetFromURL( + new() { URL = "https://example.com" } + ); + metadata.Validate(); + } +} diff --git a/src/Imagekit.Tests/Services/Files/Versions/VersionServiceTest.cs b/src/Imagekit.Tests/Services/Files/Versions/VersionServiceTest.cs new file mode 100644 index 00000000..a4ddfcdd --- /dev/null +++ b/src/Imagekit.Tests/Services/Files/Versions/VersionServiceTest.cs @@ -0,0 +1,43 @@ +using System.Threading.Tasks; + +namespace Imagekit.Tests.Services.Files.Versions; + +public class VersionServiceTest : TestBase +{ + [Fact(Skip = "Prism tests are disabled")] + public async Task List_Works() + { + var files = await this.client.Files.Versions.List(new() { FileID = "fileId" }); + foreach (var item in files) + { + item.Validate(); + } + } + + [Fact(Skip = "Prism tests are disabled")] + public async Task Delete_Works() + { + var version = await this.client.Files.Versions.Delete( + new() { FileID = "fileId", VersionID = "versionId" } + ); + version.Validate(); + } + + [Fact(Skip = "Prism tests are disabled")] + public async Task Get_Works() + { + var file = await this.client.Files.Versions.Get( + new() { FileID = "fileId", VersionID = "versionId" } + ); + file.Validate(); + } + + [Fact(Skip = "Prism tests are disabled")] + public async Task Restore_Works() + { + var file = await this.client.Files.Versions.Restore( + new() { FileID = "fileId", VersionID = "versionId" } + ); + file.Validate(); + } +} diff --git a/src/Imagekit.Tests/Services/Folders/FolderServiceTest.cs b/src/Imagekit.Tests/Services/Folders/FolderServiceTest.cs new file mode 100644 index 00000000..21dcc7f5 --- /dev/null +++ b/src/Imagekit.Tests/Services/Folders/FolderServiceTest.cs @@ -0,0 +1,57 @@ +using System.Threading.Tasks; + +namespace Imagekit.Tests.Services.Folders; + +public class FolderServiceTest : TestBase +{ + [Fact(Skip = "Prism tests are disabled")] + public async Task Create_Works() + { + var folder = await this.client.Folders.Create( + new() { FolderName = "folderName", ParentFolderPath = "parentFolderPath" } + ); + folder.Validate(); + } + + [Fact(Skip = "Prism tests are disabled")] + public async Task Delete_Works() + { + var folder = await this.client.Folders.Delete(new() { FolderPath = "folderPath" }); + folder.Validate(); + } + + [Fact(Skip = "Prism tests are disabled")] + public async Task Copy_Works() + { + var response = await this.client.Folders.Copy( + new() + { + DestinationPath = "/path/of/destination/folder", + SourceFolderPath = "/path/of/source/folder", + } + ); + response.Validate(); + } + + [Fact(Skip = "Prism tests are disabled")] + public async Task Move_Works() + { + var response = await this.client.Folders.Move( + new() + { + DestinationPath = "/path/of/destination/folder", + SourceFolderPath = "/path/of/source/folder", + } + ); + response.Validate(); + } + + [Fact(Skip = "Prism tests are disabled")] + public async Task Rename_Works() + { + var response = await this.client.Folders.Rename( + new() { FolderPath = "/path/of/folder", NewFolderName = "new-folder-name" } + ); + response.Validate(); + } +} diff --git a/src/Imagekit.Tests/Services/Folders/Job/JobServiceTest.cs b/src/Imagekit.Tests/Services/Folders/Job/JobServiceTest.cs new file mode 100644 index 00000000..9ec1497d --- /dev/null +++ b/src/Imagekit.Tests/Services/Folders/Job/JobServiceTest.cs @@ -0,0 +1,13 @@ +using System.Threading.Tasks; + +namespace Imagekit.Tests.Services.Folders.Job; + +public class JobServiceTest : TestBase +{ + [Fact(Skip = "Prism tests are disabled")] + public async Task Get_Works() + { + var job = await this.client.Folders.Job.Get(new() { JobID = "jobId" }); + job.Validate(); + } +} diff --git a/src/Imagekit.Tests/Services/Webhooks/WebhookServiceTest.cs b/src/Imagekit.Tests/Services/Webhooks/WebhookServiceTest.cs new file mode 100644 index 00000000..88914250 --- /dev/null +++ b/src/Imagekit.Tests/Services/Webhooks/WebhookServiceTest.cs @@ -0,0 +1,3 @@ +namespace Imagekit.Tests.Services.Webhooks; + +public class WebhookServiceTest : TestBase { } diff --git a/src/Imagekit.Tests/TestBase.cs b/src/Imagekit.Tests/TestBase.cs new file mode 100644 index 00000000..a045d668 --- /dev/null +++ b/src/Imagekit.Tests/TestBase.cs @@ -0,0 +1,21 @@ +using System; +using Imagekit; + +namespace Imagekit.Tests; + +public class TestBase +{ + protected IImageKitClient client; + + public TestBase() + { + client = new ImageKitClient() + { + BaseUrl = new Uri( + Environment.GetEnvironmentVariable("TEST_API_BASE_URL") ?? "http://localhost:4010" + ), + PrivateAPIKey = "My Private API Key", + Password = "My Password", + }; + } +} diff --git a/src/Imagekit/ApiEnum.cs b/src/Imagekit/ApiEnum.cs new file mode 100644 index 00000000..29b6a839 --- /dev/null +++ b/src/Imagekit/ApiEnum.cs @@ -0,0 +1,56 @@ +using System; +using System.Text.Json; +using System.Text.Json.Serialization; + +namespace Imagekit; + +public record struct ApiEnum(JsonElement Json) + where TEnum : struct, Enum +{ + public readonly TRaw Raw() => + JsonSerializer.Deserialize(this.Json, ModelBase.SerializerOptions) + ?? throw new NullReferenceException(nameof(this.Json)); + + public readonly TEnum Value() => + JsonSerializer.Deserialize(this.Json, ModelBase.SerializerOptions); + + public readonly void Validate() + { + if (!Enum.IsDefined(Value())) + { + throw new Exception(); + } + } + + public static implicit operator TRaw(ApiEnum value) => value.Raw(); + + public static implicit operator TEnum(ApiEnum value) => value.Value(); + + public static implicit operator ApiEnum(TRaw value) => + new(JsonSerializer.SerializeToElement(value, ModelBase.SerializerOptions)); + + public static implicit operator ApiEnum(TEnum value) => + new(JsonSerializer.SerializeToElement(value, ModelBase.SerializerOptions)); +} + +sealed class ApiEnumConverter : JsonConverter> + where TEnum : struct, Enum +{ + public override ApiEnum Read( + ref Utf8JsonReader reader, + Type typeToConvert, + JsonSerializerOptions options + ) + { + return new(JsonSerializer.Deserialize(ref reader, options)); + } + + public override void Write( + Utf8JsonWriter writer, + ApiEnum value, + JsonSerializerOptions options + ) + { + JsonSerializer.Serialize(writer, value.Json, options); + } +} diff --git a/src/Imagekit/HttpException.cs b/src/Imagekit/HttpException.cs new file mode 100644 index 00000000..2986ea2c --- /dev/null +++ b/src/Imagekit/HttpException.cs @@ -0,0 +1,29 @@ +using System; +using System.Diagnostics.CodeAnalysis; +using System.Net; + +namespace Imagekit; + +public sealed class HttpException : Exception +{ + public required HttpStatusCode? StatusCode { get; set; } + public required string ResponseBody { get; set; } + public override string Message + { + get + { + return string.Format( + "Status Code: {0}\n{1}", + this.StatusCode?.ToString() ?? "Unknown", + this.ResponseBody + ); + } + } + + [SetsRequiredMembers] + public HttpException(HttpStatusCode? statusCode, string responseBody) + { + this.StatusCode = statusCode; + this.ResponseBody = responseBody; + } +} diff --git a/src/Imagekit/IImageKitClient.cs b/src/Imagekit/IImageKitClient.cs new file mode 100644 index 00000000..784f4b94 --- /dev/null +++ b/src/Imagekit/IImageKitClient.cs @@ -0,0 +1,56 @@ +using System; +using System.Net.Http; +using Imagekit.Services.Accounts; +using Imagekit.Services.Assets; +using Imagekit.Services.Beta; +using Imagekit.Services.Cache; +using Imagekit.Services.CustomMetadataFields; +using Imagekit.Services.Files; +using Imagekit.Services.Folders; +using Imagekit.Services.Webhooks; + +namespace Imagekit; + +public interface IImageKitClient +{ + HttpClient HttpClient { get; init; } + + Uri BaseUrl { get; init; } + + /// + /// Your ImageKit private API key (it starts with `private_`). You can view and + /// manage API keys in the [dashboard](https://imagekit.io/dashboard/developer/api-keys). + /// + string PrivateAPIKey { get; init; } + + /// + /// ImageKit Basic Auth only uses the username field and ignores the password. + /// This field is unused. + /// + string? Password { get; init; } + + /// + /// Your ImageKit webhook secret. This is used by the SDK to verify webhook signatures. + /// It starts with a `whsec_` prefix. You can view and manage your webhook secret + /// in the [dashboard](https://imagekit.io/dashboard/developer/webhooks). Treat + /// the secret like a password, keep it private and do not expose it publicly. + /// Learn more about [webhook verification](https://imagekit.io/docs/webhooks#verify-webhook-signature). + /// + string? WebhookSecret { get; init; } + + ICustomMetadataFieldService CustomMetadataFields { get; } + + IFileService Files { get; } + + IAssetService Assets { get; } + + ICacheService Cache { get; } + + IFolderService Folders { get; } + + IAccountService Accounts { get; } + + IBetaService Beta { get; } + + IWebhookService Webhooks { get; } +} diff --git a/src/Imagekit/IVariant.cs b/src/Imagekit/IVariant.cs new file mode 100644 index 00000000..1aebab56 --- /dev/null +++ b/src/Imagekit/IVariant.cs @@ -0,0 +1,8 @@ +namespace Imagekit; + +interface IVariant + where TVariant : IVariant +{ + static abstract TVariant From(TValue value); + TValue Value { get; } +} diff --git a/src/Imagekit/ImageKitClient.cs b/src/Imagekit/ImageKitClient.cs new file mode 100644 index 00000000..73466d00 --- /dev/null +++ b/src/Imagekit/ImageKitClient.cs @@ -0,0 +1,116 @@ +using System; +using System.Net.Http; +using Imagekit.Services.Accounts; +using Imagekit.Services.Assets; +using Imagekit.Services.Beta; +using Imagekit.Services.Cache; +using Imagekit.Services.CustomMetadataFields; +using Imagekit.Services.Files; +using Imagekit.Services.Folders; +using Imagekit.Services.Webhooks; + +namespace Imagekit; + +public sealed class ImageKitClient : IImageKitClient +{ + public HttpClient HttpClient { get; init; } = new(); + + Lazy _baseUrl = new(() => + new Uri( + Environment.GetEnvironmentVariable("IMAGE_KIT_BASE_URL") ?? "https://api.imagekit.io" + ) + ); + public Uri BaseUrl + { + get { return _baseUrl.Value; } + init { _baseUrl = new(() => value); } + } + + Lazy _privateAPIKey = new(() => + Environment.GetEnvironmentVariable("IMAGEKIT_PRIVATE_API_KEY") + ?? throw new ArgumentNullException(nameof(PrivateAPIKey)) + ); + public string PrivateAPIKey + { + get { return _privateAPIKey.Value; } + init { _privateAPIKey = new(() => value); } + } + + Lazy _password = new(() => + Environment.GetEnvironmentVariable("OPTIONAL_IMAGEKIT_IGNORES_THIS") ?? "do_not_set" + ); + public string? Password + { + get { return _password.Value; } + init { _password = new(() => value); } + } + + Lazy _webhookSecret = new(() => + Environment.GetEnvironmentVariable("IMAGEKIT_WEBHOOK_SECRET") + ); + public string? WebhookSecret + { + get { return _webhookSecret.Value; } + init { _webhookSecret = new(() => value); } + } + + readonly Lazy _customMetadataFields; + public ICustomMetadataFieldService CustomMetadataFields + { + get { return _customMetadataFields.Value; } + } + + readonly Lazy _files; + public IFileService Files + { + get { return _files.Value; } + } + + readonly Lazy _assets; + public IAssetService Assets + { + get { return _assets.Value; } + } + + readonly Lazy _cache; + public ICacheService Cache + { + get { return _cache.Value; } + } + + readonly Lazy _folders; + public IFolderService Folders + { + get { return _folders.Value; } + } + + readonly Lazy _accounts; + public IAccountService Accounts + { + get { return _accounts.Value; } + } + + readonly Lazy _beta; + public IBetaService Beta + { + get { return _beta.Value; } + } + + readonly Lazy _webhooks; + public IWebhookService Webhooks + { + get { return _webhooks.Value; } + } + + public ImageKitClient() + { + _customMetadataFields = new(() => new CustomMetadataFieldService(this)); + _files = new(() => new FileService(this)); + _assets = new(() => new AssetService(this)); + _cache = new(() => new CacheService(this)); + _folders = new(() => new FolderService(this)); + _accounts = new(() => new AccountService(this)); + _beta = new(() => new BetaService(this)); + _webhooks = new(() => new WebhookService(this)); + } +} diff --git a/src/Imagekit/Imagekit.csproj b/src/Imagekit/Imagekit.csproj new file mode 100644 index 00000000..b70aa523 --- /dev/null +++ b/src/Imagekit/Imagekit.csproj @@ -0,0 +1,32 @@ + + + + The official .NET library for the Image Kit C# service API. + + SDK Code Generation Image Kit C# + Apache-2.0 + enable + 0.0.2 + net8.0 + latest + + true + README.md + https://www.github.com/imagekit-developer/imagekit-dotnet + git + + true + true + + $(NoWarn),1570,1573,1574,1591 + + $(NoWarn),IL2026,IL3050 + Debug;Release + true + true + disable + + + + + diff --git a/src/Imagekit/ModelBase.cs b/src/Imagekit/ModelBase.cs new file mode 100644 index 00000000..7e43b00e --- /dev/null +++ b/src/Imagekit/ModelBase.cs @@ -0,0 +1,202 @@ +using System.Collections.Generic; +using System.Text.Json; +using Imagekit.Models; +using Imagekit.Models.Cache.Invalidation.InvalidationGetResponseProperties; +using Imagekit.Models.CustomMetadataFields.CustomMetadataFieldProperties.SchemaProperties; +using Imagekit.Models.Files.FileUpdateParamsProperties.UpdateProperties.UpdateFileDetailsProperties.ExtensionProperties.AutoTaggingExtensionProperties; +using Imagekit.Models.Files.FileUpdateResponseProperties.IntersectionMember1Properties.ExtensionStatusProperties; +using Imagekit.Models.Files.FileUploadParamsProperties.TransformationProperties.PostProperties.AbsProperties; +using Imagekit.Models.ImageOverlayProperties.IntersectionMember1Properties; +using Imagekit.Models.OverlayPositionProperties; +using Imagekit.Models.SubtitleOverlayTransformationProperties; +using Imagekit.Models.TextOverlayTransformationProperties; +using Imagekit.Models.Webhooks.VideoTransformationAcceptedEventProperties.DataProperties.TransformationProperties.OptionsProperties; +using Imagekit.Models.Webhooks.VideoTransformationErrorEventProperties.DataProperties.TransformationProperties.ErrorProperties; +using AbsProperties = Imagekit.Models.Beta.V2.Files.FileUploadParamsProperties.TransformationProperties.PostProperties.AbsProperties; +using AssetListParamsProperties = Imagekit.Models.Assets.AssetListParamsProperties; +using AutoTaggingExtensionProperties = Imagekit.Models.Files.FileUploadParamsProperties.ExtensionProperties.AutoTaggingExtensionProperties; +using ExtensionStatusProperties = Imagekit.Models.Files.FileUploadResponseProperties.ExtensionStatusProperties; +using FileProperties = Imagekit.Models.Files.FileProperties; +using FileUploadParamsProperties = Imagekit.Models.Files.FileUploadParamsProperties; +using FolderProperties = Imagekit.Models.Files.FolderProperties; +using IntersectionMember1Properties = Imagekit.Models.SubtitleOverlayProperties.IntersectionMember1Properties; +using JobGetResponseProperties = Imagekit.Models.Folders.Job.JobGetResponseProperties; +using OptionsProperties = Imagekit.Models.Webhooks.VideoTransformationErrorEventProperties.DataProperties.TransformationProperties.OptionsProperties; +using SchemaProperties = Imagekit.Models.CustomMetadataFields.CustomMetadataFieldCreateParamsProperties.SchemaProperties; +using TransformationProperties = Imagekit.Models.TransformationProperties; + +namespace Imagekit; + +public abstract record class ModelBase +{ + public Dictionary Properties { get; set; } = []; + + internal static readonly JsonSerializerOptions SerializerOptions = new() + { + Converters = + { + new ApiEnumConverter(), + new ApiEnumConverter(), + new ApiEnumConverter(), + new ApiEnumConverter(), + new ApiEnumConverter(), + new ApiEnumConverter< + string, + global::Imagekit.Models.TextOverlayProperties.IntersectionMember1Properties.Encoding + >(), + new ApiEnumConverter(), + new ApiEnumConverter(), + new ApiEnumConverter(), + new ApiEnumConverter(), + new ApiEnumConverter(), + new ApiEnumConverter(), + new ApiEnumConverter(), + new ApiEnumConverter(), + new ApiEnumConverter(), + new ApiEnumConverter(), + new ApiEnumConverter(), + new ApiEnumConverter(), + new ApiEnumConverter(), + new ApiEnumConverter(), + new ApiEnumConverter(), + new ApiEnumConverter(), + new ApiEnumConverter< + string, + global::Imagekit.Models.VideoOverlayProperties.IntersectionMember1Properties.Encoding + >(), + new ApiEnumConverter(), + new ApiEnumConverter(), + new ApiEnumConverter(), + new ApiEnumConverter(), + new ApiEnumConverter(), + new ApiEnumConverter(), + new ApiEnumConverter(), + new ApiEnumConverter(), + new ApiEnumConverter(), + new ApiEnumConverter(), + new ApiEnumConverter(), + new ApiEnumConverter(), + new ApiEnumConverter(), + new ApiEnumConverter(), + new ApiEnumConverter(), + new ApiEnumConverter(), + new ApiEnumConverter(), + new ApiEnumConverter(), + new ApiEnumConverter(), + new ApiEnumConverter(), + new ApiEnumConverter(), + new ApiEnumConverter(), + new ApiEnumConverter< + string, + global::Imagekit.Models.Beta.V2.Files.FileUploadResponseProperties.ExtensionStatusProperties.AIAutoDescription + >(), + new ApiEnumConverter< + string, + global::Imagekit.Models.Beta.V2.Files.FileUploadResponseProperties.ExtensionStatusProperties.AwsAutoTagging + >(), + new ApiEnumConverter< + string, + global::Imagekit.Models.Beta.V2.Files.FileUploadResponseProperties.ExtensionStatusProperties.GoogleAutoTagging + >(), + new ApiEnumConverter< + string, + global::Imagekit.Models.Beta.V2.Files.FileUploadResponseProperties.ExtensionStatusProperties.RemoveBg + >(), + new ApiEnumConverter< + string, + global::Imagekit.Models.Beta.V2.Files.FileUploadParamsProperties.ExtensionProperties.AutoTaggingExtensionProperties.Name + >(), + new ApiEnumConverter< + string, + global::Imagekit.Models.Beta.V2.Files.FileUploadParamsProperties.ResponseField + >(), + new ApiEnumConverter(), + new ApiEnumConverter< + string, + global::Imagekit.Models.Webhooks.UploadPostTransformErrorEventProperties.RequestProperties.TransformationProperties.Type + >(), + new ApiEnumConverter< + string, + global::Imagekit.Models.Webhooks.UploadPostTransformErrorEventProperties.RequestProperties.TransformationProperties.Protocol + >(), + new ApiEnumConverter< + string, + global::Imagekit.Models.Webhooks.UploadPostTransformSuccessEventProperties.RequestProperties.TransformationProperties.Type + >(), + new ApiEnumConverter< + string, + global::Imagekit.Models.Webhooks.UploadPostTransformSuccessEventProperties.RequestProperties.TransformationProperties.Protocol + >(), + new ApiEnumConverter< + string, + global::Imagekit.Models.Webhooks.UploadPreTransformSuccessEventProperties.DataProperties.ExtensionStatusProperties.AIAutoDescription + >(), + new ApiEnumConverter< + string, + global::Imagekit.Models.Webhooks.UploadPreTransformSuccessEventProperties.DataProperties.ExtensionStatusProperties.AwsAutoTagging + >(), + new ApiEnumConverter< + string, + global::Imagekit.Models.Webhooks.UploadPreTransformSuccessEventProperties.DataProperties.ExtensionStatusProperties.GoogleAutoTagging + >(), + new ApiEnumConverter< + string, + global::Imagekit.Models.Webhooks.UploadPreTransformSuccessEventProperties.DataProperties.ExtensionStatusProperties.RemoveBg + >(), + new ApiEnumConverter< + string, + global::Imagekit.Models.Webhooks.VideoTransformationAcceptedEventProperties.DataProperties.TransformationProperties.Type + >(), + new ApiEnumConverter(), + new ApiEnumConverter(), + new ApiEnumConverter(), + new ApiEnumConverter(), + new ApiEnumConverter< + string, + global::Imagekit.Models.Webhooks.VideoTransformationErrorEventProperties.DataProperties.TransformationProperties.Type + >(), + new ApiEnumConverter(), + new ApiEnumConverter(), + new ApiEnumConverter(), + new ApiEnumConverter(), + new ApiEnumConverter(), + new ApiEnumConverter< + string, + global::Imagekit.Models.Webhooks.VideoTransformationReadyEventProperties.DataProperties.TransformationProperties.Type + >(), + new ApiEnumConverter< + string, + global::Imagekit.Models.Webhooks.VideoTransformationReadyEventProperties.DataProperties.TransformationProperties.OptionsProperties.AudioCodec + >(), + new ApiEnumConverter< + string, + global::Imagekit.Models.Webhooks.VideoTransformationReadyEventProperties.DataProperties.TransformationProperties.OptionsProperties.Format + >(), + new ApiEnumConverter< + string, + global::Imagekit.Models.Webhooks.VideoTransformationReadyEventProperties.DataProperties.TransformationProperties.OptionsProperties.StreamProtocol + >(), + new ApiEnumConverter< + string, + global::Imagekit.Models.Webhooks.VideoTransformationReadyEventProperties.DataProperties.TransformationProperties.OptionsProperties.VideoCodec + >(), + }, + }; + + static readonly JsonSerializerOptions _toStringSerializerOptions = new(SerializerOptions) + { + WriteIndented = true, + }; + + public sealed override string? ToString() + { + return JsonSerializer.Serialize(this.Properties, _toStringSerializerOptions); + } + + public abstract void Validate(); +} + +interface IFromRaw +{ + static abstract T FromRawUnchecked(Dictionary properties); +} diff --git a/src/Imagekit/ModelConverter.cs b/src/Imagekit/ModelConverter.cs new file mode 100644 index 00000000..0c40a8ef --- /dev/null +++ b/src/Imagekit/ModelConverter.cs @@ -0,0 +1,30 @@ +using System; +using System.Collections.Generic; +using System.Text.Json; +using System.Text.Json.Serialization; + +namespace Imagekit; + +sealed class ModelConverter : JsonConverter + where TModel : ModelBase, IFromRaw +{ + public override TModel? Read( + ref Utf8JsonReader reader, + Type typeToConvert, + JsonSerializerOptions options + ) + { + Dictionary? properties = JsonSerializer.Deserialize< + Dictionary + >(ref reader, options); + if (properties == null) + return null; + + return TModel.FromRawUnchecked(properties); + } + + public override void Write(Utf8JsonWriter writer, TModel value, JsonSerializerOptions options) + { + JsonSerializer.Serialize(writer, value.Properties, options); + } +} diff --git a/src/Imagekit/Models/Accounts/Origins/OriginCreateParams.cs b/src/Imagekit/Models/Accounts/Origins/OriginCreateParams.cs new file mode 100644 index 00000000..b485becb --- /dev/null +++ b/src/Imagekit/Models/Accounts/Origins/OriginCreateParams.cs @@ -0,0 +1,64 @@ +using System; +using System.Collections.Generic; +using System.Net.Http; +using System.Text; +using System.Text.Json; + +namespace Imagekit.Models.Accounts.Origins; + +/// +/// **Note:** This API is currently in beta. Creates a new origin and returns the +/// origin object. +/// +public sealed record class OriginCreateParams : ParamsBase +{ + public Dictionary BodyProperties { get; set; } = []; + + /// + /// Schema for origin request resources. + /// + public required OriginRequest Origin + { + get + { + if (!this.BodyProperties.TryGetValue("origin", out JsonElement element)) + throw new ArgumentOutOfRangeException("origin", "Missing required argument"); + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions) + ?? throw new ArgumentNullException("origin"); + } + set + { + this.BodyProperties["origin"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + public override Uri Url(IImageKitClient client) + { + return new UriBuilder(client.BaseUrl.ToString().TrimEnd('/') + "/v1/accounts/origins") + { + Query = this.QueryString(client), + }.Uri; + } + + public StringContent BodyContent() + { + return new( + JsonSerializer.Serialize(this.BodyProperties), + Encoding.UTF8, + "application/json" + ); + } + + public void AddHeadersToRequest(HttpRequestMessage request, IImageKitClient client) + { + ParamsBase.AddDefaultHeaders(request, client); + foreach (var item in this.HeaderProperties) + { + ParamsBase.AddHeaderElementToRequest(request, item.Key, item.Value); + } + } +} diff --git a/src/Imagekit/Models/Accounts/Origins/OriginDeleteParams.cs b/src/Imagekit/Models/Accounts/Origins/OriginDeleteParams.cs new file mode 100644 index 00000000..826a127b --- /dev/null +++ b/src/Imagekit/Models/Accounts/Origins/OriginDeleteParams.cs @@ -0,0 +1,34 @@ +using System; +using System.Net.Http; + +namespace Imagekit.Models.Accounts.Origins; + +/// +/// **Note:** This API is currently in beta. Permanently removes the origin identified +/// by `id`. If the origin is in use by any URL‑endpoints, the API will return an +/// error. +/// +public sealed record class OriginDeleteParams : ParamsBase +{ + public required string ID; + + public override Uri Url(IImageKitClient client) + { + return new UriBuilder( + client.BaseUrl.ToString().TrimEnd('/') + + string.Format("/v1/accounts/origins/{0}", this.ID) + ) + { + Query = this.QueryString(client), + }.Uri; + } + + public void AddHeadersToRequest(HttpRequestMessage request, IImageKitClient client) + { + ParamsBase.AddDefaultHeaders(request, client); + foreach (var item in this.HeaderProperties) + { + ParamsBase.AddHeaderElementToRequest(request, item.Key, item.Value); + } + } +} diff --git a/src/Imagekit/Models/Accounts/Origins/OriginGetParams.cs b/src/Imagekit/Models/Accounts/Origins/OriginGetParams.cs new file mode 100644 index 00000000..1387a2da --- /dev/null +++ b/src/Imagekit/Models/Accounts/Origins/OriginGetParams.cs @@ -0,0 +1,33 @@ +using System; +using System.Net.Http; + +namespace Imagekit.Models.Accounts.Origins; + +/// +/// **Note:** This API is currently in beta. Retrieves the origin identified by +/// `id`. +/// +public sealed record class OriginGetParams : ParamsBase +{ + public required string ID; + + public override Uri Url(IImageKitClient client) + { + return new UriBuilder( + client.BaseUrl.ToString().TrimEnd('/') + + string.Format("/v1/accounts/origins/{0}", this.ID) + ) + { + Query = this.QueryString(client), + }.Uri; + } + + public void AddHeadersToRequest(HttpRequestMessage request, IImageKitClient client) + { + ParamsBase.AddDefaultHeaders(request, client); + foreach (var item in this.HeaderProperties) + { + ParamsBase.AddHeaderElementToRequest(request, item.Key, item.Value); + } + } +} diff --git a/src/Imagekit/Models/Accounts/Origins/OriginListParams.cs b/src/Imagekit/Models/Accounts/Origins/OriginListParams.cs new file mode 100644 index 00000000..29897449 --- /dev/null +++ b/src/Imagekit/Models/Accounts/Origins/OriginListParams.cs @@ -0,0 +1,28 @@ +using System; +using System.Net.Http; + +namespace Imagekit.Models.Accounts.Origins; + +/// +/// **Note:** This API is currently in beta. Returns an array of all configured +/// origins for the current account. +/// +public sealed record class OriginListParams : ParamsBase +{ + public override Uri Url(IImageKitClient client) + { + return new UriBuilder(client.BaseUrl.ToString().TrimEnd('/') + "/v1/accounts/origins") + { + Query = this.QueryString(client), + }.Uri; + } + + public void AddHeadersToRequest(HttpRequestMessage request, IImageKitClient client) + { + ParamsBase.AddDefaultHeaders(request, client); + foreach (var item in this.HeaderProperties) + { + ParamsBase.AddHeaderElementToRequest(request, item.Key, item.Value); + } + } +} diff --git a/src/Imagekit/Models/Accounts/Origins/OriginRequest.cs b/src/Imagekit/Models/Accounts/Origins/OriginRequest.cs new file mode 100644 index 00000000..be08db0e --- /dev/null +++ b/src/Imagekit/Models/Accounts/Origins/OriginRequest.cs @@ -0,0 +1,360 @@ +using System; +using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; +using System.Text.Json; +using System.Text.Json.Serialization; +using Imagekit.Models.Accounts.Origins.OriginRequestProperties; +using OriginRequestVariants = Imagekit.Models.Accounts.Origins.OriginRequestVariants; + +namespace Imagekit.Models.Accounts.Origins; + +/// +/// Schema for origin request resources. +/// +[JsonConverter(typeof(OriginRequestConverter))] +public abstract record class OriginRequest +{ + internal OriginRequest() { } + + public static implicit operator OriginRequest(S3 value) => new OriginRequestVariants::S3(value); + + public static implicit operator OriginRequest(S3Compatible value) => + new OriginRequestVariants::S3Compatible(value); + + public static implicit operator OriginRequest(CloudinaryBackup value) => + new OriginRequestVariants::CloudinaryBackup(value); + + public static implicit operator OriginRequest(WebFolder value) => + new OriginRequestVariants::WebFolder(value); + + public static implicit operator OriginRequest(WebProxy value) => + new OriginRequestVariants::WebProxy(value); + + public static implicit operator OriginRequest(Gcs value) => + new OriginRequestVariants::Gcs(value); + + public static implicit operator OriginRequest(AzureBlob value) => + new OriginRequestVariants::AzureBlob(value); + + public static implicit operator OriginRequest(AkeneoPim value) => + new OriginRequestVariants::AkeneoPim(value); + + public bool TryPickS3([NotNullWhen(true)] out S3? value) + { + value = (this as OriginRequestVariants::S3)?.Value; + return value != null; + } + + public bool TryPickS3Compatible([NotNullWhen(true)] out S3Compatible? value) + { + value = (this as OriginRequestVariants::S3Compatible)?.Value; + return value != null; + } + + public bool TryPickCloudinaryBackup([NotNullWhen(true)] out CloudinaryBackup? value) + { + value = (this as OriginRequestVariants::CloudinaryBackup)?.Value; + return value != null; + } + + public bool TryPickWebFolder([NotNullWhen(true)] out WebFolder? value) + { + value = (this as OriginRequestVariants::WebFolder)?.Value; + return value != null; + } + + public bool TryPickWebProxy([NotNullWhen(true)] out WebProxy? value) + { + value = (this as OriginRequestVariants::WebProxy)?.Value; + return value != null; + } + + public bool TryPickGcs([NotNullWhen(true)] out Gcs? value) + { + value = (this as OriginRequestVariants::Gcs)?.Value; + return value != null; + } + + public bool TryPickAzureBlob([NotNullWhen(true)] out AzureBlob? value) + { + value = (this as OriginRequestVariants::AzureBlob)?.Value; + return value != null; + } + + public bool TryPickAkeneoPim([NotNullWhen(true)] out AkeneoPim? value) + { + value = (this as OriginRequestVariants::AkeneoPim)?.Value; + return value != null; + } + + public void Switch( + Action s3, + Action s3Compatible, + Action cloudinaryBackup, + Action webFolder, + Action webProxy, + Action gcs, + Action azureBlob, + Action akeneoPim + ) + { + switch (this) + { + case OriginRequestVariants::S3 inner: + s3(inner); + break; + case OriginRequestVariants::S3Compatible inner: + s3Compatible(inner); + break; + case OriginRequestVariants::CloudinaryBackup inner: + cloudinaryBackup(inner); + break; + case OriginRequestVariants::WebFolder inner: + webFolder(inner); + break; + case OriginRequestVariants::WebProxy inner: + webProxy(inner); + break; + case OriginRequestVariants::Gcs inner: + gcs(inner); + break; + case OriginRequestVariants::AzureBlob inner: + azureBlob(inner); + break; + case OriginRequestVariants::AkeneoPim inner: + akeneoPim(inner); + break; + default: + throw new InvalidOperationException(); + } + } + + public T Match( + Func s3, + Func s3Compatible, + Func cloudinaryBackup, + Func webFolder, + Func webProxy, + Func gcs, + Func azureBlob, + Func akeneoPim + ) + { + return this switch + { + OriginRequestVariants::S3 inner => s3(inner), + OriginRequestVariants::S3Compatible inner => s3Compatible(inner), + OriginRequestVariants::CloudinaryBackup inner => cloudinaryBackup(inner), + OriginRequestVariants::WebFolder inner => webFolder(inner), + OriginRequestVariants::WebProxy inner => webProxy(inner), + OriginRequestVariants::Gcs inner => gcs(inner), + OriginRequestVariants::AzureBlob inner => azureBlob(inner), + OriginRequestVariants::AkeneoPim inner => akeneoPim(inner), + _ => throw new InvalidOperationException(), + }; + } + + public abstract void Validate(); +} + +sealed class OriginRequestConverter : JsonConverter +{ + public override OriginRequest? Read( + ref Utf8JsonReader reader, + Type typeToConvert, + JsonSerializerOptions options + ) + { + var json = JsonSerializer.Deserialize(ref reader, options); + string? type; + try + { + type = json.GetProperty("type").GetString(); + } + catch + { + type = null; + } + + switch (type) + { + case "S3": + { + List exceptions = []; + + try + { + var deserialized = JsonSerializer.Deserialize(json, options); + if (deserialized != null) + { + return new OriginRequestVariants::S3(deserialized); + } + } + catch (JsonException e) + { + exceptions.Add(e); + } + + throw new AggregateException(exceptions); + } + case "S3_COMPATIBLE": + { + List exceptions = []; + + try + { + var deserialized = JsonSerializer.Deserialize(json, options); + if (deserialized != null) + { + return new OriginRequestVariants::S3Compatible(deserialized); + } + } + catch (JsonException e) + { + exceptions.Add(e); + } + + throw new AggregateException(exceptions); + } + case "CLOUDINARY_BACKUP": + { + List exceptions = []; + + try + { + var deserialized = JsonSerializer.Deserialize(json, options); + if (deserialized != null) + { + return new OriginRequestVariants::CloudinaryBackup(deserialized); + } + } + catch (JsonException e) + { + exceptions.Add(e); + } + + throw new AggregateException(exceptions); + } + case "WEB_FOLDER": + { + List exceptions = []; + + try + { + var deserialized = JsonSerializer.Deserialize(json, options); + if (deserialized != null) + { + return new OriginRequestVariants::WebFolder(deserialized); + } + } + catch (JsonException e) + { + exceptions.Add(e); + } + + throw new AggregateException(exceptions); + } + case "WEB_PROXY": + { + List exceptions = []; + + try + { + var deserialized = JsonSerializer.Deserialize(json, options); + if (deserialized != null) + { + return new OriginRequestVariants::WebProxy(deserialized); + } + } + catch (JsonException e) + { + exceptions.Add(e); + } + + throw new AggregateException(exceptions); + } + case "GCS": + { + List exceptions = []; + + try + { + var deserialized = JsonSerializer.Deserialize(json, options); + if (deserialized != null) + { + return new OriginRequestVariants::Gcs(deserialized); + } + } + catch (JsonException e) + { + exceptions.Add(e); + } + + throw new AggregateException(exceptions); + } + case "AZURE_BLOB": + { + List exceptions = []; + + try + { + var deserialized = JsonSerializer.Deserialize(json, options); + if (deserialized != null) + { + return new OriginRequestVariants::AzureBlob(deserialized); + } + } + catch (JsonException e) + { + exceptions.Add(e); + } + + throw new AggregateException(exceptions); + } + case "AKENEO_PIM": + { + List exceptions = []; + + try + { + var deserialized = JsonSerializer.Deserialize(json, options); + if (deserialized != null) + { + return new OriginRequestVariants::AkeneoPim(deserialized); + } + } + catch (JsonException e) + { + exceptions.Add(e); + } + + throw new AggregateException(exceptions); + } + default: + { + throw new Exception(); + } + } + } + + public override void Write( + Utf8JsonWriter writer, + OriginRequest value, + JsonSerializerOptions options + ) + { + object variant = value switch + { + OriginRequestVariants::S3(var s3) => s3, + OriginRequestVariants::S3Compatible(var s3Compatible) => s3Compatible, + OriginRequestVariants::CloudinaryBackup(var cloudinaryBackup) => cloudinaryBackup, + OriginRequestVariants::WebFolder(var webFolder) => webFolder, + OriginRequestVariants::WebProxy(var webProxy) => webProxy, + OriginRequestVariants::Gcs(var gcs) => gcs, + OriginRequestVariants::AzureBlob(var azureBlob) => azureBlob, + OriginRequestVariants::AkeneoPim(var akeneoPim) => akeneoPim, + _ => throw new ArgumentOutOfRangeException(nameof(value)), + }; + JsonSerializer.Serialize(writer, variant, options); + } +} diff --git a/src/Imagekit/Models/Accounts/Origins/OriginRequestProperties/AkeneoPim.cs b/src/Imagekit/Models/Accounts/Origins/OriginRequestProperties/AkeneoPim.cs new file mode 100644 index 00000000..e3bb4329 --- /dev/null +++ b/src/Imagekit/Models/Accounts/Origins/OriginRequestProperties/AkeneoPim.cs @@ -0,0 +1,233 @@ +using System; +using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; +using System.Text.Json; +using System.Text.Json.Serialization; + +namespace Imagekit.Models.Accounts.Origins.OriginRequestProperties; + +[JsonConverter(typeof(ModelConverter))] +public sealed record class AkeneoPim : ModelBase, IFromRaw +{ + /// + /// Akeneo instance base URL. + /// + public required string BaseURL + { + get + { + if (!this.Properties.TryGetValue("baseUrl", out JsonElement element)) + throw new ArgumentOutOfRangeException("baseUrl", "Missing required argument"); + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions) + ?? throw new ArgumentNullException("baseUrl"); + } + set + { + this.Properties["baseUrl"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + /// + /// Akeneo API client ID. + /// + public required string ClientID + { + get + { + if (!this.Properties.TryGetValue("clientId", out JsonElement element)) + throw new ArgumentOutOfRangeException("clientId", "Missing required argument"); + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions) + ?? throw new ArgumentNullException("clientId"); + } + set + { + this.Properties["clientId"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + /// + /// Akeneo API client secret. + /// + public required string ClientSecret + { + get + { + if (!this.Properties.TryGetValue("clientSecret", out JsonElement element)) + throw new ArgumentOutOfRangeException("clientSecret", "Missing required argument"); + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions) + ?? throw new ArgumentNullException("clientSecret"); + } + set + { + this.Properties["clientSecret"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + /// + /// Display name of the origin. + /// + public required string Name + { + get + { + if (!this.Properties.TryGetValue("name", out JsonElement element)) + throw new ArgumentOutOfRangeException("name", "Missing required argument"); + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions) + ?? throw new ArgumentNullException("name"); + } + set + { + this.Properties["name"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + /// + /// Akeneo API password. + /// + public required string Password + { + get + { + if (!this.Properties.TryGetValue("password", out JsonElement element)) + throw new ArgumentOutOfRangeException("password", "Missing required argument"); + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions) + ?? throw new ArgumentNullException("password"); + } + set + { + this.Properties["password"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + public JsonElement Type + { + get + { + if (!this.Properties.TryGetValue("type", out JsonElement element)) + throw new ArgumentOutOfRangeException("type", "Missing required argument"); + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions); + } + set + { + this.Properties["type"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + /// + /// Akeneo API username. + /// + public required string Username + { + get + { + if (!this.Properties.TryGetValue("username", out JsonElement element)) + throw new ArgumentOutOfRangeException("username", "Missing required argument"); + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions) + ?? throw new ArgumentNullException("username"); + } + set + { + this.Properties["username"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + /// + /// URL used in the Canonical header (if enabled). + /// + public string? BaseURLForCanonicalHeader + { + get + { + if (!this.Properties.TryGetValue("baseUrlForCanonicalHeader", out JsonElement element)) + return null; + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions); + } + set + { + this.Properties["baseUrlForCanonicalHeader"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + /// + /// Whether to send a Canonical header. + /// + public bool? IncludeCanonicalHeader + { + get + { + if (!this.Properties.TryGetValue("includeCanonicalHeader", out JsonElement element)) + return null; + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions); + } + set + { + this.Properties["includeCanonicalHeader"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + public override void Validate() + { + _ = this.BaseURL; + _ = this.ClientID; + _ = this.ClientSecret; + _ = this.Name; + _ = this.Password; + _ = this.Username; + _ = this.BaseURLForCanonicalHeader; + _ = this.IncludeCanonicalHeader; + } + + public AkeneoPim() + { + this.Type = JsonSerializer.Deserialize("\"AKENEO_PIM\""); + } + +#pragma warning disable CS8618 + [SetsRequiredMembers] + AkeneoPim(Dictionary properties) + { + Properties = properties; + } +#pragma warning restore CS8618 + + public static AkeneoPim FromRawUnchecked(Dictionary properties) + { + return new(properties); + } +} diff --git a/src/Imagekit/Models/Accounts/Origins/OriginRequestProperties/AzureBlob.cs b/src/Imagekit/Models/Accounts/Origins/OriginRequestProperties/AzureBlob.cs new file mode 100644 index 00000000..130af741 --- /dev/null +++ b/src/Imagekit/Models/Accounts/Origins/OriginRequestProperties/AzureBlob.cs @@ -0,0 +1,197 @@ +using System; +using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; +using System.Text.Json; +using System.Text.Json.Serialization; + +namespace Imagekit.Models.Accounts.Origins.OriginRequestProperties; + +[JsonConverter(typeof(ModelConverter))] +public sealed record class AzureBlob : ModelBase, IFromRaw +{ + public required string AccountName + { + get + { + if (!this.Properties.TryGetValue("accountName", out JsonElement element)) + throw new ArgumentOutOfRangeException("accountName", "Missing required argument"); + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions) + ?? throw new ArgumentNullException("accountName"); + } + set + { + this.Properties["accountName"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + public required string Container + { + get + { + if (!this.Properties.TryGetValue("container", out JsonElement element)) + throw new ArgumentOutOfRangeException("container", "Missing required argument"); + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions) + ?? throw new ArgumentNullException("container"); + } + set + { + this.Properties["container"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + /// + /// Display name of the origin. + /// + public required string Name + { + get + { + if (!this.Properties.TryGetValue("name", out JsonElement element)) + throw new ArgumentOutOfRangeException("name", "Missing required argument"); + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions) + ?? throw new ArgumentNullException("name"); + } + set + { + this.Properties["name"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + public required string SasToken + { + get + { + if (!this.Properties.TryGetValue("sasToken", out JsonElement element)) + throw new ArgumentOutOfRangeException("sasToken", "Missing required argument"); + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions) + ?? throw new ArgumentNullException("sasToken"); + } + set + { + this.Properties["sasToken"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + public JsonElement Type + { + get + { + if (!this.Properties.TryGetValue("type", out JsonElement element)) + throw new ArgumentOutOfRangeException("type", "Missing required argument"); + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions); + } + set + { + this.Properties["type"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + /// + /// URL used in the Canonical header (if enabled). + /// + public string? BaseURLForCanonicalHeader + { + get + { + if (!this.Properties.TryGetValue("baseUrlForCanonicalHeader", out JsonElement element)) + return null; + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions); + } + set + { + this.Properties["baseUrlForCanonicalHeader"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + /// + /// Whether to send a Canonical header. + /// + public bool? IncludeCanonicalHeader + { + get + { + if (!this.Properties.TryGetValue("includeCanonicalHeader", out JsonElement element)) + return null; + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions); + } + set + { + this.Properties["includeCanonicalHeader"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + public string? Prefix + { + get + { + if (!this.Properties.TryGetValue("prefix", out JsonElement element)) + return null; + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions); + } + set + { + this.Properties["prefix"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + public override void Validate() + { + _ = this.AccountName; + _ = this.Container; + _ = this.Name; + _ = this.SasToken; + _ = this.BaseURLForCanonicalHeader; + _ = this.IncludeCanonicalHeader; + _ = this.Prefix; + } + + public AzureBlob() + { + this.Type = JsonSerializer.Deserialize("\"AZURE_BLOB\""); + } + +#pragma warning disable CS8618 + [SetsRequiredMembers] + AzureBlob(Dictionary properties) + { + Properties = properties; + } +#pragma warning restore CS8618 + + public static AzureBlob FromRawUnchecked(Dictionary properties) + { + return new(properties); + } +} diff --git a/src/Imagekit/Models/Accounts/Origins/OriginRequestProperties/CloudinaryBackup.cs b/src/Imagekit/Models/Accounts/Origins/OriginRequestProperties/CloudinaryBackup.cs new file mode 100644 index 00000000..a4b9bb4f --- /dev/null +++ b/src/Imagekit/Models/Accounts/Origins/OriginRequestProperties/CloudinaryBackup.cs @@ -0,0 +1,209 @@ +using System; +using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; +using System.Text.Json; +using System.Text.Json.Serialization; + +namespace Imagekit.Models.Accounts.Origins.OriginRequestProperties; + +[JsonConverter(typeof(ModelConverter))] +public sealed record class CloudinaryBackup : ModelBase, IFromRaw +{ + /// + /// Access key for the bucket. + /// + public required string AccessKey + { + get + { + if (!this.Properties.TryGetValue("accessKey", out JsonElement element)) + throw new ArgumentOutOfRangeException("accessKey", "Missing required argument"); + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions) + ?? throw new ArgumentNullException("accessKey"); + } + set + { + this.Properties["accessKey"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + /// + /// S3 bucket name. + /// + public required string Bucket + { + get + { + if (!this.Properties.TryGetValue("bucket", out JsonElement element)) + throw new ArgumentOutOfRangeException("bucket", "Missing required argument"); + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions) + ?? throw new ArgumentNullException("bucket"); + } + set + { + this.Properties["bucket"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + /// + /// Display name of the origin. + /// + public required string Name + { + get + { + if (!this.Properties.TryGetValue("name", out JsonElement element)) + throw new ArgumentOutOfRangeException("name", "Missing required argument"); + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions) + ?? throw new ArgumentNullException("name"); + } + set + { + this.Properties["name"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + /// + /// Secret key for the bucket. + /// + public required string SecretKey + { + get + { + if (!this.Properties.TryGetValue("secretKey", out JsonElement element)) + throw new ArgumentOutOfRangeException("secretKey", "Missing required argument"); + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions) + ?? throw new ArgumentNullException("secretKey"); + } + set + { + this.Properties["secretKey"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + public JsonElement Type + { + get + { + if (!this.Properties.TryGetValue("type", out JsonElement element)) + throw new ArgumentOutOfRangeException("type", "Missing required argument"); + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions); + } + set + { + this.Properties["type"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + /// + /// URL used in the Canonical header (if enabled). + /// + public string? BaseURLForCanonicalHeader + { + get + { + if (!this.Properties.TryGetValue("baseUrlForCanonicalHeader", out JsonElement element)) + return null; + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions); + } + set + { + this.Properties["baseUrlForCanonicalHeader"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + /// + /// Whether to send a Canonical header. + /// + public bool? IncludeCanonicalHeader + { + get + { + if (!this.Properties.TryGetValue("includeCanonicalHeader", out JsonElement element)) + return null; + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions); + } + set + { + this.Properties["includeCanonicalHeader"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + /// + /// Path prefix inside the bucket. + /// + public string? Prefix + { + get + { + if (!this.Properties.TryGetValue("prefix", out JsonElement element)) + return null; + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions); + } + set + { + this.Properties["prefix"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + public override void Validate() + { + _ = this.AccessKey; + _ = this.Bucket; + _ = this.Name; + _ = this.SecretKey; + _ = this.BaseURLForCanonicalHeader; + _ = this.IncludeCanonicalHeader; + _ = this.Prefix; + } + + public CloudinaryBackup() + { + this.Type = JsonSerializer.Deserialize("\"CLOUDINARY_BACKUP\""); + } + +#pragma warning disable CS8618 + [SetsRequiredMembers] + CloudinaryBackup(Dictionary properties) + { + Properties = properties; + } +#pragma warning restore CS8618 + + public static CloudinaryBackup FromRawUnchecked(Dictionary properties) + { + return new(properties); + } +} diff --git a/src/Imagekit/Models/Accounts/Origins/OriginRequestProperties/Gcs.cs b/src/Imagekit/Models/Accounts/Origins/OriginRequestProperties/Gcs.cs new file mode 100644 index 00000000..ad22fac8 --- /dev/null +++ b/src/Imagekit/Models/Accounts/Origins/OriginRequestProperties/Gcs.cs @@ -0,0 +1,197 @@ +using System; +using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; +using System.Text.Json; +using System.Text.Json.Serialization; + +namespace Imagekit.Models.Accounts.Origins.OriginRequestProperties; + +[JsonConverter(typeof(ModelConverter))] +public sealed record class Gcs : ModelBase, IFromRaw +{ + public required string Bucket + { + get + { + if (!this.Properties.TryGetValue("bucket", out JsonElement element)) + throw new ArgumentOutOfRangeException("bucket", "Missing required argument"); + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions) + ?? throw new ArgumentNullException("bucket"); + } + set + { + this.Properties["bucket"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + public required string ClientEmail + { + get + { + if (!this.Properties.TryGetValue("clientEmail", out JsonElement element)) + throw new ArgumentOutOfRangeException("clientEmail", "Missing required argument"); + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions) + ?? throw new ArgumentNullException("clientEmail"); + } + set + { + this.Properties["clientEmail"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + /// + /// Display name of the origin. + /// + public required string Name + { + get + { + if (!this.Properties.TryGetValue("name", out JsonElement element)) + throw new ArgumentOutOfRangeException("name", "Missing required argument"); + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions) + ?? throw new ArgumentNullException("name"); + } + set + { + this.Properties["name"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + public required string PrivateKey + { + get + { + if (!this.Properties.TryGetValue("privateKey", out JsonElement element)) + throw new ArgumentOutOfRangeException("privateKey", "Missing required argument"); + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions) + ?? throw new ArgumentNullException("privateKey"); + } + set + { + this.Properties["privateKey"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + public JsonElement Type + { + get + { + if (!this.Properties.TryGetValue("type", out JsonElement element)) + throw new ArgumentOutOfRangeException("type", "Missing required argument"); + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions); + } + set + { + this.Properties["type"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + /// + /// URL used in the Canonical header (if enabled). + /// + public string? BaseURLForCanonicalHeader + { + get + { + if (!this.Properties.TryGetValue("baseUrlForCanonicalHeader", out JsonElement element)) + return null; + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions); + } + set + { + this.Properties["baseUrlForCanonicalHeader"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + /// + /// Whether to send a Canonical header. + /// + public bool? IncludeCanonicalHeader + { + get + { + if (!this.Properties.TryGetValue("includeCanonicalHeader", out JsonElement element)) + return null; + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions); + } + set + { + this.Properties["includeCanonicalHeader"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + public string? Prefix + { + get + { + if (!this.Properties.TryGetValue("prefix", out JsonElement element)) + return null; + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions); + } + set + { + this.Properties["prefix"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + public override void Validate() + { + _ = this.Bucket; + _ = this.ClientEmail; + _ = this.Name; + _ = this.PrivateKey; + _ = this.BaseURLForCanonicalHeader; + _ = this.IncludeCanonicalHeader; + _ = this.Prefix; + } + + public Gcs() + { + this.Type = JsonSerializer.Deserialize("\"GCS\""); + } + +#pragma warning disable CS8618 + [SetsRequiredMembers] + Gcs(Dictionary properties) + { + Properties = properties; + } +#pragma warning restore CS8618 + + public static Gcs FromRawUnchecked(Dictionary properties) + { + return new(properties); + } +} diff --git a/src/Imagekit/Models/Accounts/Origins/OriginRequestProperties/S3.cs b/src/Imagekit/Models/Accounts/Origins/OriginRequestProperties/S3.cs new file mode 100644 index 00000000..f9d0d5f1 --- /dev/null +++ b/src/Imagekit/Models/Accounts/Origins/OriginRequestProperties/S3.cs @@ -0,0 +1,209 @@ +using System; +using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; +using System.Text.Json; +using System.Text.Json.Serialization; + +namespace Imagekit.Models.Accounts.Origins.OriginRequestProperties; + +[JsonConverter(typeof(ModelConverter))] +public sealed record class S3 : ModelBase, IFromRaw +{ + /// + /// Access key for the bucket. + /// + public required string AccessKey + { + get + { + if (!this.Properties.TryGetValue("accessKey", out JsonElement element)) + throw new ArgumentOutOfRangeException("accessKey", "Missing required argument"); + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions) + ?? throw new ArgumentNullException("accessKey"); + } + set + { + this.Properties["accessKey"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + /// + /// S3 bucket name. + /// + public required string Bucket + { + get + { + if (!this.Properties.TryGetValue("bucket", out JsonElement element)) + throw new ArgumentOutOfRangeException("bucket", "Missing required argument"); + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions) + ?? throw new ArgumentNullException("bucket"); + } + set + { + this.Properties["bucket"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + /// + /// Display name of the origin. + /// + public required string Name + { + get + { + if (!this.Properties.TryGetValue("name", out JsonElement element)) + throw new ArgumentOutOfRangeException("name", "Missing required argument"); + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions) + ?? throw new ArgumentNullException("name"); + } + set + { + this.Properties["name"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + /// + /// Secret key for the bucket. + /// + public required string SecretKey + { + get + { + if (!this.Properties.TryGetValue("secretKey", out JsonElement element)) + throw new ArgumentOutOfRangeException("secretKey", "Missing required argument"); + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions) + ?? throw new ArgumentNullException("secretKey"); + } + set + { + this.Properties["secretKey"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + public JsonElement Type + { + get + { + if (!this.Properties.TryGetValue("type", out JsonElement element)) + throw new ArgumentOutOfRangeException("type", "Missing required argument"); + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions); + } + set + { + this.Properties["type"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + /// + /// URL used in the Canonical header (if enabled). + /// + public string? BaseURLForCanonicalHeader + { + get + { + if (!this.Properties.TryGetValue("baseUrlForCanonicalHeader", out JsonElement element)) + return null; + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions); + } + set + { + this.Properties["baseUrlForCanonicalHeader"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + /// + /// Whether to send a Canonical header. + /// + public bool? IncludeCanonicalHeader + { + get + { + if (!this.Properties.TryGetValue("includeCanonicalHeader", out JsonElement element)) + return null; + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions); + } + set + { + this.Properties["includeCanonicalHeader"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + /// + /// Path prefix inside the bucket. + /// + public string? Prefix + { + get + { + if (!this.Properties.TryGetValue("prefix", out JsonElement element)) + return null; + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions); + } + set + { + this.Properties["prefix"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + public override void Validate() + { + _ = this.AccessKey; + _ = this.Bucket; + _ = this.Name; + _ = this.SecretKey; + _ = this.BaseURLForCanonicalHeader; + _ = this.IncludeCanonicalHeader; + _ = this.Prefix; + } + + public S3() + { + this.Type = JsonSerializer.Deserialize("\"S3\""); + } + +#pragma warning disable CS8618 + [SetsRequiredMembers] + S3(Dictionary properties) + { + Properties = properties; + } +#pragma warning restore CS8618 + + public static S3 FromRawUnchecked(Dictionary properties) + { + return new(properties); + } +} diff --git a/src/Imagekit/Models/Accounts/Origins/OriginRequestProperties/S3Compatible.cs b/src/Imagekit/Models/Accounts/Origins/OriginRequestProperties/S3Compatible.cs new file mode 100644 index 00000000..500d31b5 --- /dev/null +++ b/src/Imagekit/Models/Accounts/Origins/OriginRequestProperties/S3Compatible.cs @@ -0,0 +1,254 @@ +using System; +using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; +using System.Text.Json; +using System.Text.Json.Serialization; + +namespace Imagekit.Models.Accounts.Origins.OriginRequestProperties; + +[JsonConverter(typeof(ModelConverter))] +public sealed record class S3Compatible : ModelBase, IFromRaw +{ + /// + /// Access key for the bucket. + /// + public required string AccessKey + { + get + { + if (!this.Properties.TryGetValue("accessKey", out JsonElement element)) + throw new ArgumentOutOfRangeException("accessKey", "Missing required argument"); + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions) + ?? throw new ArgumentNullException("accessKey"); + } + set + { + this.Properties["accessKey"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + /// + /// S3 bucket name. + /// + public required string Bucket + { + get + { + if (!this.Properties.TryGetValue("bucket", out JsonElement element)) + throw new ArgumentOutOfRangeException("bucket", "Missing required argument"); + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions) + ?? throw new ArgumentNullException("bucket"); + } + set + { + this.Properties["bucket"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + /// + /// Custom S3-compatible endpoint. + /// + public required string Endpoint + { + get + { + if (!this.Properties.TryGetValue("endpoint", out JsonElement element)) + throw new ArgumentOutOfRangeException("endpoint", "Missing required argument"); + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions) + ?? throw new ArgumentNullException("endpoint"); + } + set + { + this.Properties["endpoint"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + /// + /// Display name of the origin. + /// + public required string Name + { + get + { + if (!this.Properties.TryGetValue("name", out JsonElement element)) + throw new ArgumentOutOfRangeException("name", "Missing required argument"); + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions) + ?? throw new ArgumentNullException("name"); + } + set + { + this.Properties["name"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + /// + /// Secret key for the bucket. + /// + public required string SecretKey + { + get + { + if (!this.Properties.TryGetValue("secretKey", out JsonElement element)) + throw new ArgumentOutOfRangeException("secretKey", "Missing required argument"); + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions) + ?? throw new ArgumentNullException("secretKey"); + } + set + { + this.Properties["secretKey"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + public JsonElement Type + { + get + { + if (!this.Properties.TryGetValue("type", out JsonElement element)) + throw new ArgumentOutOfRangeException("type", "Missing required argument"); + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions); + } + set + { + this.Properties["type"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + /// + /// URL used in the Canonical header (if enabled). + /// + public string? BaseURLForCanonicalHeader + { + get + { + if (!this.Properties.TryGetValue("baseUrlForCanonicalHeader", out JsonElement element)) + return null; + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions); + } + set + { + this.Properties["baseUrlForCanonicalHeader"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + /// + /// Whether to send a Canonical header. + /// + public bool? IncludeCanonicalHeader + { + get + { + if (!this.Properties.TryGetValue("includeCanonicalHeader", out JsonElement element)) + return null; + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions); + } + set + { + this.Properties["includeCanonicalHeader"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + /// + /// Path prefix inside the bucket. + /// + public string? Prefix + { + get + { + if (!this.Properties.TryGetValue("prefix", out JsonElement element)) + return null; + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions); + } + set + { + this.Properties["prefix"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + /// + /// Use path-style S3 URLs? + /// + public bool? S3ForcePathStyle + { + get + { + if (!this.Properties.TryGetValue("s3ForcePathStyle", out JsonElement element)) + return null; + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions); + } + set + { + this.Properties["s3ForcePathStyle"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + public override void Validate() + { + _ = this.AccessKey; + _ = this.Bucket; + _ = this.Endpoint; + _ = this.Name; + _ = this.SecretKey; + _ = this.BaseURLForCanonicalHeader; + _ = this.IncludeCanonicalHeader; + _ = this.Prefix; + _ = this.S3ForcePathStyle; + } + + public S3Compatible() + { + this.Type = JsonSerializer.Deserialize("\"S3_COMPATIBLE\""); + } + +#pragma warning disable CS8618 + [SetsRequiredMembers] + S3Compatible(Dictionary properties) + { + Properties = properties; + } +#pragma warning restore CS8618 + + public static S3Compatible FromRawUnchecked(Dictionary properties) + { + return new(properties); + } +} diff --git a/src/Imagekit/Models/Accounts/Origins/OriginRequestProperties/WebFolder.cs b/src/Imagekit/Models/Accounts/Origins/OriginRequestProperties/WebFolder.cs new file mode 100644 index 00000000..09bf8765 --- /dev/null +++ b/src/Imagekit/Models/Accounts/Origins/OriginRequestProperties/WebFolder.cs @@ -0,0 +1,163 @@ +using System; +using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; +using System.Text.Json; +using System.Text.Json.Serialization; + +namespace Imagekit.Models.Accounts.Origins.OriginRequestProperties; + +[JsonConverter(typeof(ModelConverter))] +public sealed record class WebFolder : ModelBase, IFromRaw +{ + /// + /// Root URL for the web folder origin. + /// + public required string BaseURL + { + get + { + if (!this.Properties.TryGetValue("baseUrl", out JsonElement element)) + throw new ArgumentOutOfRangeException("baseUrl", "Missing required argument"); + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions) + ?? throw new ArgumentNullException("baseUrl"); + } + set + { + this.Properties["baseUrl"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + /// + /// Display name of the origin. + /// + public required string Name + { + get + { + if (!this.Properties.TryGetValue("name", out JsonElement element)) + throw new ArgumentOutOfRangeException("name", "Missing required argument"); + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions) + ?? throw new ArgumentNullException("name"); + } + set + { + this.Properties["name"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + public JsonElement Type + { + get + { + if (!this.Properties.TryGetValue("type", out JsonElement element)) + throw new ArgumentOutOfRangeException("type", "Missing required argument"); + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions); + } + set + { + this.Properties["type"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + /// + /// URL used in the Canonical header (if enabled). + /// + public string? BaseURLForCanonicalHeader + { + get + { + if (!this.Properties.TryGetValue("baseUrlForCanonicalHeader", out JsonElement element)) + return null; + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions); + } + set + { + this.Properties["baseUrlForCanonicalHeader"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + /// + /// Forward the Host header to origin? + /// + public bool? ForwardHostHeaderToOrigin + { + get + { + if (!this.Properties.TryGetValue("forwardHostHeaderToOrigin", out JsonElement element)) + return null; + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions); + } + set + { + this.Properties["forwardHostHeaderToOrigin"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + /// + /// Whether to send a Canonical header. + /// + public bool? IncludeCanonicalHeader + { + get + { + if (!this.Properties.TryGetValue("includeCanonicalHeader", out JsonElement element)) + return null; + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions); + } + set + { + this.Properties["includeCanonicalHeader"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + public override void Validate() + { + _ = this.BaseURL; + _ = this.Name; + _ = this.BaseURLForCanonicalHeader; + _ = this.ForwardHostHeaderToOrigin; + _ = this.IncludeCanonicalHeader; + } + + public WebFolder() + { + this.Type = JsonSerializer.Deserialize("\"WEB_FOLDER\""); + } + +#pragma warning disable CS8618 + [SetsRequiredMembers] + WebFolder(Dictionary properties) + { + Properties = properties; + } +#pragma warning restore CS8618 + + public static WebFolder FromRawUnchecked(Dictionary properties) + { + return new(properties); + } +} diff --git a/src/Imagekit/Models/Accounts/Origins/OriginRequestProperties/WebProxy.cs b/src/Imagekit/Models/Accounts/Origins/OriginRequestProperties/WebProxy.cs new file mode 100644 index 00000000..bf88baa9 --- /dev/null +++ b/src/Imagekit/Models/Accounts/Origins/OriginRequestProperties/WebProxy.cs @@ -0,0 +1,125 @@ +using System; +using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; +using System.Text.Json; +using System.Text.Json.Serialization; + +namespace Imagekit.Models.Accounts.Origins.OriginRequestProperties; + +[JsonConverter(typeof(ModelConverter))] +public sealed record class WebProxy : ModelBase, IFromRaw +{ + /// + /// Display name of the origin. + /// + public required string Name + { + get + { + if (!this.Properties.TryGetValue("name", out JsonElement element)) + throw new ArgumentOutOfRangeException("name", "Missing required argument"); + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions) + ?? throw new ArgumentNullException("name"); + } + set + { + this.Properties["name"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + public JsonElement Type + { + get + { + if (!this.Properties.TryGetValue("type", out JsonElement element)) + throw new ArgumentOutOfRangeException("type", "Missing required argument"); + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions); + } + set + { + this.Properties["type"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + /// + /// URL used in the Canonical header (if enabled). + /// + public string? BaseURLForCanonicalHeader + { + get + { + if (!this.Properties.TryGetValue("baseUrlForCanonicalHeader", out JsonElement element)) + return null; + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions); + } + set + { + this.Properties["baseUrlForCanonicalHeader"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + /// + /// Whether to send a Canonical header. + /// + public bool? IncludeCanonicalHeader + { + get + { + if (!this.Properties.TryGetValue("includeCanonicalHeader", out JsonElement element)) + return null; + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions); + } + set + { + this.Properties["includeCanonicalHeader"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + public override void Validate() + { + _ = this.Name; + _ = this.BaseURLForCanonicalHeader; + _ = this.IncludeCanonicalHeader; + } + + public WebProxy() + { + this.Type = JsonSerializer.Deserialize("\"WEB_PROXY\""); + } + +#pragma warning disable CS8618 + [SetsRequiredMembers] + WebProxy(Dictionary properties) + { + Properties = properties; + } +#pragma warning restore CS8618 + + public static WebProxy FromRawUnchecked(Dictionary properties) + { + return new(properties); + } + + [SetsRequiredMembers] + public WebProxy(string name) + : this() + { + this.Name = name; + } +} diff --git a/src/Imagekit/Models/Accounts/Origins/OriginRequestVariants/All.cs b/src/Imagekit/Models/Accounts/Origins/OriginRequestVariants/All.cs new file mode 100644 index 00000000..bfaed1ab --- /dev/null +++ b/src/Imagekit/Models/Accounts/Origins/OriginRequestVariants/All.cs @@ -0,0 +1,123 @@ +using OriginRequestProperties = Imagekit.Models.Accounts.Origins.OriginRequestProperties; + +namespace Imagekit.Models.Accounts.Origins.OriginRequestVariants; + +public sealed record class S3(OriginRequestProperties::S3 Value) + : OriginRequest, + IVariant +{ + public static S3 From(OriginRequestProperties::S3 value) + { + return new(value); + } + + public override void Validate() + { + this.Value.Validate(); + } +} + +public sealed record class S3Compatible(OriginRequestProperties::S3Compatible Value) + : OriginRequest, + IVariant +{ + public static S3Compatible From(OriginRequestProperties::S3Compatible value) + { + return new(value); + } + + public override void Validate() + { + this.Value.Validate(); + } +} + +public sealed record class CloudinaryBackup(OriginRequestProperties::CloudinaryBackup Value) + : OriginRequest, + IVariant +{ + public static CloudinaryBackup From(OriginRequestProperties::CloudinaryBackup value) + { + return new(value); + } + + public override void Validate() + { + this.Value.Validate(); + } +} + +public sealed record class WebFolder(OriginRequestProperties::WebFolder Value) + : OriginRequest, + IVariant +{ + public static WebFolder From(OriginRequestProperties::WebFolder value) + { + return new(value); + } + + public override void Validate() + { + this.Value.Validate(); + } +} + +public sealed record class WebProxy(OriginRequestProperties::WebProxy Value) + : OriginRequest, + IVariant +{ + public static WebProxy From(OriginRequestProperties::WebProxy value) + { + return new(value); + } + + public override void Validate() + { + this.Value.Validate(); + } +} + +public sealed record class Gcs(OriginRequestProperties::Gcs Value) + : OriginRequest, + IVariant +{ + public static Gcs From(OriginRequestProperties::Gcs value) + { + return new(value); + } + + public override void Validate() + { + this.Value.Validate(); + } +} + +public sealed record class AzureBlob(OriginRequestProperties::AzureBlob Value) + : OriginRequest, + IVariant +{ + public static AzureBlob From(OriginRequestProperties::AzureBlob value) + { + return new(value); + } + + public override void Validate() + { + this.Value.Validate(); + } +} + +public sealed record class AkeneoPim(OriginRequestProperties::AkeneoPim Value) + : OriginRequest, + IVariant +{ + public static AkeneoPim From(OriginRequestProperties::AkeneoPim value) + { + return new(value); + } + + public override void Validate() + { + this.Value.Validate(); + } +} diff --git a/src/Imagekit/Models/Accounts/Origins/OriginResponse.cs b/src/Imagekit/Models/Accounts/Origins/OriginResponse.cs new file mode 100644 index 00000000..9fd7dadf --- /dev/null +++ b/src/Imagekit/Models/Accounts/Origins/OriginResponse.cs @@ -0,0 +1,361 @@ +using System; +using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; +using System.Text.Json; +using System.Text.Json.Serialization; +using Imagekit.Models.Accounts.Origins.OriginResponseProperties; +using OriginResponseVariants = Imagekit.Models.Accounts.Origins.OriginResponseVariants; + +namespace Imagekit.Models.Accounts.Origins; + +/// +/// Origin object as returned by the API (sensitive fields removed). +/// +[JsonConverter(typeof(OriginResponseConverter))] +public abstract record class OriginResponse +{ + internal OriginResponse() { } + + public static implicit operator OriginResponse(S3 value) => + new OriginResponseVariants::S3(value); + + public static implicit operator OriginResponse(S3Compatible value) => + new OriginResponseVariants::S3Compatible(value); + + public static implicit operator OriginResponse(CloudinaryBackup value) => + new OriginResponseVariants::CloudinaryBackup(value); + + public static implicit operator OriginResponse(WebFolder value) => + new OriginResponseVariants::WebFolder(value); + + public static implicit operator OriginResponse(WebProxy value) => + new OriginResponseVariants::WebProxy(value); + + public static implicit operator OriginResponse(Gcs value) => + new OriginResponseVariants::Gcs(value); + + public static implicit operator OriginResponse(AzureBlob value) => + new OriginResponseVariants::AzureBlob(value); + + public static implicit operator OriginResponse(AkeneoPim value) => + new OriginResponseVariants::AkeneoPim(value); + + public bool TryPickS3([NotNullWhen(true)] out S3? value) + { + value = (this as OriginResponseVariants::S3)?.Value; + return value != null; + } + + public bool TryPickS3Compatible([NotNullWhen(true)] out S3Compatible? value) + { + value = (this as OriginResponseVariants::S3Compatible)?.Value; + return value != null; + } + + public bool TryPickCloudinaryBackup([NotNullWhen(true)] out CloudinaryBackup? value) + { + value = (this as OriginResponseVariants::CloudinaryBackup)?.Value; + return value != null; + } + + public bool TryPickWebFolder([NotNullWhen(true)] out WebFolder? value) + { + value = (this as OriginResponseVariants::WebFolder)?.Value; + return value != null; + } + + public bool TryPickWebProxy([NotNullWhen(true)] out WebProxy? value) + { + value = (this as OriginResponseVariants::WebProxy)?.Value; + return value != null; + } + + public bool TryPickGcs([NotNullWhen(true)] out Gcs? value) + { + value = (this as OriginResponseVariants::Gcs)?.Value; + return value != null; + } + + public bool TryPickAzureBlob([NotNullWhen(true)] out AzureBlob? value) + { + value = (this as OriginResponseVariants::AzureBlob)?.Value; + return value != null; + } + + public bool TryPickAkeneoPim([NotNullWhen(true)] out AkeneoPim? value) + { + value = (this as OriginResponseVariants::AkeneoPim)?.Value; + return value != null; + } + + public void Switch( + Action s3, + Action s3Compatible, + Action cloudinaryBackup, + Action webFolder, + Action webProxy, + Action gcs, + Action azureBlob, + Action akeneoPim + ) + { + switch (this) + { + case OriginResponseVariants::S3 inner: + s3(inner); + break; + case OriginResponseVariants::S3Compatible inner: + s3Compatible(inner); + break; + case OriginResponseVariants::CloudinaryBackup inner: + cloudinaryBackup(inner); + break; + case OriginResponseVariants::WebFolder inner: + webFolder(inner); + break; + case OriginResponseVariants::WebProxy inner: + webProxy(inner); + break; + case OriginResponseVariants::Gcs inner: + gcs(inner); + break; + case OriginResponseVariants::AzureBlob inner: + azureBlob(inner); + break; + case OriginResponseVariants::AkeneoPim inner: + akeneoPim(inner); + break; + default: + throw new InvalidOperationException(); + } + } + + public T Match( + Func s3, + Func s3Compatible, + Func cloudinaryBackup, + Func webFolder, + Func webProxy, + Func gcs, + Func azureBlob, + Func akeneoPim + ) + { + return this switch + { + OriginResponseVariants::S3 inner => s3(inner), + OriginResponseVariants::S3Compatible inner => s3Compatible(inner), + OriginResponseVariants::CloudinaryBackup inner => cloudinaryBackup(inner), + OriginResponseVariants::WebFolder inner => webFolder(inner), + OriginResponseVariants::WebProxy inner => webProxy(inner), + OriginResponseVariants::Gcs inner => gcs(inner), + OriginResponseVariants::AzureBlob inner => azureBlob(inner), + OriginResponseVariants::AkeneoPim inner => akeneoPim(inner), + _ => throw new InvalidOperationException(), + }; + } + + public abstract void Validate(); +} + +sealed class OriginResponseConverter : JsonConverter +{ + public override OriginResponse? Read( + ref Utf8JsonReader reader, + Type typeToConvert, + JsonSerializerOptions options + ) + { + var json = JsonSerializer.Deserialize(ref reader, options); + string? type; + try + { + type = json.GetProperty("type").GetString(); + } + catch + { + type = null; + } + + switch (type) + { + case "S3": + { + List exceptions = []; + + try + { + var deserialized = JsonSerializer.Deserialize(json, options); + if (deserialized != null) + { + return new OriginResponseVariants::S3(deserialized); + } + } + catch (JsonException e) + { + exceptions.Add(e); + } + + throw new AggregateException(exceptions); + } + case "S3_COMPATIBLE": + { + List exceptions = []; + + try + { + var deserialized = JsonSerializer.Deserialize(json, options); + if (deserialized != null) + { + return new OriginResponseVariants::S3Compatible(deserialized); + } + } + catch (JsonException e) + { + exceptions.Add(e); + } + + throw new AggregateException(exceptions); + } + case "CLOUDINARY_BACKUP": + { + List exceptions = []; + + try + { + var deserialized = JsonSerializer.Deserialize(json, options); + if (deserialized != null) + { + return new OriginResponseVariants::CloudinaryBackup(deserialized); + } + } + catch (JsonException e) + { + exceptions.Add(e); + } + + throw new AggregateException(exceptions); + } + case "WEB_FOLDER": + { + List exceptions = []; + + try + { + var deserialized = JsonSerializer.Deserialize(json, options); + if (deserialized != null) + { + return new OriginResponseVariants::WebFolder(deserialized); + } + } + catch (JsonException e) + { + exceptions.Add(e); + } + + throw new AggregateException(exceptions); + } + case "WEB_PROXY": + { + List exceptions = []; + + try + { + var deserialized = JsonSerializer.Deserialize(json, options); + if (deserialized != null) + { + return new OriginResponseVariants::WebProxy(deserialized); + } + } + catch (JsonException e) + { + exceptions.Add(e); + } + + throw new AggregateException(exceptions); + } + case "GCS": + { + List exceptions = []; + + try + { + var deserialized = JsonSerializer.Deserialize(json, options); + if (deserialized != null) + { + return new OriginResponseVariants::Gcs(deserialized); + } + } + catch (JsonException e) + { + exceptions.Add(e); + } + + throw new AggregateException(exceptions); + } + case "AZURE_BLOB": + { + List exceptions = []; + + try + { + var deserialized = JsonSerializer.Deserialize(json, options); + if (deserialized != null) + { + return new OriginResponseVariants::AzureBlob(deserialized); + } + } + catch (JsonException e) + { + exceptions.Add(e); + } + + throw new AggregateException(exceptions); + } + case "AKENEO_PIM": + { + List exceptions = []; + + try + { + var deserialized = JsonSerializer.Deserialize(json, options); + if (deserialized != null) + { + return new OriginResponseVariants::AkeneoPim(deserialized); + } + } + catch (JsonException e) + { + exceptions.Add(e); + } + + throw new AggregateException(exceptions); + } + default: + { + throw new Exception(); + } + } + } + + public override void Write( + Utf8JsonWriter writer, + OriginResponse value, + JsonSerializerOptions options + ) + { + object variant = value switch + { + OriginResponseVariants::S3(var s3) => s3, + OriginResponseVariants::S3Compatible(var s3Compatible) => s3Compatible, + OriginResponseVariants::CloudinaryBackup(var cloudinaryBackup) => cloudinaryBackup, + OriginResponseVariants::WebFolder(var webFolder) => webFolder, + OriginResponseVariants::WebProxy(var webProxy) => webProxy, + OriginResponseVariants::Gcs(var gcs) => gcs, + OriginResponseVariants::AzureBlob(var azureBlob) => azureBlob, + OriginResponseVariants::AkeneoPim(var akeneoPim) => akeneoPim, + _ => throw new ArgumentOutOfRangeException(nameof(value)), + }; + JsonSerializer.Serialize(writer, variant, options); + } +} diff --git a/src/Imagekit/Models/Accounts/Origins/OriginResponseProperties/AkeneoPim.cs b/src/Imagekit/Models/Accounts/Origins/OriginResponseProperties/AkeneoPim.cs new file mode 100644 index 00000000..9860c44c --- /dev/null +++ b/src/Imagekit/Models/Accounts/Origins/OriginResponseProperties/AkeneoPim.cs @@ -0,0 +1,168 @@ +using System; +using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; +using System.Text.Json; +using System.Text.Json.Serialization; + +namespace Imagekit.Models.Accounts.Origins.OriginResponseProperties; + +[JsonConverter(typeof(ModelConverter))] +public sealed record class AkeneoPim : ModelBase, IFromRaw +{ + /// + /// Unique identifier for the origin. This is generated by ImageKit when you create + /// a new origin. + /// + public required string ID + { + get + { + if (!this.Properties.TryGetValue("id", out JsonElement element)) + throw new ArgumentOutOfRangeException("id", "Missing required argument"); + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions) + ?? throw new ArgumentNullException("id"); + } + set + { + this.Properties["id"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + /// + /// Akeneo instance base URL. + /// + public required string BaseURL + { + get + { + if (!this.Properties.TryGetValue("baseUrl", out JsonElement element)) + throw new ArgumentOutOfRangeException("baseUrl", "Missing required argument"); + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions) + ?? throw new ArgumentNullException("baseUrl"); + } + set + { + this.Properties["baseUrl"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + /// + /// Whether to send a Canonical header. + /// + public required bool IncludeCanonicalHeader + { + get + { + if (!this.Properties.TryGetValue("includeCanonicalHeader", out JsonElement element)) + throw new ArgumentOutOfRangeException( + "includeCanonicalHeader", + "Missing required argument" + ); + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions); + } + set + { + this.Properties["includeCanonicalHeader"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + /// + /// Display name of the origin. + /// + public required string Name + { + get + { + if (!this.Properties.TryGetValue("name", out JsonElement element)) + throw new ArgumentOutOfRangeException("name", "Missing required argument"); + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions) + ?? throw new ArgumentNullException("name"); + } + set + { + this.Properties["name"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + public JsonElement Type + { + get + { + if (!this.Properties.TryGetValue("type", out JsonElement element)) + throw new ArgumentOutOfRangeException("type", "Missing required argument"); + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions); + } + set + { + this.Properties["type"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + /// + /// URL used in the Canonical header (if enabled). + /// + public string? BaseURLForCanonicalHeader + { + get + { + if (!this.Properties.TryGetValue("baseUrlForCanonicalHeader", out JsonElement element)) + return null; + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions); + } + set + { + this.Properties["baseUrlForCanonicalHeader"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + public override void Validate() + { + _ = this.ID; + _ = this.BaseURL; + _ = this.IncludeCanonicalHeader; + _ = this.Name; + _ = this.BaseURLForCanonicalHeader; + } + + public AkeneoPim() + { + this.Type = JsonSerializer.Deserialize("\"AKENEO_PIM\""); + } + +#pragma warning disable CS8618 + [SetsRequiredMembers] + AkeneoPim(Dictionary properties) + { + Properties = properties; + } +#pragma warning restore CS8618 + + public static AkeneoPim FromRawUnchecked(Dictionary properties) + { + return new(properties); + } +} diff --git a/src/Imagekit/Models/Accounts/Origins/OriginResponseProperties/AzureBlob.cs b/src/Imagekit/Models/Accounts/Origins/OriginResponseProperties/AzureBlob.cs new file mode 100644 index 00000000..afd047bd --- /dev/null +++ b/src/Imagekit/Models/Accounts/Origins/OriginResponseProperties/AzureBlob.cs @@ -0,0 +1,205 @@ +using System; +using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; +using System.Text.Json; +using System.Text.Json.Serialization; + +namespace Imagekit.Models.Accounts.Origins.OriginResponseProperties; + +[JsonConverter(typeof(ModelConverter))] +public sealed record class AzureBlob : ModelBase, IFromRaw +{ + /// + /// Unique identifier for the origin. This is generated by ImageKit when you create + /// a new origin. + /// + public required string ID + { + get + { + if (!this.Properties.TryGetValue("id", out JsonElement element)) + throw new ArgumentOutOfRangeException("id", "Missing required argument"); + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions) + ?? throw new ArgumentNullException("id"); + } + set + { + this.Properties["id"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + public required string AccountName + { + get + { + if (!this.Properties.TryGetValue("accountName", out JsonElement element)) + throw new ArgumentOutOfRangeException("accountName", "Missing required argument"); + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions) + ?? throw new ArgumentNullException("accountName"); + } + set + { + this.Properties["accountName"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + public required string Container + { + get + { + if (!this.Properties.TryGetValue("container", out JsonElement element)) + throw new ArgumentOutOfRangeException("container", "Missing required argument"); + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions) + ?? throw new ArgumentNullException("container"); + } + set + { + this.Properties["container"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + /// + /// Whether to send a Canonical header. + /// + public required bool IncludeCanonicalHeader + { + get + { + if (!this.Properties.TryGetValue("includeCanonicalHeader", out JsonElement element)) + throw new ArgumentOutOfRangeException( + "includeCanonicalHeader", + "Missing required argument" + ); + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions); + } + set + { + this.Properties["includeCanonicalHeader"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + /// + /// Display name of the origin. + /// + public required string Name + { + get + { + if (!this.Properties.TryGetValue("name", out JsonElement element)) + throw new ArgumentOutOfRangeException("name", "Missing required argument"); + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions) + ?? throw new ArgumentNullException("name"); + } + set + { + this.Properties["name"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + public required string Prefix + { + get + { + if (!this.Properties.TryGetValue("prefix", out JsonElement element)) + throw new ArgumentOutOfRangeException("prefix", "Missing required argument"); + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions) + ?? throw new ArgumentNullException("prefix"); + } + set + { + this.Properties["prefix"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + public JsonElement Type + { + get + { + if (!this.Properties.TryGetValue("type", out JsonElement element)) + throw new ArgumentOutOfRangeException("type", "Missing required argument"); + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions); + } + set + { + this.Properties["type"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + /// + /// URL used in the Canonical header (if enabled). + /// + public string? BaseURLForCanonicalHeader + { + get + { + if (!this.Properties.TryGetValue("baseUrlForCanonicalHeader", out JsonElement element)) + return null; + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions); + } + set + { + this.Properties["baseUrlForCanonicalHeader"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + public override void Validate() + { + _ = this.ID; + _ = this.AccountName; + _ = this.Container; + _ = this.IncludeCanonicalHeader; + _ = this.Name; + _ = this.Prefix; + _ = this.BaseURLForCanonicalHeader; + } + + public AzureBlob() + { + this.Type = JsonSerializer.Deserialize("\"AZURE_BLOB\""); + } + +#pragma warning disable CS8618 + [SetsRequiredMembers] + AzureBlob(Dictionary properties) + { + Properties = properties; + } +#pragma warning restore CS8618 + + public static AzureBlob FromRawUnchecked(Dictionary properties) + { + return new(properties); + } +} diff --git a/src/Imagekit/Models/Accounts/Origins/OriginResponseProperties/CloudinaryBackup.cs b/src/Imagekit/Models/Accounts/Origins/OriginResponseProperties/CloudinaryBackup.cs new file mode 100644 index 00000000..288553c5 --- /dev/null +++ b/src/Imagekit/Models/Accounts/Origins/OriginResponseProperties/CloudinaryBackup.cs @@ -0,0 +1,191 @@ +using System; +using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; +using System.Text.Json; +using System.Text.Json.Serialization; + +namespace Imagekit.Models.Accounts.Origins.OriginResponseProperties; + +[JsonConverter(typeof(ModelConverter))] +public sealed record class CloudinaryBackup : ModelBase, IFromRaw +{ + /// + /// Unique identifier for the origin. This is generated by ImageKit when you create + /// a new origin. + /// + public required string ID + { + get + { + if (!this.Properties.TryGetValue("id", out JsonElement element)) + throw new ArgumentOutOfRangeException("id", "Missing required argument"); + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions) + ?? throw new ArgumentNullException("id"); + } + set + { + this.Properties["id"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + /// + /// S3 bucket name. + /// + public required string Bucket + { + get + { + if (!this.Properties.TryGetValue("bucket", out JsonElement element)) + throw new ArgumentOutOfRangeException("bucket", "Missing required argument"); + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions) + ?? throw new ArgumentNullException("bucket"); + } + set + { + this.Properties["bucket"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + /// + /// Whether to send a Canonical header. + /// + public required bool IncludeCanonicalHeader + { + get + { + if (!this.Properties.TryGetValue("includeCanonicalHeader", out JsonElement element)) + throw new ArgumentOutOfRangeException( + "includeCanonicalHeader", + "Missing required argument" + ); + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions); + } + set + { + this.Properties["includeCanonicalHeader"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + /// + /// Display name of the origin. + /// + public required string Name + { + get + { + if (!this.Properties.TryGetValue("name", out JsonElement element)) + throw new ArgumentOutOfRangeException("name", "Missing required argument"); + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions) + ?? throw new ArgumentNullException("name"); + } + set + { + this.Properties["name"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + /// + /// Path prefix inside the bucket. + /// + public required string Prefix + { + get + { + if (!this.Properties.TryGetValue("prefix", out JsonElement element)) + throw new ArgumentOutOfRangeException("prefix", "Missing required argument"); + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions) + ?? throw new ArgumentNullException("prefix"); + } + set + { + this.Properties["prefix"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + public JsonElement Type + { + get + { + if (!this.Properties.TryGetValue("type", out JsonElement element)) + throw new ArgumentOutOfRangeException("type", "Missing required argument"); + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions); + } + set + { + this.Properties["type"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + /// + /// URL used in the Canonical header (if enabled). + /// + public string? BaseURLForCanonicalHeader + { + get + { + if (!this.Properties.TryGetValue("baseUrlForCanonicalHeader", out JsonElement element)) + return null; + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions); + } + set + { + this.Properties["baseUrlForCanonicalHeader"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + public override void Validate() + { + _ = this.ID; + _ = this.Bucket; + _ = this.IncludeCanonicalHeader; + _ = this.Name; + _ = this.Prefix; + _ = this.BaseURLForCanonicalHeader; + } + + public CloudinaryBackup() + { + this.Type = JsonSerializer.Deserialize("\"CLOUDINARY_BACKUP\""); + } + +#pragma warning disable CS8618 + [SetsRequiredMembers] + CloudinaryBackup(Dictionary properties) + { + Properties = properties; + } +#pragma warning restore CS8618 + + public static CloudinaryBackup FromRawUnchecked(Dictionary properties) + { + return new(properties); + } +} diff --git a/src/Imagekit/Models/Accounts/Origins/OriginResponseProperties/Gcs.cs b/src/Imagekit/Models/Accounts/Origins/OriginResponseProperties/Gcs.cs new file mode 100644 index 00000000..17a6daac --- /dev/null +++ b/src/Imagekit/Models/Accounts/Origins/OriginResponseProperties/Gcs.cs @@ -0,0 +1,205 @@ +using System; +using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; +using System.Text.Json; +using System.Text.Json.Serialization; + +namespace Imagekit.Models.Accounts.Origins.OriginResponseProperties; + +[JsonConverter(typeof(ModelConverter))] +public sealed record class Gcs : ModelBase, IFromRaw +{ + /// + /// Unique identifier for the origin. This is generated by ImageKit when you create + /// a new origin. + /// + public required string ID + { + get + { + if (!this.Properties.TryGetValue("id", out JsonElement element)) + throw new ArgumentOutOfRangeException("id", "Missing required argument"); + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions) + ?? throw new ArgumentNullException("id"); + } + set + { + this.Properties["id"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + public required string Bucket + { + get + { + if (!this.Properties.TryGetValue("bucket", out JsonElement element)) + throw new ArgumentOutOfRangeException("bucket", "Missing required argument"); + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions) + ?? throw new ArgumentNullException("bucket"); + } + set + { + this.Properties["bucket"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + public required string ClientEmail + { + get + { + if (!this.Properties.TryGetValue("clientEmail", out JsonElement element)) + throw new ArgumentOutOfRangeException("clientEmail", "Missing required argument"); + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions) + ?? throw new ArgumentNullException("clientEmail"); + } + set + { + this.Properties["clientEmail"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + /// + /// Whether to send a Canonical header. + /// + public required bool IncludeCanonicalHeader + { + get + { + if (!this.Properties.TryGetValue("includeCanonicalHeader", out JsonElement element)) + throw new ArgumentOutOfRangeException( + "includeCanonicalHeader", + "Missing required argument" + ); + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions); + } + set + { + this.Properties["includeCanonicalHeader"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + /// + /// Display name of the origin. + /// + public required string Name + { + get + { + if (!this.Properties.TryGetValue("name", out JsonElement element)) + throw new ArgumentOutOfRangeException("name", "Missing required argument"); + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions) + ?? throw new ArgumentNullException("name"); + } + set + { + this.Properties["name"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + public required string Prefix + { + get + { + if (!this.Properties.TryGetValue("prefix", out JsonElement element)) + throw new ArgumentOutOfRangeException("prefix", "Missing required argument"); + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions) + ?? throw new ArgumentNullException("prefix"); + } + set + { + this.Properties["prefix"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + public JsonElement Type + { + get + { + if (!this.Properties.TryGetValue("type", out JsonElement element)) + throw new ArgumentOutOfRangeException("type", "Missing required argument"); + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions); + } + set + { + this.Properties["type"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + /// + /// URL used in the Canonical header (if enabled). + /// + public string? BaseURLForCanonicalHeader + { + get + { + if (!this.Properties.TryGetValue("baseUrlForCanonicalHeader", out JsonElement element)) + return null; + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions); + } + set + { + this.Properties["baseUrlForCanonicalHeader"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + public override void Validate() + { + _ = this.ID; + _ = this.Bucket; + _ = this.ClientEmail; + _ = this.IncludeCanonicalHeader; + _ = this.Name; + _ = this.Prefix; + _ = this.BaseURLForCanonicalHeader; + } + + public Gcs() + { + this.Type = JsonSerializer.Deserialize("\"GCS\""); + } + +#pragma warning disable CS8618 + [SetsRequiredMembers] + Gcs(Dictionary properties) + { + Properties = properties; + } +#pragma warning restore CS8618 + + public static Gcs FromRawUnchecked(Dictionary properties) + { + return new(properties); + } +} diff --git a/src/Imagekit/Models/Accounts/Origins/OriginResponseProperties/S3.cs b/src/Imagekit/Models/Accounts/Origins/OriginResponseProperties/S3.cs new file mode 100644 index 00000000..b2046890 --- /dev/null +++ b/src/Imagekit/Models/Accounts/Origins/OriginResponseProperties/S3.cs @@ -0,0 +1,191 @@ +using System; +using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; +using System.Text.Json; +using System.Text.Json.Serialization; + +namespace Imagekit.Models.Accounts.Origins.OriginResponseProperties; + +[JsonConverter(typeof(ModelConverter))] +public sealed record class S3 : ModelBase, IFromRaw +{ + /// + /// Unique identifier for the origin. This is generated by ImageKit when you create + /// a new origin. + /// + public required string ID + { + get + { + if (!this.Properties.TryGetValue("id", out JsonElement element)) + throw new ArgumentOutOfRangeException("id", "Missing required argument"); + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions) + ?? throw new ArgumentNullException("id"); + } + set + { + this.Properties["id"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + /// + /// S3 bucket name. + /// + public required string Bucket + { + get + { + if (!this.Properties.TryGetValue("bucket", out JsonElement element)) + throw new ArgumentOutOfRangeException("bucket", "Missing required argument"); + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions) + ?? throw new ArgumentNullException("bucket"); + } + set + { + this.Properties["bucket"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + /// + /// Whether to send a Canonical header. + /// + public required bool IncludeCanonicalHeader + { + get + { + if (!this.Properties.TryGetValue("includeCanonicalHeader", out JsonElement element)) + throw new ArgumentOutOfRangeException( + "includeCanonicalHeader", + "Missing required argument" + ); + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions); + } + set + { + this.Properties["includeCanonicalHeader"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + /// + /// Display name of the origin. + /// + public required string Name + { + get + { + if (!this.Properties.TryGetValue("name", out JsonElement element)) + throw new ArgumentOutOfRangeException("name", "Missing required argument"); + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions) + ?? throw new ArgumentNullException("name"); + } + set + { + this.Properties["name"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + /// + /// Path prefix inside the bucket. + /// + public required string Prefix + { + get + { + if (!this.Properties.TryGetValue("prefix", out JsonElement element)) + throw new ArgumentOutOfRangeException("prefix", "Missing required argument"); + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions) + ?? throw new ArgumentNullException("prefix"); + } + set + { + this.Properties["prefix"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + public JsonElement Type + { + get + { + if (!this.Properties.TryGetValue("type", out JsonElement element)) + throw new ArgumentOutOfRangeException("type", "Missing required argument"); + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions); + } + set + { + this.Properties["type"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + /// + /// URL used in the Canonical header (if enabled). + /// + public string? BaseURLForCanonicalHeader + { + get + { + if (!this.Properties.TryGetValue("baseUrlForCanonicalHeader", out JsonElement element)) + return null; + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions); + } + set + { + this.Properties["baseUrlForCanonicalHeader"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + public override void Validate() + { + _ = this.ID; + _ = this.Bucket; + _ = this.IncludeCanonicalHeader; + _ = this.Name; + _ = this.Prefix; + _ = this.BaseURLForCanonicalHeader; + } + + public S3() + { + this.Type = JsonSerializer.Deserialize("\"S3\""); + } + +#pragma warning disable CS8618 + [SetsRequiredMembers] + S3(Dictionary properties) + { + Properties = properties; + } +#pragma warning restore CS8618 + + public static S3 FromRawUnchecked(Dictionary properties) + { + return new(properties); + } +} diff --git a/src/Imagekit/Models/Accounts/Origins/OriginResponseProperties/S3Compatible.cs b/src/Imagekit/Models/Accounts/Origins/OriginResponseProperties/S3Compatible.cs new file mode 100644 index 00000000..8d36f4a9 --- /dev/null +++ b/src/Imagekit/Models/Accounts/Origins/OriginResponseProperties/S3Compatible.cs @@ -0,0 +1,239 @@ +using System; +using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; +using System.Text.Json; +using System.Text.Json.Serialization; + +namespace Imagekit.Models.Accounts.Origins.OriginResponseProperties; + +[JsonConverter(typeof(ModelConverter))] +public sealed record class S3Compatible : ModelBase, IFromRaw +{ + /// + /// Unique identifier for the origin. This is generated by ImageKit when you create + /// a new origin. + /// + public required string ID + { + get + { + if (!this.Properties.TryGetValue("id", out JsonElement element)) + throw new ArgumentOutOfRangeException("id", "Missing required argument"); + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions) + ?? throw new ArgumentNullException("id"); + } + set + { + this.Properties["id"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + /// + /// S3 bucket name. + /// + public required string Bucket + { + get + { + if (!this.Properties.TryGetValue("bucket", out JsonElement element)) + throw new ArgumentOutOfRangeException("bucket", "Missing required argument"); + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions) + ?? throw new ArgumentNullException("bucket"); + } + set + { + this.Properties["bucket"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + /// + /// Custom S3-compatible endpoint. + /// + public required string Endpoint + { + get + { + if (!this.Properties.TryGetValue("endpoint", out JsonElement element)) + throw new ArgumentOutOfRangeException("endpoint", "Missing required argument"); + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions) + ?? throw new ArgumentNullException("endpoint"); + } + set + { + this.Properties["endpoint"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + /// + /// Whether to send a Canonical header. + /// + public required bool IncludeCanonicalHeader + { + get + { + if (!this.Properties.TryGetValue("includeCanonicalHeader", out JsonElement element)) + throw new ArgumentOutOfRangeException( + "includeCanonicalHeader", + "Missing required argument" + ); + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions); + } + set + { + this.Properties["includeCanonicalHeader"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + /// + /// Display name of the origin. + /// + public required string Name + { + get + { + if (!this.Properties.TryGetValue("name", out JsonElement element)) + throw new ArgumentOutOfRangeException("name", "Missing required argument"); + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions) + ?? throw new ArgumentNullException("name"); + } + set + { + this.Properties["name"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + /// + /// Path prefix inside the bucket. + /// + public required string Prefix + { + get + { + if (!this.Properties.TryGetValue("prefix", out JsonElement element)) + throw new ArgumentOutOfRangeException("prefix", "Missing required argument"); + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions) + ?? throw new ArgumentNullException("prefix"); + } + set + { + this.Properties["prefix"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + /// + /// Use path-style S3 URLs? + /// + public required bool S3ForcePathStyle + { + get + { + if (!this.Properties.TryGetValue("s3ForcePathStyle", out JsonElement element)) + throw new ArgumentOutOfRangeException( + "s3ForcePathStyle", + "Missing required argument" + ); + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions); + } + set + { + this.Properties["s3ForcePathStyle"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + public JsonElement Type + { + get + { + if (!this.Properties.TryGetValue("type", out JsonElement element)) + throw new ArgumentOutOfRangeException("type", "Missing required argument"); + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions); + } + set + { + this.Properties["type"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + /// + /// URL used in the Canonical header (if enabled). + /// + public string? BaseURLForCanonicalHeader + { + get + { + if (!this.Properties.TryGetValue("baseUrlForCanonicalHeader", out JsonElement element)) + return null; + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions); + } + set + { + this.Properties["baseUrlForCanonicalHeader"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + public override void Validate() + { + _ = this.ID; + _ = this.Bucket; + _ = this.Endpoint; + _ = this.IncludeCanonicalHeader; + _ = this.Name; + _ = this.Prefix; + _ = this.S3ForcePathStyle; + _ = this.BaseURLForCanonicalHeader; + } + + public S3Compatible() + { + this.Type = JsonSerializer.Deserialize("\"S3_COMPATIBLE\""); + } + +#pragma warning disable CS8618 + [SetsRequiredMembers] + S3Compatible(Dictionary properties) + { + Properties = properties; + } +#pragma warning restore CS8618 + + public static S3Compatible FromRawUnchecked(Dictionary properties) + { + return new(properties); + } +} diff --git a/src/Imagekit/Models/Accounts/Origins/OriginResponseProperties/WebFolder.cs b/src/Imagekit/Models/Accounts/Origins/OriginResponseProperties/WebFolder.cs new file mode 100644 index 00000000..8313749f --- /dev/null +++ b/src/Imagekit/Models/Accounts/Origins/OriginResponseProperties/WebFolder.cs @@ -0,0 +1,193 @@ +using System; +using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; +using System.Text.Json; +using System.Text.Json.Serialization; + +namespace Imagekit.Models.Accounts.Origins.OriginResponseProperties; + +[JsonConverter(typeof(ModelConverter))] +public sealed record class WebFolder : ModelBase, IFromRaw +{ + /// + /// Unique identifier for the origin. This is generated by ImageKit when you create + /// a new origin. + /// + public required string ID + { + get + { + if (!this.Properties.TryGetValue("id", out JsonElement element)) + throw new ArgumentOutOfRangeException("id", "Missing required argument"); + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions) + ?? throw new ArgumentNullException("id"); + } + set + { + this.Properties["id"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + /// + /// Root URL for the web folder origin. + /// + public required string BaseURL + { + get + { + if (!this.Properties.TryGetValue("baseUrl", out JsonElement element)) + throw new ArgumentOutOfRangeException("baseUrl", "Missing required argument"); + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions) + ?? throw new ArgumentNullException("baseUrl"); + } + set + { + this.Properties["baseUrl"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + /// + /// Forward the Host header to origin? + /// + public required bool ForwardHostHeaderToOrigin + { + get + { + if (!this.Properties.TryGetValue("forwardHostHeaderToOrigin", out JsonElement element)) + throw new ArgumentOutOfRangeException( + "forwardHostHeaderToOrigin", + "Missing required argument" + ); + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions); + } + set + { + this.Properties["forwardHostHeaderToOrigin"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + /// + /// Whether to send a Canonical header. + /// + public required bool IncludeCanonicalHeader + { + get + { + if (!this.Properties.TryGetValue("includeCanonicalHeader", out JsonElement element)) + throw new ArgumentOutOfRangeException( + "includeCanonicalHeader", + "Missing required argument" + ); + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions); + } + set + { + this.Properties["includeCanonicalHeader"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + /// + /// Display name of the origin. + /// + public required string Name + { + get + { + if (!this.Properties.TryGetValue("name", out JsonElement element)) + throw new ArgumentOutOfRangeException("name", "Missing required argument"); + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions) + ?? throw new ArgumentNullException("name"); + } + set + { + this.Properties["name"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + public JsonElement Type + { + get + { + if (!this.Properties.TryGetValue("type", out JsonElement element)) + throw new ArgumentOutOfRangeException("type", "Missing required argument"); + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions); + } + set + { + this.Properties["type"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + /// + /// URL used in the Canonical header (if enabled). + /// + public string? BaseURLForCanonicalHeader + { + get + { + if (!this.Properties.TryGetValue("baseUrlForCanonicalHeader", out JsonElement element)) + return null; + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions); + } + set + { + this.Properties["baseUrlForCanonicalHeader"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + public override void Validate() + { + _ = this.ID; + _ = this.BaseURL; + _ = this.ForwardHostHeaderToOrigin; + _ = this.IncludeCanonicalHeader; + _ = this.Name; + _ = this.BaseURLForCanonicalHeader; + } + + public WebFolder() + { + this.Type = JsonSerializer.Deserialize("\"WEB_FOLDER\""); + } + +#pragma warning disable CS8618 + [SetsRequiredMembers] + WebFolder(Dictionary properties) + { + Properties = properties; + } +#pragma warning restore CS8618 + + public static WebFolder FromRawUnchecked(Dictionary properties) + { + return new(properties); + } +} diff --git a/src/Imagekit/Models/Accounts/Origins/OriginResponseProperties/WebProxy.cs b/src/Imagekit/Models/Accounts/Origins/OriginResponseProperties/WebProxy.cs new file mode 100644 index 00000000..150c5901 --- /dev/null +++ b/src/Imagekit/Models/Accounts/Origins/OriginResponseProperties/WebProxy.cs @@ -0,0 +1,145 @@ +using System; +using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; +using System.Text.Json; +using System.Text.Json.Serialization; + +namespace Imagekit.Models.Accounts.Origins.OriginResponseProperties; + +[JsonConverter(typeof(ModelConverter))] +public sealed record class WebProxy : ModelBase, IFromRaw +{ + /// + /// Unique identifier for the origin. This is generated by ImageKit when you create + /// a new origin. + /// + public required string ID + { + get + { + if (!this.Properties.TryGetValue("id", out JsonElement element)) + throw new ArgumentOutOfRangeException("id", "Missing required argument"); + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions) + ?? throw new ArgumentNullException("id"); + } + set + { + this.Properties["id"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + /// + /// Whether to send a Canonical header. + /// + public required bool IncludeCanonicalHeader + { + get + { + if (!this.Properties.TryGetValue("includeCanonicalHeader", out JsonElement element)) + throw new ArgumentOutOfRangeException( + "includeCanonicalHeader", + "Missing required argument" + ); + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions); + } + set + { + this.Properties["includeCanonicalHeader"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + /// + /// Display name of the origin. + /// + public required string Name + { + get + { + if (!this.Properties.TryGetValue("name", out JsonElement element)) + throw new ArgumentOutOfRangeException("name", "Missing required argument"); + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions) + ?? throw new ArgumentNullException("name"); + } + set + { + this.Properties["name"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + public JsonElement Type + { + get + { + if (!this.Properties.TryGetValue("type", out JsonElement element)) + throw new ArgumentOutOfRangeException("type", "Missing required argument"); + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions); + } + set + { + this.Properties["type"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + /// + /// URL used in the Canonical header (if enabled). + /// + public string? BaseURLForCanonicalHeader + { + get + { + if (!this.Properties.TryGetValue("baseUrlForCanonicalHeader", out JsonElement element)) + return null; + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions); + } + set + { + this.Properties["baseUrlForCanonicalHeader"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + public override void Validate() + { + _ = this.ID; + _ = this.IncludeCanonicalHeader; + _ = this.Name; + _ = this.BaseURLForCanonicalHeader; + } + + public WebProxy() + { + this.Type = JsonSerializer.Deserialize("\"WEB_PROXY\""); + } + +#pragma warning disable CS8618 + [SetsRequiredMembers] + WebProxy(Dictionary properties) + { + Properties = properties; + } +#pragma warning restore CS8618 + + public static WebProxy FromRawUnchecked(Dictionary properties) + { + return new(properties); + } +} diff --git a/src/Imagekit/Models/Accounts/Origins/OriginResponseVariants/All.cs b/src/Imagekit/Models/Accounts/Origins/OriginResponseVariants/All.cs new file mode 100644 index 00000000..cb69f75d --- /dev/null +++ b/src/Imagekit/Models/Accounts/Origins/OriginResponseVariants/All.cs @@ -0,0 +1,123 @@ +using OriginResponseProperties = Imagekit.Models.Accounts.Origins.OriginResponseProperties; + +namespace Imagekit.Models.Accounts.Origins.OriginResponseVariants; + +public sealed record class S3(OriginResponseProperties::S3 Value) + : OriginResponse, + IVariant +{ + public static S3 From(OriginResponseProperties::S3 value) + { + return new(value); + } + + public override void Validate() + { + this.Value.Validate(); + } +} + +public sealed record class S3Compatible(OriginResponseProperties::S3Compatible Value) + : OriginResponse, + IVariant +{ + public static S3Compatible From(OriginResponseProperties::S3Compatible value) + { + return new(value); + } + + public override void Validate() + { + this.Value.Validate(); + } +} + +public sealed record class CloudinaryBackup(OriginResponseProperties::CloudinaryBackup Value) + : OriginResponse, + IVariant +{ + public static CloudinaryBackup From(OriginResponseProperties::CloudinaryBackup value) + { + return new(value); + } + + public override void Validate() + { + this.Value.Validate(); + } +} + +public sealed record class WebFolder(OriginResponseProperties::WebFolder Value) + : OriginResponse, + IVariant +{ + public static WebFolder From(OriginResponseProperties::WebFolder value) + { + return new(value); + } + + public override void Validate() + { + this.Value.Validate(); + } +} + +public sealed record class WebProxy(OriginResponseProperties::WebProxy Value) + : OriginResponse, + IVariant +{ + public static WebProxy From(OriginResponseProperties::WebProxy value) + { + return new(value); + } + + public override void Validate() + { + this.Value.Validate(); + } +} + +public sealed record class Gcs(OriginResponseProperties::Gcs Value) + : OriginResponse, + IVariant +{ + public static Gcs From(OriginResponseProperties::Gcs value) + { + return new(value); + } + + public override void Validate() + { + this.Value.Validate(); + } +} + +public sealed record class AzureBlob(OriginResponseProperties::AzureBlob Value) + : OriginResponse, + IVariant +{ + public static AzureBlob From(OriginResponseProperties::AzureBlob value) + { + return new(value); + } + + public override void Validate() + { + this.Value.Validate(); + } +} + +public sealed record class AkeneoPim(OriginResponseProperties::AkeneoPim Value) + : OriginResponse, + IVariant +{ + public static AkeneoPim From(OriginResponseProperties::AkeneoPim value) + { + return new(value); + } + + public override void Validate() + { + this.Value.Validate(); + } +} diff --git a/src/Imagekit/Models/Accounts/Origins/OriginUpdateParams.cs b/src/Imagekit/Models/Accounts/Origins/OriginUpdateParams.cs new file mode 100644 index 00000000..e2b40c56 --- /dev/null +++ b/src/Imagekit/Models/Accounts/Origins/OriginUpdateParams.cs @@ -0,0 +1,69 @@ +using System; +using System.Collections.Generic; +using System.Net.Http; +using System.Text; +using System.Text.Json; + +namespace Imagekit.Models.Accounts.Origins; + +/// +/// **Note:** This API is currently in beta. Updates the origin identified by `id` +/// and returns the updated origin object. +/// +public sealed record class OriginUpdateParams : ParamsBase +{ + public Dictionary BodyProperties { get; set; } = []; + + public required string ID; + + /// + /// Schema for origin request resources. + /// + public required OriginRequest Origin + { + get + { + if (!this.BodyProperties.TryGetValue("origin", out JsonElement element)) + throw new ArgumentOutOfRangeException("origin", "Missing required argument"); + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions) + ?? throw new ArgumentNullException("origin"); + } + set + { + this.BodyProperties["origin"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + public override Uri Url(IImageKitClient client) + { + return new UriBuilder( + client.BaseUrl.ToString().TrimEnd('/') + + string.Format("/v1/accounts/origins/{0}", this.ID) + ) + { + Query = this.QueryString(client), + }.Uri; + } + + public StringContent BodyContent() + { + return new( + JsonSerializer.Serialize(this.BodyProperties), + Encoding.UTF8, + "application/json" + ); + } + + public void AddHeadersToRequest(HttpRequestMessage request, IImageKitClient client) + { + ParamsBase.AddDefaultHeaders(request, client); + foreach (var item in this.HeaderProperties) + { + ParamsBase.AddHeaderElementToRequest(request, item.Key, item.Value); + } + } +} diff --git a/src/Imagekit/Models/Accounts/URLEndpoints/URLEndpointCreateParams.cs b/src/Imagekit/Models/Accounts/URLEndpoints/URLEndpointCreateParams.cs new file mode 100644 index 00000000..246f09e9 --- /dev/null +++ b/src/Imagekit/Models/Accounts/URLEndpoints/URLEndpointCreateParams.cs @@ -0,0 +1,131 @@ +using System; +using System.Collections.Generic; +using System.Net.Http; +using System.Text; +using System.Text.Json; +using Imagekit.Models.Accounts.URLEndpoints.URLEndpointCreateParamsProperties; + +namespace Imagekit.Models.Accounts.URLEndpoints; + +/// +/// **Note:** This API is currently in beta. Creates a new URL‑endpoint and returns +/// the resulting object. +/// +public sealed record class URLEndpointCreateParams : ParamsBase +{ + public Dictionary BodyProperties { get; set; } = []; + + /// + /// Description of the URL endpoint. + /// + public required string Description + { + get + { + if (!this.BodyProperties.TryGetValue("description", out JsonElement element)) + throw new ArgumentOutOfRangeException("description", "Missing required argument"); + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions) + ?? throw new ArgumentNullException("description"); + } + set + { + this.BodyProperties["description"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + /// + /// Ordered list of origin IDs to try when the file isn’t in the Media Library; + /// ImageKit checks them in the sequence provided. Origin must be created before + /// it can be used in a URL endpoint. + /// + public List? Origins + { + get + { + if (!this.BodyProperties.TryGetValue("origins", out JsonElement element)) + return null; + + return JsonSerializer.Deserialize?>(element, ModelBase.SerializerOptions); + } + set + { + this.BodyProperties["origins"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + /// + /// Path segment appended to your base URL to form the endpoint (letters, digits, + /// and hyphens only — or empty for the default endpoint). + /// + public string? URLPrefix + { + get + { + if (!this.BodyProperties.TryGetValue("urlPrefix", out JsonElement element)) + return null; + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions); + } + set + { + this.BodyProperties["urlPrefix"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + /// + /// Configuration for third-party URL rewriting. + /// + public URLRewriter? URLRewriter + { + get + { + if (!this.BodyProperties.TryGetValue("urlRewriter", out JsonElement element)) + return null; + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions); + } + set + { + this.BodyProperties["urlRewriter"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + public override Uri Url(IImageKitClient client) + { + return new UriBuilder(client.BaseUrl.ToString().TrimEnd('/') + "/v1/accounts/url-endpoints") + { + Query = this.QueryString(client), + }.Uri; + } + + public StringContent BodyContent() + { + return new( + JsonSerializer.Serialize(this.BodyProperties), + Encoding.UTF8, + "application/json" + ); + } + + public void AddHeadersToRequest(HttpRequestMessage request, IImageKitClient client) + { + ParamsBase.AddDefaultHeaders(request, client); + foreach (var item in this.HeaderProperties) + { + ParamsBase.AddHeaderElementToRequest(request, item.Key, item.Value); + } + } +} diff --git a/src/Imagekit/Models/Accounts/URLEndpoints/URLEndpointCreateParamsProperties/URLRewriter.cs b/src/Imagekit/Models/Accounts/URLEndpoints/URLEndpointCreateParamsProperties/URLRewriter.cs new file mode 100644 index 00000000..5d26268a --- /dev/null +++ b/src/Imagekit/Models/Accounts/URLEndpoints/URLEndpointCreateParamsProperties/URLRewriter.cs @@ -0,0 +1,176 @@ +using System; +using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; +using System.Text.Json; +using System.Text.Json.Serialization; +using Imagekit.Models.Accounts.URLEndpoints.URLEndpointCreateParamsProperties.URLRewriterProperties; +using URLRewriterVariants = Imagekit.Models.Accounts.URLEndpoints.URLEndpointCreateParamsProperties.URLRewriterVariants; + +namespace Imagekit.Models.Accounts.URLEndpoints.URLEndpointCreateParamsProperties; + +/// +/// Configuration for third-party URL rewriting. +/// +[JsonConverter(typeof(URLRewriterConverter))] +public abstract record class URLRewriter +{ + internal URLRewriter() { } + + public static implicit operator URLRewriter(Cloudinary value) => + new URLRewriterVariants::Cloudinary(value); + + public bool TryPickCloudinary([NotNullWhen(true)] out Cloudinary? value) + { + value = (this as URLRewriterVariants::Cloudinary)?.Value; + return value != null; + } + + public bool TryPickImgix([NotNullWhen(true)] out JsonElement? value) + { + value = (this as URLRewriterVariants::Imgix)?.Value; + return value != null; + } + + public bool TryPickAkamai([NotNullWhen(true)] out JsonElement? value) + { + value = (this as URLRewriterVariants::Akamai)?.Value; + return value != null; + } + + public void Switch( + Action cloudinary, + Action imgix, + Action akamai + ) + { + switch (this) + { + case URLRewriterVariants::Cloudinary inner: + cloudinary(inner); + break; + case URLRewriterVariants::Imgix inner: + imgix(inner); + break; + case URLRewriterVariants::Akamai inner: + akamai(inner); + break; + default: + throw new InvalidOperationException(); + } + } + + public T Match( + Func cloudinary, + Func imgix, + Func akamai + ) + { + return this switch + { + URLRewriterVariants::Cloudinary inner => cloudinary(inner), + URLRewriterVariants::Imgix inner => imgix(inner), + URLRewriterVariants::Akamai inner => akamai(inner), + _ => throw new InvalidOperationException(), + }; + } + + public abstract void Validate(); +} + +sealed class URLRewriterConverter : JsonConverter +{ + public override URLRewriter? Read( + ref Utf8JsonReader reader, + Type typeToConvert, + JsonSerializerOptions options + ) + { + var json = JsonSerializer.Deserialize(ref reader, options); + string? type; + try + { + type = json.GetProperty("type").GetString(); + } + catch + { + type = null; + } + + switch (type) + { + case "CLOUDINARY": + { + List exceptions = []; + + try + { + var deserialized = JsonSerializer.Deserialize(json, options); + if (deserialized != null) + { + return new URLRewriterVariants::Cloudinary(deserialized); + } + } + catch (JsonException e) + { + exceptions.Add(e); + } + + throw new AggregateException(exceptions); + } + case "IMGIX": + { + List exceptions = []; + + try + { + return new URLRewriterVariants::Imgix( + JsonSerializer.Deserialize(json, options) + ); + } + catch (JsonException e) + { + exceptions.Add(e); + } + + throw new AggregateException(exceptions); + } + case "AKAMAI": + { + List exceptions = []; + + try + { + return new URLRewriterVariants::Akamai( + JsonSerializer.Deserialize(json, options) + ); + } + catch (JsonException e) + { + exceptions.Add(e); + } + + throw new AggregateException(exceptions); + } + default: + { + throw new Exception(); + } + } + } + + public override void Write( + Utf8JsonWriter writer, + URLRewriter value, + JsonSerializerOptions options + ) + { + object variant = value switch + { + URLRewriterVariants::Cloudinary(var cloudinary) => cloudinary, + URLRewriterVariants::Imgix(var imgix) => imgix, + URLRewriterVariants::Akamai(var akamai) => akamai, + _ => throw new ArgumentOutOfRangeException(nameof(value)), + }; + JsonSerializer.Serialize(writer, variant, options); + } +} diff --git a/src/Imagekit/Models/Accounts/URLEndpoints/URLEndpointCreateParamsProperties/URLRewriterProperties/Cloudinary.cs b/src/Imagekit/Models/Accounts/URLEndpoints/URLEndpointCreateParamsProperties/URLRewriterProperties/Cloudinary.cs new file mode 100644 index 00000000..e1342282 --- /dev/null +++ b/src/Imagekit/Models/Accounts/URLEndpoints/URLEndpointCreateParamsProperties/URLRewriterProperties/Cloudinary.cs @@ -0,0 +1,73 @@ +using System; +using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; +using System.Text.Json; +using System.Text.Json.Serialization; + +namespace Imagekit.Models.Accounts.URLEndpoints.URLEndpointCreateParamsProperties.URLRewriterProperties; + +[JsonConverter(typeof(ModelConverter))] +public sealed record class Cloudinary : ModelBase, IFromRaw +{ + public JsonElement Type + { + get + { + if (!this.Properties.TryGetValue("type", out JsonElement element)) + throw new ArgumentOutOfRangeException("type", "Missing required argument"); + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions); + } + set + { + this.Properties["type"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + /// + /// Whether to preserve `/` in the rewritten URL. + /// + public bool? PreserveAssetDeliveryTypes + { + get + { + if (!this.Properties.TryGetValue("preserveAssetDeliveryTypes", out JsonElement element)) + return null; + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions); + } + set + { + this.Properties["preserveAssetDeliveryTypes"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + public override void Validate() + { + _ = this.PreserveAssetDeliveryTypes; + } + + public Cloudinary() + { + this.Type = JsonSerializer.Deserialize("\"CLOUDINARY\""); + } + +#pragma warning disable CS8618 + [SetsRequiredMembers] + Cloudinary(Dictionary properties) + { + Properties = properties; + } +#pragma warning restore CS8618 + + public static Cloudinary FromRawUnchecked(Dictionary properties) + { + return new(properties); + } +} diff --git a/src/Imagekit/Models/Accounts/URLEndpoints/URLEndpointCreateParamsProperties/URLRewriterVariants/All.cs b/src/Imagekit/Models/Accounts/URLEndpoints/URLEndpointCreateParamsProperties/URLRewriterVariants/All.cs new file mode 100644 index 00000000..bbef6b5d --- /dev/null +++ b/src/Imagekit/Models/Accounts/URLEndpoints/URLEndpointCreateParamsProperties/URLRewriterVariants/All.cs @@ -0,0 +1,39 @@ +using System.Text.Json; +using URLRewriterProperties = Imagekit.Models.Accounts.URLEndpoints.URLEndpointCreateParamsProperties.URLRewriterProperties; + +namespace Imagekit.Models.Accounts.URLEndpoints.URLEndpointCreateParamsProperties.URLRewriterVariants; + +public sealed record class Cloudinary(URLRewriterProperties::Cloudinary Value) + : URLRewriter, + IVariant +{ + public static Cloudinary From(URLRewriterProperties::Cloudinary value) + { + return new(value); + } + + public override void Validate() + { + this.Value.Validate(); + } +} + +public sealed record class Imgix(JsonElement Value) : URLRewriter, IVariant +{ + public static Imgix From(JsonElement value) + { + return new(value); + } + + public override void Validate() { } +} + +public sealed record class Akamai(JsonElement Value) : URLRewriter, IVariant +{ + public static Akamai From(JsonElement value) + { + return new(value); + } + + public override void Validate() { } +} diff --git a/src/Imagekit/Models/Accounts/URLEndpoints/URLEndpointDeleteParams.cs b/src/Imagekit/Models/Accounts/URLEndpoints/URLEndpointDeleteParams.cs new file mode 100644 index 00000000..7c5510bf --- /dev/null +++ b/src/Imagekit/Models/Accounts/URLEndpoints/URLEndpointDeleteParams.cs @@ -0,0 +1,34 @@ +using System; +using System.Net.Http; + +namespace Imagekit.Models.Accounts.URLEndpoints; + +/// +/// **Note:** This API is currently in beta. Deletes the URL‑endpoint identified +/// by `id`. You cannot delete the default URL‑endpoint created by ImageKit during +/// account creation. +/// +public sealed record class URLEndpointDeleteParams : ParamsBase +{ + public required string ID; + + public override Uri Url(IImageKitClient client) + { + return new UriBuilder( + client.BaseUrl.ToString().TrimEnd('/') + + string.Format("/v1/accounts/url-endpoints/{0}", this.ID) + ) + { + Query = this.QueryString(client), + }.Uri; + } + + public void AddHeadersToRequest(HttpRequestMessage request, IImageKitClient client) + { + ParamsBase.AddDefaultHeaders(request, client); + foreach (var item in this.HeaderProperties) + { + ParamsBase.AddHeaderElementToRequest(request, item.Key, item.Value); + } + } +} diff --git a/src/Imagekit/Models/Accounts/URLEndpoints/URLEndpointGetParams.cs b/src/Imagekit/Models/Accounts/URLEndpoints/URLEndpointGetParams.cs new file mode 100644 index 00000000..785de18a --- /dev/null +++ b/src/Imagekit/Models/Accounts/URLEndpoints/URLEndpointGetParams.cs @@ -0,0 +1,33 @@ +using System; +using System.Net.Http; + +namespace Imagekit.Models.Accounts.URLEndpoints; + +/// +/// **Note:** This API is currently in beta. Retrieves the URL‑endpoint identified +/// by `id`. +/// +public sealed record class URLEndpointGetParams : ParamsBase +{ + public required string ID; + + public override Uri Url(IImageKitClient client) + { + return new UriBuilder( + client.BaseUrl.ToString().TrimEnd('/') + + string.Format("/v1/accounts/url-endpoints/{0}", this.ID) + ) + { + Query = this.QueryString(client), + }.Uri; + } + + public void AddHeadersToRequest(HttpRequestMessage request, IImageKitClient client) + { + ParamsBase.AddDefaultHeaders(request, client); + foreach (var item in this.HeaderProperties) + { + ParamsBase.AddHeaderElementToRequest(request, item.Key, item.Value); + } + } +} diff --git a/src/Imagekit/Models/Accounts/URLEndpoints/URLEndpointListParams.cs b/src/Imagekit/Models/Accounts/URLEndpoints/URLEndpointListParams.cs new file mode 100644 index 00000000..86dcc613 --- /dev/null +++ b/src/Imagekit/Models/Accounts/URLEndpoints/URLEndpointListParams.cs @@ -0,0 +1,29 @@ +using System; +using System.Net.Http; + +namespace Imagekit.Models.Accounts.URLEndpoints; + +/// +/// **Note:** This API is currently in beta. Returns an array of all URL‑endpoints +/// configured including the default URL-endpoint generated by ImageKit during account +/// creation. +/// +public sealed record class URLEndpointListParams : ParamsBase +{ + public override Uri Url(IImageKitClient client) + { + return new UriBuilder(client.BaseUrl.ToString().TrimEnd('/') + "/v1/accounts/url-endpoints") + { + Query = this.QueryString(client), + }.Uri; + } + + public void AddHeadersToRequest(HttpRequestMessage request, IImageKitClient client) + { + ParamsBase.AddDefaultHeaders(request, client); + foreach (var item in this.HeaderProperties) + { + ParamsBase.AddHeaderElementToRequest(request, item.Key, item.Value); + } + } +} diff --git a/src/Imagekit/Models/Accounts/URLEndpoints/URLEndpointRequest.cs b/src/Imagekit/Models/Accounts/URLEndpoints/URLEndpointRequest.cs new file mode 100644 index 00000000..69d87d20 --- /dev/null +++ b/src/Imagekit/Models/Accounts/URLEndpoints/URLEndpointRequest.cs @@ -0,0 +1,136 @@ +using System; +using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; +using System.Text.Json; +using System.Text.Json.Serialization; +using Imagekit.Models.Accounts.URLEndpoints.URLEndpointRequestProperties; + +namespace Imagekit.Models.Accounts.URLEndpoints; + +/// +/// Schema for URL endpoint resource. +/// +[JsonConverter(typeof(ModelConverter))] +public sealed record class URLEndpointRequest : ModelBase, IFromRaw +{ + /// + /// Description of the URL endpoint. + /// + public required string Description + { + get + { + if (!this.Properties.TryGetValue("description", out JsonElement element)) + throw new ArgumentOutOfRangeException("description", "Missing required argument"); + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions) + ?? throw new ArgumentNullException("description"); + } + set + { + this.Properties["description"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + /// + /// Ordered list of origin IDs to try when the file isn’t in the Media Library; + /// ImageKit checks them in the sequence provided. Origin must be created before + /// it can be used in a URL endpoint. + /// + public List? Origins + { + get + { + if (!this.Properties.TryGetValue("origins", out JsonElement element)) + return null; + + return JsonSerializer.Deserialize?>(element, ModelBase.SerializerOptions); + } + set + { + this.Properties["origins"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + /// + /// Path segment appended to your base URL to form the endpoint (letters, digits, + /// and hyphens only — or empty for the default endpoint). + /// + public string? URLPrefix + { + get + { + if (!this.Properties.TryGetValue("urlPrefix", out JsonElement element)) + return null; + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions); + } + set + { + this.Properties["urlPrefix"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + /// + /// Configuration for third-party URL rewriting. + /// + public URLRewriter? URLRewriter + { + get + { + if (!this.Properties.TryGetValue("urlRewriter", out JsonElement element)) + return null; + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions); + } + set + { + this.Properties["urlRewriter"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + public override void Validate() + { + _ = this.Description; + foreach (var item in this.Origins ?? []) + { + _ = item; + } + _ = this.URLPrefix; + this.URLRewriter?.Validate(); + } + + public URLEndpointRequest() { } + +#pragma warning disable CS8618 + [SetsRequiredMembers] + URLEndpointRequest(Dictionary properties) + { + Properties = properties; + } +#pragma warning restore CS8618 + + public static URLEndpointRequest FromRawUnchecked(Dictionary properties) + { + return new(properties); + } + + [SetsRequiredMembers] + public URLEndpointRequest(string description) + : this() + { + this.Description = description; + } +} diff --git a/src/Imagekit/Models/Accounts/URLEndpoints/URLEndpointRequestProperties/URLRewriter.cs b/src/Imagekit/Models/Accounts/URLEndpoints/URLEndpointRequestProperties/URLRewriter.cs new file mode 100644 index 00000000..9ee41202 --- /dev/null +++ b/src/Imagekit/Models/Accounts/URLEndpoints/URLEndpointRequestProperties/URLRewriter.cs @@ -0,0 +1,176 @@ +using System; +using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; +using System.Text.Json; +using System.Text.Json.Serialization; +using Imagekit.Models.Accounts.URLEndpoints.URLEndpointRequestProperties.URLRewriterProperties; +using URLRewriterVariants = Imagekit.Models.Accounts.URLEndpoints.URLEndpointRequestProperties.URLRewriterVariants; + +namespace Imagekit.Models.Accounts.URLEndpoints.URLEndpointRequestProperties; + +/// +/// Configuration for third-party URL rewriting. +/// +[JsonConverter(typeof(URLRewriterConverter))] +public abstract record class URLRewriter +{ + internal URLRewriter() { } + + public static implicit operator URLRewriter(Cloudinary value) => + new URLRewriterVariants::Cloudinary(value); + + public bool TryPickCloudinary([NotNullWhen(true)] out Cloudinary? value) + { + value = (this as URLRewriterVariants::Cloudinary)?.Value; + return value != null; + } + + public bool TryPickImgix([NotNullWhen(true)] out JsonElement? value) + { + value = (this as URLRewriterVariants::Imgix)?.Value; + return value != null; + } + + public bool TryPickAkamai([NotNullWhen(true)] out JsonElement? value) + { + value = (this as URLRewriterVariants::Akamai)?.Value; + return value != null; + } + + public void Switch( + Action cloudinary, + Action imgix, + Action akamai + ) + { + switch (this) + { + case URLRewriterVariants::Cloudinary inner: + cloudinary(inner); + break; + case URLRewriterVariants::Imgix inner: + imgix(inner); + break; + case URLRewriterVariants::Akamai inner: + akamai(inner); + break; + default: + throw new InvalidOperationException(); + } + } + + public T Match( + Func cloudinary, + Func imgix, + Func akamai + ) + { + return this switch + { + URLRewriterVariants::Cloudinary inner => cloudinary(inner), + URLRewriterVariants::Imgix inner => imgix(inner), + URLRewriterVariants::Akamai inner => akamai(inner), + _ => throw new InvalidOperationException(), + }; + } + + public abstract void Validate(); +} + +sealed class URLRewriterConverter : JsonConverter +{ + public override URLRewriter? Read( + ref Utf8JsonReader reader, + Type typeToConvert, + JsonSerializerOptions options + ) + { + var json = JsonSerializer.Deserialize(ref reader, options); + string? type; + try + { + type = json.GetProperty("type").GetString(); + } + catch + { + type = null; + } + + switch (type) + { + case "CLOUDINARY": + { + List exceptions = []; + + try + { + var deserialized = JsonSerializer.Deserialize(json, options); + if (deserialized != null) + { + return new URLRewriterVariants::Cloudinary(deserialized); + } + } + catch (JsonException e) + { + exceptions.Add(e); + } + + throw new AggregateException(exceptions); + } + case "IMGIX": + { + List exceptions = []; + + try + { + return new URLRewriterVariants::Imgix( + JsonSerializer.Deserialize(json, options) + ); + } + catch (JsonException e) + { + exceptions.Add(e); + } + + throw new AggregateException(exceptions); + } + case "AKAMAI": + { + List exceptions = []; + + try + { + return new URLRewriterVariants::Akamai( + JsonSerializer.Deserialize(json, options) + ); + } + catch (JsonException e) + { + exceptions.Add(e); + } + + throw new AggregateException(exceptions); + } + default: + { + throw new Exception(); + } + } + } + + public override void Write( + Utf8JsonWriter writer, + URLRewriter value, + JsonSerializerOptions options + ) + { + object variant = value switch + { + URLRewriterVariants::Cloudinary(var cloudinary) => cloudinary, + URLRewriterVariants::Imgix(var imgix) => imgix, + URLRewriterVariants::Akamai(var akamai) => akamai, + _ => throw new ArgumentOutOfRangeException(nameof(value)), + }; + JsonSerializer.Serialize(writer, variant, options); + } +} diff --git a/src/Imagekit/Models/Accounts/URLEndpoints/URLEndpointRequestProperties/URLRewriterProperties/Cloudinary.cs b/src/Imagekit/Models/Accounts/URLEndpoints/URLEndpointRequestProperties/URLRewriterProperties/Cloudinary.cs new file mode 100644 index 00000000..67997088 --- /dev/null +++ b/src/Imagekit/Models/Accounts/URLEndpoints/URLEndpointRequestProperties/URLRewriterProperties/Cloudinary.cs @@ -0,0 +1,73 @@ +using System; +using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; +using System.Text.Json; +using System.Text.Json.Serialization; + +namespace Imagekit.Models.Accounts.URLEndpoints.URLEndpointRequestProperties.URLRewriterProperties; + +[JsonConverter(typeof(ModelConverter))] +public sealed record class Cloudinary : ModelBase, IFromRaw +{ + public JsonElement Type + { + get + { + if (!this.Properties.TryGetValue("type", out JsonElement element)) + throw new ArgumentOutOfRangeException("type", "Missing required argument"); + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions); + } + set + { + this.Properties["type"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + /// + /// Whether to preserve `/` in the rewritten URL. + /// + public bool? PreserveAssetDeliveryTypes + { + get + { + if (!this.Properties.TryGetValue("preserveAssetDeliveryTypes", out JsonElement element)) + return null; + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions); + } + set + { + this.Properties["preserveAssetDeliveryTypes"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + public override void Validate() + { + _ = this.PreserveAssetDeliveryTypes; + } + + public Cloudinary() + { + this.Type = JsonSerializer.Deserialize("\"CLOUDINARY\""); + } + +#pragma warning disable CS8618 + [SetsRequiredMembers] + Cloudinary(Dictionary properties) + { + Properties = properties; + } +#pragma warning restore CS8618 + + public static Cloudinary FromRawUnchecked(Dictionary properties) + { + return new(properties); + } +} diff --git a/src/Imagekit/Models/Accounts/URLEndpoints/URLEndpointRequestProperties/URLRewriterVariants/All.cs b/src/Imagekit/Models/Accounts/URLEndpoints/URLEndpointRequestProperties/URLRewriterVariants/All.cs new file mode 100644 index 00000000..fcad34a1 --- /dev/null +++ b/src/Imagekit/Models/Accounts/URLEndpoints/URLEndpointRequestProperties/URLRewriterVariants/All.cs @@ -0,0 +1,39 @@ +using System.Text.Json; +using URLRewriterProperties = Imagekit.Models.Accounts.URLEndpoints.URLEndpointRequestProperties.URLRewriterProperties; + +namespace Imagekit.Models.Accounts.URLEndpoints.URLEndpointRequestProperties.URLRewriterVariants; + +public sealed record class Cloudinary(URLRewriterProperties::Cloudinary Value) + : URLRewriter, + IVariant +{ + public static Cloudinary From(URLRewriterProperties::Cloudinary value) + { + return new(value); + } + + public override void Validate() + { + this.Value.Validate(); + } +} + +public sealed record class Imgix(JsonElement Value) : URLRewriter, IVariant +{ + public static Imgix From(JsonElement value) + { + return new(value); + } + + public override void Validate() { } +} + +public sealed record class Akamai(JsonElement Value) : URLRewriter, IVariant +{ + public static Akamai From(JsonElement value) + { + return new(value); + } + + public override void Validate() { } +} diff --git a/src/Imagekit/Models/Accounts/URLEndpoints/URLEndpointResponse.cs b/src/Imagekit/Models/Accounts/URLEndpoints/URLEndpointResponse.cs new file mode 100644 index 00000000..478785dc --- /dev/null +++ b/src/Imagekit/Models/Accounts/URLEndpoints/URLEndpointResponse.cs @@ -0,0 +1,155 @@ +using System; +using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; +using System.Text.Json; +using System.Text.Json.Serialization; +using Imagekit.Models.Accounts.URLEndpoints.URLEndpointResponseProperties; + +namespace Imagekit.Models.Accounts.URLEndpoints; + +/// +/// URL‑endpoint object as returned by the API. +/// +[JsonConverter(typeof(ModelConverter))] +public sealed record class URLEndpointResponse : ModelBase, IFromRaw +{ + /// + /// Unique identifier for the URL-endpoint. This is generated by ImageKit when + /// you create a new URL-endpoint. For the default URL-endpoint, this is always `default`. + /// + public required string ID + { + get + { + if (!this.Properties.TryGetValue("id", out JsonElement element)) + throw new ArgumentOutOfRangeException("id", "Missing required argument"); + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions) + ?? throw new ArgumentNullException("id"); + } + set + { + this.Properties["id"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + /// + /// Description of the URL endpoint. + /// + public required string Description + { + get + { + if (!this.Properties.TryGetValue("description", out JsonElement element)) + throw new ArgumentOutOfRangeException("description", "Missing required argument"); + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions) + ?? throw new ArgumentNullException("description"); + } + set + { + this.Properties["description"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + /// + /// Ordered list of origin IDs to try when the file isn’t in the Media Library; + /// ImageKit checks them in the sequence provided. Origin must be created before + /// it can be used in a URL endpoint. + /// + public required List Origins + { + get + { + if (!this.Properties.TryGetValue("origins", out JsonElement element)) + throw new ArgumentOutOfRangeException("origins", "Missing required argument"); + + return JsonSerializer.Deserialize>(element, ModelBase.SerializerOptions) + ?? throw new ArgumentNullException("origins"); + } + set + { + this.Properties["origins"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + /// + /// Path segment appended to your base URL to form the endpoint (letters, digits, + /// and hyphens only — or empty for the default endpoint). + /// + public required string URLPrefix + { + get + { + if (!this.Properties.TryGetValue("urlPrefix", out JsonElement element)) + throw new ArgumentOutOfRangeException("urlPrefix", "Missing required argument"); + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions) + ?? throw new ArgumentNullException("urlPrefix"); + } + set + { + this.Properties["urlPrefix"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + /// + /// Configuration for third-party URL rewriting. + /// + public URLRewriter? URLRewriter + { + get + { + if (!this.Properties.TryGetValue("urlRewriter", out JsonElement element)) + return null; + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions); + } + set + { + this.Properties["urlRewriter"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + public override void Validate() + { + _ = this.ID; + _ = this.Description; + foreach (var item in this.Origins) + { + _ = item; + } + _ = this.URLPrefix; + this.URLRewriter?.Validate(); + } + + public URLEndpointResponse() { } + +#pragma warning disable CS8618 + [SetsRequiredMembers] + URLEndpointResponse(Dictionary properties) + { + Properties = properties; + } +#pragma warning restore CS8618 + + public static URLEndpointResponse FromRawUnchecked(Dictionary properties) + { + return new(properties); + } +} diff --git a/src/Imagekit/Models/Accounts/URLEndpoints/URLEndpointResponseProperties/URLRewriter.cs b/src/Imagekit/Models/Accounts/URLEndpoints/URLEndpointResponseProperties/URLRewriter.cs new file mode 100644 index 00000000..26256e1c --- /dev/null +++ b/src/Imagekit/Models/Accounts/URLEndpoints/URLEndpointResponseProperties/URLRewriter.cs @@ -0,0 +1,176 @@ +using System; +using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; +using System.Text.Json; +using System.Text.Json.Serialization; +using Imagekit.Models.Accounts.URLEndpoints.URLEndpointResponseProperties.URLRewriterProperties; +using URLRewriterVariants = Imagekit.Models.Accounts.URLEndpoints.URLEndpointResponseProperties.URLRewriterVariants; + +namespace Imagekit.Models.Accounts.URLEndpoints.URLEndpointResponseProperties; + +/// +/// Configuration for third-party URL rewriting. +/// +[JsonConverter(typeof(URLRewriterConverter))] +public abstract record class URLRewriter +{ + internal URLRewriter() { } + + public static implicit operator URLRewriter(Cloudinary value) => + new URLRewriterVariants::Cloudinary(value); + + public bool TryPickCloudinary([NotNullWhen(true)] out Cloudinary? value) + { + value = (this as URLRewriterVariants::Cloudinary)?.Value; + return value != null; + } + + public bool TryPickImgix([NotNullWhen(true)] out JsonElement? value) + { + value = (this as URLRewriterVariants::Imgix)?.Value; + return value != null; + } + + public bool TryPickAkamai([NotNullWhen(true)] out JsonElement? value) + { + value = (this as URLRewriterVariants::Akamai)?.Value; + return value != null; + } + + public void Switch( + Action cloudinary, + Action imgix, + Action akamai + ) + { + switch (this) + { + case URLRewriterVariants::Cloudinary inner: + cloudinary(inner); + break; + case URLRewriterVariants::Imgix inner: + imgix(inner); + break; + case URLRewriterVariants::Akamai inner: + akamai(inner); + break; + default: + throw new InvalidOperationException(); + } + } + + public T Match( + Func cloudinary, + Func imgix, + Func akamai + ) + { + return this switch + { + URLRewriterVariants::Cloudinary inner => cloudinary(inner), + URLRewriterVariants::Imgix inner => imgix(inner), + URLRewriterVariants::Akamai inner => akamai(inner), + _ => throw new InvalidOperationException(), + }; + } + + public abstract void Validate(); +} + +sealed class URLRewriterConverter : JsonConverter +{ + public override URLRewriter? Read( + ref Utf8JsonReader reader, + Type typeToConvert, + JsonSerializerOptions options + ) + { + var json = JsonSerializer.Deserialize(ref reader, options); + string? type; + try + { + type = json.GetProperty("type").GetString(); + } + catch + { + type = null; + } + + switch (type) + { + case "CLOUDINARY": + { + List exceptions = []; + + try + { + var deserialized = JsonSerializer.Deserialize(json, options); + if (deserialized != null) + { + return new URLRewriterVariants::Cloudinary(deserialized); + } + } + catch (JsonException e) + { + exceptions.Add(e); + } + + throw new AggregateException(exceptions); + } + case "IMGIX": + { + List exceptions = []; + + try + { + return new URLRewriterVariants::Imgix( + JsonSerializer.Deserialize(json, options) + ); + } + catch (JsonException e) + { + exceptions.Add(e); + } + + throw new AggregateException(exceptions); + } + case "AKAMAI": + { + List exceptions = []; + + try + { + return new URLRewriterVariants::Akamai( + JsonSerializer.Deserialize(json, options) + ); + } + catch (JsonException e) + { + exceptions.Add(e); + } + + throw new AggregateException(exceptions); + } + default: + { + throw new Exception(); + } + } + } + + public override void Write( + Utf8JsonWriter writer, + URLRewriter value, + JsonSerializerOptions options + ) + { + object variant = value switch + { + URLRewriterVariants::Cloudinary(var cloudinary) => cloudinary, + URLRewriterVariants::Imgix(var imgix) => imgix, + URLRewriterVariants::Akamai(var akamai) => akamai, + _ => throw new ArgumentOutOfRangeException(nameof(value)), + }; + JsonSerializer.Serialize(writer, variant, options); + } +} diff --git a/src/Imagekit/Models/Accounts/URLEndpoints/URLEndpointResponseProperties/URLRewriterProperties/Cloudinary.cs b/src/Imagekit/Models/Accounts/URLEndpoints/URLEndpointResponseProperties/URLRewriterProperties/Cloudinary.cs new file mode 100644 index 00000000..e2ebff1d --- /dev/null +++ b/src/Imagekit/Models/Accounts/URLEndpoints/URLEndpointResponseProperties/URLRewriterProperties/Cloudinary.cs @@ -0,0 +1,83 @@ +using System; +using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; +using System.Text.Json; +using System.Text.Json.Serialization; + +namespace Imagekit.Models.Accounts.URLEndpoints.URLEndpointResponseProperties.URLRewriterProperties; + +[JsonConverter(typeof(ModelConverter))] +public sealed record class Cloudinary : ModelBase, IFromRaw +{ + /// + /// Whether to preserve `/` in the rewritten URL. + /// + public required bool PreserveAssetDeliveryTypes + { + get + { + if (!this.Properties.TryGetValue("preserveAssetDeliveryTypes", out JsonElement element)) + throw new ArgumentOutOfRangeException( + "preserveAssetDeliveryTypes", + "Missing required argument" + ); + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions); + } + set + { + this.Properties["preserveAssetDeliveryTypes"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + public JsonElement Type + { + get + { + if (!this.Properties.TryGetValue("type", out JsonElement element)) + throw new ArgumentOutOfRangeException("type", "Missing required argument"); + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions); + } + set + { + this.Properties["type"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + public override void Validate() + { + _ = this.PreserveAssetDeliveryTypes; + } + + public Cloudinary() + { + this.Type = JsonSerializer.Deserialize("\"CLOUDINARY\""); + } + +#pragma warning disable CS8618 + [SetsRequiredMembers] + Cloudinary(Dictionary properties) + { + Properties = properties; + } +#pragma warning restore CS8618 + + public static Cloudinary FromRawUnchecked(Dictionary properties) + { + return new(properties); + } + + [SetsRequiredMembers] + public Cloudinary(bool preserveAssetDeliveryTypes) + : this() + { + this.PreserveAssetDeliveryTypes = preserveAssetDeliveryTypes; + } +} diff --git a/src/Imagekit/Models/Accounts/URLEndpoints/URLEndpointResponseProperties/URLRewriterVariants/All.cs b/src/Imagekit/Models/Accounts/URLEndpoints/URLEndpointResponseProperties/URLRewriterVariants/All.cs new file mode 100644 index 00000000..7e77ed0a --- /dev/null +++ b/src/Imagekit/Models/Accounts/URLEndpoints/URLEndpointResponseProperties/URLRewriterVariants/All.cs @@ -0,0 +1,39 @@ +using System.Text.Json; +using URLRewriterProperties = Imagekit.Models.Accounts.URLEndpoints.URLEndpointResponseProperties.URLRewriterProperties; + +namespace Imagekit.Models.Accounts.URLEndpoints.URLEndpointResponseProperties.URLRewriterVariants; + +public sealed record class Cloudinary(URLRewriterProperties::Cloudinary Value) + : URLRewriter, + IVariant +{ + public static Cloudinary From(URLRewriterProperties::Cloudinary value) + { + return new(value); + } + + public override void Validate() + { + this.Value.Validate(); + } +} + +public sealed record class Imgix(JsonElement Value) : URLRewriter, IVariant +{ + public static Imgix From(JsonElement value) + { + return new(value); + } + + public override void Validate() { } +} + +public sealed record class Akamai(JsonElement Value) : URLRewriter, IVariant +{ + public static Akamai From(JsonElement value) + { + return new(value); + } + + public override void Validate() { } +} diff --git a/src/Imagekit/Models/Accounts/URLEndpoints/URLEndpointUpdateParams.cs b/src/Imagekit/Models/Accounts/URLEndpoints/URLEndpointUpdateParams.cs new file mode 100644 index 00000000..8a2aac55 --- /dev/null +++ b/src/Imagekit/Models/Accounts/URLEndpoints/URLEndpointUpdateParams.cs @@ -0,0 +1,136 @@ +using System; +using System.Collections.Generic; +using System.Net.Http; +using System.Text; +using System.Text.Json; +using Imagekit.Models.Accounts.URLEndpoints.URLEndpointUpdateParamsProperties; + +namespace Imagekit.Models.Accounts.URLEndpoints; + +/// +/// **Note:** This API is currently in beta. Updates the URL‑endpoint identified +/// by `id` and returns the updated object. +/// +public sealed record class URLEndpointUpdateParams : ParamsBase +{ + public Dictionary BodyProperties { get; set; } = []; + + public required string ID; + + /// + /// Description of the URL endpoint. + /// + public required string Description + { + get + { + if (!this.BodyProperties.TryGetValue("description", out JsonElement element)) + throw new ArgumentOutOfRangeException("description", "Missing required argument"); + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions) + ?? throw new ArgumentNullException("description"); + } + set + { + this.BodyProperties["description"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + /// + /// Ordered list of origin IDs to try when the file isn’t in the Media Library; + /// ImageKit checks them in the sequence provided. Origin must be created before + /// it can be used in a URL endpoint. + /// + public List? Origins + { + get + { + if (!this.BodyProperties.TryGetValue("origins", out JsonElement element)) + return null; + + return JsonSerializer.Deserialize?>(element, ModelBase.SerializerOptions); + } + set + { + this.BodyProperties["origins"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + /// + /// Path segment appended to your base URL to form the endpoint (letters, digits, + /// and hyphens only — or empty for the default endpoint). + /// + public string? URLPrefix + { + get + { + if (!this.BodyProperties.TryGetValue("urlPrefix", out JsonElement element)) + return null; + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions); + } + set + { + this.BodyProperties["urlPrefix"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + /// + /// Configuration for third-party URL rewriting. + /// + public URLRewriter? URLRewriter + { + get + { + if (!this.BodyProperties.TryGetValue("urlRewriter", out JsonElement element)) + return null; + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions); + } + set + { + this.BodyProperties["urlRewriter"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + public override Uri Url(IImageKitClient client) + { + return new UriBuilder( + client.BaseUrl.ToString().TrimEnd('/') + + string.Format("/v1/accounts/url-endpoints/{0}", this.ID) + ) + { + Query = this.QueryString(client), + }.Uri; + } + + public StringContent BodyContent() + { + return new( + JsonSerializer.Serialize(this.BodyProperties), + Encoding.UTF8, + "application/json" + ); + } + + public void AddHeadersToRequest(HttpRequestMessage request, IImageKitClient client) + { + ParamsBase.AddDefaultHeaders(request, client); + foreach (var item in this.HeaderProperties) + { + ParamsBase.AddHeaderElementToRequest(request, item.Key, item.Value); + } + } +} diff --git a/src/Imagekit/Models/Accounts/URLEndpoints/URLEndpointUpdateParamsProperties/URLRewriter.cs b/src/Imagekit/Models/Accounts/URLEndpoints/URLEndpointUpdateParamsProperties/URLRewriter.cs new file mode 100644 index 00000000..a33a02b3 --- /dev/null +++ b/src/Imagekit/Models/Accounts/URLEndpoints/URLEndpointUpdateParamsProperties/URLRewriter.cs @@ -0,0 +1,176 @@ +using System; +using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; +using System.Text.Json; +using System.Text.Json.Serialization; +using Imagekit.Models.Accounts.URLEndpoints.URLEndpointUpdateParamsProperties.URLRewriterProperties; +using URLRewriterVariants = Imagekit.Models.Accounts.URLEndpoints.URLEndpointUpdateParamsProperties.URLRewriterVariants; + +namespace Imagekit.Models.Accounts.URLEndpoints.URLEndpointUpdateParamsProperties; + +/// +/// Configuration for third-party URL rewriting. +/// +[JsonConverter(typeof(URLRewriterConverter))] +public abstract record class URLRewriter +{ + internal URLRewriter() { } + + public static implicit operator URLRewriter(Cloudinary value) => + new URLRewriterVariants::Cloudinary(value); + + public bool TryPickCloudinary([NotNullWhen(true)] out Cloudinary? value) + { + value = (this as URLRewriterVariants::Cloudinary)?.Value; + return value != null; + } + + public bool TryPickImgix([NotNullWhen(true)] out JsonElement? value) + { + value = (this as URLRewriterVariants::Imgix)?.Value; + return value != null; + } + + public bool TryPickAkamai([NotNullWhen(true)] out JsonElement? value) + { + value = (this as URLRewriterVariants::Akamai)?.Value; + return value != null; + } + + public void Switch( + Action cloudinary, + Action imgix, + Action akamai + ) + { + switch (this) + { + case URLRewriterVariants::Cloudinary inner: + cloudinary(inner); + break; + case URLRewriterVariants::Imgix inner: + imgix(inner); + break; + case URLRewriterVariants::Akamai inner: + akamai(inner); + break; + default: + throw new InvalidOperationException(); + } + } + + public T Match( + Func cloudinary, + Func imgix, + Func akamai + ) + { + return this switch + { + URLRewriterVariants::Cloudinary inner => cloudinary(inner), + URLRewriterVariants::Imgix inner => imgix(inner), + URLRewriterVariants::Akamai inner => akamai(inner), + _ => throw new InvalidOperationException(), + }; + } + + public abstract void Validate(); +} + +sealed class URLRewriterConverter : JsonConverter +{ + public override URLRewriter? Read( + ref Utf8JsonReader reader, + Type typeToConvert, + JsonSerializerOptions options + ) + { + var json = JsonSerializer.Deserialize(ref reader, options); + string? type; + try + { + type = json.GetProperty("type").GetString(); + } + catch + { + type = null; + } + + switch (type) + { + case "CLOUDINARY": + { + List exceptions = []; + + try + { + var deserialized = JsonSerializer.Deserialize(json, options); + if (deserialized != null) + { + return new URLRewriterVariants::Cloudinary(deserialized); + } + } + catch (JsonException e) + { + exceptions.Add(e); + } + + throw new AggregateException(exceptions); + } + case "IMGIX": + { + List exceptions = []; + + try + { + return new URLRewriterVariants::Imgix( + JsonSerializer.Deserialize(json, options) + ); + } + catch (JsonException e) + { + exceptions.Add(e); + } + + throw new AggregateException(exceptions); + } + case "AKAMAI": + { + List exceptions = []; + + try + { + return new URLRewriterVariants::Akamai( + JsonSerializer.Deserialize(json, options) + ); + } + catch (JsonException e) + { + exceptions.Add(e); + } + + throw new AggregateException(exceptions); + } + default: + { + throw new Exception(); + } + } + } + + public override void Write( + Utf8JsonWriter writer, + URLRewriter value, + JsonSerializerOptions options + ) + { + object variant = value switch + { + URLRewriterVariants::Cloudinary(var cloudinary) => cloudinary, + URLRewriterVariants::Imgix(var imgix) => imgix, + URLRewriterVariants::Akamai(var akamai) => akamai, + _ => throw new ArgumentOutOfRangeException(nameof(value)), + }; + JsonSerializer.Serialize(writer, variant, options); + } +} diff --git a/src/Imagekit/Models/Accounts/URLEndpoints/URLEndpointUpdateParamsProperties/URLRewriterProperties/Cloudinary.cs b/src/Imagekit/Models/Accounts/URLEndpoints/URLEndpointUpdateParamsProperties/URLRewriterProperties/Cloudinary.cs new file mode 100644 index 00000000..169c202f --- /dev/null +++ b/src/Imagekit/Models/Accounts/URLEndpoints/URLEndpointUpdateParamsProperties/URLRewriterProperties/Cloudinary.cs @@ -0,0 +1,73 @@ +using System; +using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; +using System.Text.Json; +using System.Text.Json.Serialization; + +namespace Imagekit.Models.Accounts.URLEndpoints.URLEndpointUpdateParamsProperties.URLRewriterProperties; + +[JsonConverter(typeof(ModelConverter))] +public sealed record class Cloudinary : ModelBase, IFromRaw +{ + public JsonElement Type + { + get + { + if (!this.Properties.TryGetValue("type", out JsonElement element)) + throw new ArgumentOutOfRangeException("type", "Missing required argument"); + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions); + } + set + { + this.Properties["type"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + /// + /// Whether to preserve `/` in the rewritten URL. + /// + public bool? PreserveAssetDeliveryTypes + { + get + { + if (!this.Properties.TryGetValue("preserveAssetDeliveryTypes", out JsonElement element)) + return null; + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions); + } + set + { + this.Properties["preserveAssetDeliveryTypes"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + public override void Validate() + { + _ = this.PreserveAssetDeliveryTypes; + } + + public Cloudinary() + { + this.Type = JsonSerializer.Deserialize("\"CLOUDINARY\""); + } + +#pragma warning disable CS8618 + [SetsRequiredMembers] + Cloudinary(Dictionary properties) + { + Properties = properties; + } +#pragma warning restore CS8618 + + public static Cloudinary FromRawUnchecked(Dictionary properties) + { + return new(properties); + } +} diff --git a/src/Imagekit/Models/Accounts/URLEndpoints/URLEndpointUpdateParamsProperties/URLRewriterVariants/All.cs b/src/Imagekit/Models/Accounts/URLEndpoints/URLEndpointUpdateParamsProperties/URLRewriterVariants/All.cs new file mode 100644 index 00000000..bab987b0 --- /dev/null +++ b/src/Imagekit/Models/Accounts/URLEndpoints/URLEndpointUpdateParamsProperties/URLRewriterVariants/All.cs @@ -0,0 +1,39 @@ +using System.Text.Json; +using URLRewriterProperties = Imagekit.Models.Accounts.URLEndpoints.URLEndpointUpdateParamsProperties.URLRewriterProperties; + +namespace Imagekit.Models.Accounts.URLEndpoints.URLEndpointUpdateParamsProperties.URLRewriterVariants; + +public sealed record class Cloudinary(URLRewriterProperties::Cloudinary Value) + : URLRewriter, + IVariant +{ + public static Cloudinary From(URLRewriterProperties::Cloudinary value) + { + return new(value); + } + + public override void Validate() + { + this.Value.Validate(); + } +} + +public sealed record class Imgix(JsonElement Value) : URLRewriter, IVariant +{ + public static Imgix From(JsonElement value) + { + return new(value); + } + + public override void Validate() { } +} + +public sealed record class Akamai(JsonElement Value) : URLRewriter, IVariant +{ + public static Akamai From(JsonElement value) + { + return new(value); + } + + public override void Validate() { } +} diff --git a/src/Imagekit/Models/Accounts/Usage/UsageGetParams.cs b/src/Imagekit/Models/Accounts/Usage/UsageGetParams.cs new file mode 100644 index 00000000..fe843155 --- /dev/null +++ b/src/Imagekit/Models/Accounts/Usage/UsageGetParams.cs @@ -0,0 +1,75 @@ +using System; +using System.Net.Http; +using System.Text.Json; + +namespace Imagekit.Models.Accounts.Usage; + +/// +/// Get the account usage information between two dates. Note that the API response +/// includes data from the start date while excluding data from the end date. In +/// other words, the data covers the period starting from the specified start date +/// up to, but not including, the end date. +/// +public sealed record class UsageGetParams : ParamsBase +{ + /// + /// Specify a `endDate` in `YYYY-MM-DD` format. It should be after the `startDate`. + /// The difference between `startDate` and `endDate` should be less than 90 days. + /// + public required DateOnly EndDate + { + get + { + if (!this.QueryProperties.TryGetValue("endDate", out JsonElement element)) + throw new ArgumentOutOfRangeException("endDate", "Missing required argument"); + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions); + } + set + { + this.QueryProperties["endDate"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + /// + /// Specify a `startDate` in `YYYY-MM-DD` format. It should be before the `endDate`. + /// The difference between `startDate` and `endDate` should be less than 90 days. + /// + public required DateOnly StartDate + { + get + { + if (!this.QueryProperties.TryGetValue("startDate", out JsonElement element)) + throw new ArgumentOutOfRangeException("startDate", "Missing required argument"); + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions); + } + set + { + this.QueryProperties["startDate"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + public override Uri Url(IImageKitClient client) + { + return new UriBuilder(client.BaseUrl.ToString().TrimEnd('/') + "/v1/accounts/usage") + { + Query = this.QueryString(client), + }.Uri; + } + + public void AddHeadersToRequest(HttpRequestMessage request, IImageKitClient client) + { + ParamsBase.AddDefaultHeaders(request, client); + foreach (var item in this.HeaderProperties) + { + ParamsBase.AddHeaderElementToRequest(request, item.Key, item.Value); + } + } +} diff --git a/src/Imagekit/Models/Accounts/Usage/UsageGetResponse.cs b/src/Imagekit/Models/Accounts/Usage/UsageGetResponse.cs new file mode 100644 index 00000000..d540bab5 --- /dev/null +++ b/src/Imagekit/Models/Accounts/Usage/UsageGetResponse.cs @@ -0,0 +1,139 @@ +using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; +using System.Text.Json; +using System.Text.Json.Serialization; + +namespace Imagekit.Models.Accounts.Usage; + +[JsonConverter(typeof(ModelConverter))] +public sealed record class UsageGetResponse : ModelBase, IFromRaw +{ + /// + /// Amount of bandwidth used in bytes. + /// + public long? BandwidthBytes + { + get + { + if (!this.Properties.TryGetValue("bandwidthBytes", out JsonElement element)) + return null; + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions); + } + set + { + this.Properties["bandwidthBytes"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + /// + /// Number of extension units used. + /// + public long? ExtensionUnitsCount + { + get + { + if (!this.Properties.TryGetValue("extensionUnitsCount", out JsonElement element)) + return null; + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions); + } + set + { + this.Properties["extensionUnitsCount"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + /// + /// Storage used by media library in bytes. + /// + public long? MediaLibraryStorageBytes + { + get + { + if (!this.Properties.TryGetValue("mediaLibraryStorageBytes", out JsonElement element)) + return null; + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions); + } + set + { + this.Properties["mediaLibraryStorageBytes"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + /// + /// Storage used by the original cache in bytes. + /// + public long? OriginalCacheStorageBytes + { + get + { + if (!this.Properties.TryGetValue("originalCacheStorageBytes", out JsonElement element)) + return null; + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions); + } + set + { + this.Properties["originalCacheStorageBytes"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + /// + /// Number of video processing units used. + /// + public long? VideoProcessingUnitsCount + { + get + { + if (!this.Properties.TryGetValue("videoProcessingUnitsCount", out JsonElement element)) + return null; + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions); + } + set + { + this.Properties["videoProcessingUnitsCount"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + public override void Validate() + { + _ = this.BandwidthBytes; + _ = this.ExtensionUnitsCount; + _ = this.MediaLibraryStorageBytes; + _ = this.OriginalCacheStorageBytes; + _ = this.VideoProcessingUnitsCount; + } + + public UsageGetResponse() { } + +#pragma warning disable CS8618 + [SetsRequiredMembers] + UsageGetResponse(Dictionary properties) + { + Properties = properties; + } +#pragma warning restore CS8618 + + public static UsageGetResponse FromRawUnchecked(Dictionary properties) + { + return new(properties); + } +} diff --git a/src/Imagekit/Models/Assets/AssetListParams.cs b/src/Imagekit/Models/Assets/AssetListParams.cs new file mode 100644 index 00000000..0e5fb2b3 --- /dev/null +++ b/src/Imagekit/Models/Assets/AssetListParams.cs @@ -0,0 +1,210 @@ +using System; +using System.Net.Http; +using System.Text.Json; +using AssetListParamsProperties = Imagekit.Models.Assets.AssetListParamsProperties; + +namespace Imagekit.Models.Assets; + +/// +/// This API can list all the uploaded files and folders in your ImageKit.io media +/// library. In addition, you can fine-tune your query by specifying various filters +/// by generating a query string in a Lucene-like syntax and provide this generated +/// string as the value of the `searchQuery`. +/// +public sealed record class AssetListParams : ParamsBase +{ + /// + /// Filter results by file type. + /// + /// - `all` — include all file types - `image` — include only image files + /// - `non-image` — include only non-image files (e.g., JS, CSS, video) + /// + public ApiEnum? FileType + { + get + { + if (!this.QueryProperties.TryGetValue("fileType", out JsonElement element)) + return null; + + return JsonSerializer.Deserialize?>(element, ModelBase.SerializerOptions); + } + set + { + this.QueryProperties["fileType"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + /// + /// The maximum number of results to return in response. + /// + public long? Limit + { + get + { + if (!this.QueryProperties.TryGetValue("limit", out JsonElement element)) + return null; + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions); + } + set + { + this.QueryProperties["limit"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + /// + /// Folder path if you want to limit the search within a specific folder. For + /// example, `/sales-banner/` will only search in folder sales-banner. + /// + /// Note : If your use case involves searching within a folder as well as its + /// subfolders, you can use `path` parameter in `searchQuery` with appropriate + /// operator. Checkout [Supported parameters](/docs/api-reference/digital-asset-management-dam/list-and-search-assets#supported-parameters) + /// for more information. + /// + public string? Path + { + get + { + if (!this.QueryProperties.TryGetValue("path", out JsonElement element)) + return null; + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions); + } + set + { + this.QueryProperties["path"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + /// + /// Query string in a Lucene-like query language e.g. `createdAt > "7d"`. + /// + /// Note : When the searchQuery parameter is present, the following query parameters + /// will have no effect on the result: + /// + /// 1. `tags` 2. `type` 3. `name` + /// + /// [Learn more](/docs/api-reference/digital-asset-management-dam/list-and-search-assets#advanced-search-queries) + /// from examples. + /// + public string? SearchQuery + { + get + { + if (!this.QueryProperties.TryGetValue("searchQuery", out JsonElement element)) + return null; + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions); + } + set + { + this.QueryProperties["searchQuery"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + /// + /// The number of results to skip before returning results. + /// + public long? Skip + { + get + { + if (!this.QueryProperties.TryGetValue("skip", out JsonElement element)) + return null; + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions); + } + set + { + this.QueryProperties["skip"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + /// + /// Sort the results by one of the supported fields in ascending or descending + /// order. + /// + public ApiEnum? Sort + { + get + { + if (!this.QueryProperties.TryGetValue("sort", out JsonElement element)) + return null; + + return JsonSerializer.Deserialize?>( + element, + ModelBase.SerializerOptions + ); + } + set + { + this.QueryProperties["sort"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + /// + /// Filter results by asset type. + /// + /// - `file` — returns only files - `file-version` — returns specific file versions + /// - `folder` — returns only folders - `all` — returns both files and folders + /// (excludes `file-version`) + /// + public ApiEnum? Type + { + get + { + if (!this.QueryProperties.TryGetValue("type", out JsonElement element)) + return null; + + return JsonSerializer.Deserialize?>( + element, + ModelBase.SerializerOptions + ); + } + set + { + this.QueryProperties["type"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + public override Uri Url(IImageKitClient client) + { + return new UriBuilder(client.BaseUrl.ToString().TrimEnd('/') + "/v1/files") + { + Query = this.QueryString(client), + }.Uri; + } + + public void AddHeadersToRequest(HttpRequestMessage request, IImageKitClient client) + { + ParamsBase.AddDefaultHeaders(request, client); + foreach (var item in this.HeaderProperties) + { + ParamsBase.AddHeaderElementToRequest(request, item.Key, item.Value); + } + } +} diff --git a/src/Imagekit/Models/Assets/AssetListParamsProperties/FileType.cs b/src/Imagekit/Models/Assets/AssetListParamsProperties/FileType.cs new file mode 100644 index 00000000..620809fb --- /dev/null +++ b/src/Imagekit/Models/Assets/AssetListParamsProperties/FileType.cs @@ -0,0 +1,52 @@ +using System.Text.Json; +using System.Text.Json.Serialization; +using System = System; + +namespace Imagekit.Models.Assets.AssetListParamsProperties; + +/// +/// Filter results by file type. +/// +/// - `all` — include all file types - `image` — include only image files - `non-image` +/// — include only non-image files (e.g., JS, CSS, video) +/// +[JsonConverter(typeof(FileTypeConverter))] +public enum FileType +{ + All, + Image, + NonImage, +} + +sealed class FileTypeConverter : JsonConverter +{ + public override FileType Read( + ref Utf8JsonReader reader, + System::Type typeToConvert, + JsonSerializerOptions options + ) + { + return JsonSerializer.Deserialize(ref reader, options) switch + { + "all" => FileType.All, + "image" => FileType.Image, + "non-image" => FileType.NonImage, + _ => (FileType)(-1), + }; + } + + public override void Write(Utf8JsonWriter writer, FileType value, JsonSerializerOptions options) + { + JsonSerializer.Serialize( + writer, + value switch + { + FileType.All => "all", + FileType.Image => "image", + FileType.NonImage => "non-image", + _ => throw new System::ArgumentOutOfRangeException(nameof(value)), + }, + options + ); + } +} diff --git a/src/Imagekit/Models/Assets/AssetListParamsProperties/Sort.cs b/src/Imagekit/Models/Assets/AssetListParamsProperties/Sort.cs new file mode 100644 index 00000000..a932d642 --- /dev/null +++ b/src/Imagekit/Models/Assets/AssetListParamsProperties/Sort.cs @@ -0,0 +1,82 @@ +using System.Text.Json; +using System.Text.Json.Serialization; +using System = System; + +namespace Imagekit.Models.Assets.AssetListParamsProperties; + +/// +/// Sort the results by one of the supported fields in ascending or descending order. +/// +[JsonConverter(typeof(SortConverter))] +public enum Sort +{ + AscName, + DescName, + AscCreated, + DescCreated, + AscUpdated, + DescUpdated, + AscHeight, + DescHeight, + AscWidth, + DescWidth, + AscSize, + DescSize, + AscRelevance, + DescRelevance, +} + +sealed class SortConverter : JsonConverter +{ + public override Sort Read( + ref Utf8JsonReader reader, + System::Type typeToConvert, + JsonSerializerOptions options + ) + { + return JsonSerializer.Deserialize(ref reader, options) switch + { + "ASC_NAME" => Sort.AscName, + "DESC_NAME" => Sort.DescName, + "ASC_CREATED" => Sort.AscCreated, + "DESC_CREATED" => Sort.DescCreated, + "ASC_UPDATED" => Sort.AscUpdated, + "DESC_UPDATED" => Sort.DescUpdated, + "ASC_HEIGHT" => Sort.AscHeight, + "DESC_HEIGHT" => Sort.DescHeight, + "ASC_WIDTH" => Sort.AscWidth, + "DESC_WIDTH" => Sort.DescWidth, + "ASC_SIZE" => Sort.AscSize, + "DESC_SIZE" => Sort.DescSize, + "ASC_RELEVANCE" => Sort.AscRelevance, + "DESC_RELEVANCE" => Sort.DescRelevance, + _ => (Sort)(-1), + }; + } + + public override void Write(Utf8JsonWriter writer, Sort value, JsonSerializerOptions options) + { + JsonSerializer.Serialize( + writer, + value switch + { + Sort.AscName => "ASC_NAME", + Sort.DescName => "DESC_NAME", + Sort.AscCreated => "ASC_CREATED", + Sort.DescCreated => "DESC_CREATED", + Sort.AscUpdated => "ASC_UPDATED", + Sort.DescUpdated => "DESC_UPDATED", + Sort.AscHeight => "ASC_HEIGHT", + Sort.DescHeight => "DESC_HEIGHT", + Sort.AscWidth => "ASC_WIDTH", + Sort.DescWidth => "DESC_WIDTH", + Sort.AscSize => "ASC_SIZE", + Sort.DescSize => "DESC_SIZE", + Sort.AscRelevance => "ASC_RELEVANCE", + Sort.DescRelevance => "DESC_RELEVANCE", + _ => throw new System::ArgumentOutOfRangeException(nameof(value)), + }, + options + ); + } +} diff --git a/src/Imagekit/Models/Assets/AssetListParamsProperties/Type.cs b/src/Imagekit/Models/Assets/AssetListParamsProperties/Type.cs new file mode 100644 index 00000000..e3141966 --- /dev/null +++ b/src/Imagekit/Models/Assets/AssetListParamsProperties/Type.cs @@ -0,0 +1,56 @@ +using System.Text.Json; +using System.Text.Json.Serialization; +using System = System; + +namespace Imagekit.Models.Assets.AssetListParamsProperties; + +/// +/// Filter results by asset type. +/// +/// - `file` — returns only files - `file-version` — returns specific file versions +/// - `folder` — returns only folders - `all` — returns both files and folders +/// (excludes `file-version`) +/// +[JsonConverter(typeof(TypeConverter))] +public enum Type +{ + File, + FileVersion, + Folder, + All, +} + +sealed class TypeConverter : JsonConverter +{ + public override Type Read( + ref Utf8JsonReader reader, + System::Type typeToConvert, + JsonSerializerOptions options + ) + { + return JsonSerializer.Deserialize(ref reader, options) switch + { + "file" => AssetListParamsProperties.Type.File, + "file-version" => AssetListParamsProperties.Type.FileVersion, + "folder" => AssetListParamsProperties.Type.Folder, + "all" => AssetListParamsProperties.Type.All, + _ => (Type)(-1), + }; + } + + public override void Write(Utf8JsonWriter writer, Type value, JsonSerializerOptions options) + { + JsonSerializer.Serialize( + writer, + value switch + { + AssetListParamsProperties.Type.File => "file", + AssetListParamsProperties.Type.FileVersion => "file-version", + AssetListParamsProperties.Type.Folder => "folder", + AssetListParamsProperties.Type.All => "all", + _ => throw new System::ArgumentOutOfRangeException(nameof(value)), + }, + options + ); + } +} diff --git a/src/Imagekit/Models/Assets/AssetListResponse.cs b/src/Imagekit/Models/Assets/AssetListResponse.cs new file mode 100644 index 00000000..4fb2cf1b --- /dev/null +++ b/src/Imagekit/Models/Assets/AssetListResponse.cs @@ -0,0 +1,147 @@ +using System; +using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; +using System.Text.Json; +using System.Text.Json.Serialization; +using Imagekit.Models.Files; +using AssetListResponseVariants = Imagekit.Models.Assets.AssetListResponseVariants; + +namespace Imagekit.Models.Assets; + +/// +/// Object containing details of a file or file version. +/// +[JsonConverter(typeof(AssetListResponseConverter))] +public abstract record class AssetListResponse +{ + internal AssetListResponse() { } + + public static implicit operator AssetListResponse(File value) => + new AssetListResponseVariants::File(value); + + public static implicit operator AssetListResponse(Folder value) => + new AssetListResponseVariants::Folder(value); + + public bool TryPickFile([NotNullWhen(true)] out File? value) + { + value = (this as AssetListResponseVariants::File)?.Value; + return value != null; + } + + public bool TryPickFolder([NotNullWhen(true)] out Folder? value) + { + value = (this as AssetListResponseVariants::Folder)?.Value; + return value != null; + } + + public void Switch( + Action file, + Action folder + ) + { + switch (this) + { + case AssetListResponseVariants::File inner: + file(inner); + break; + case AssetListResponseVariants::Folder inner: + folder(inner); + break; + default: + throw new InvalidOperationException(); + } + } + + public T Match( + Func file, + Func folder + ) + { + return this switch + { + AssetListResponseVariants::File inner => file(inner), + AssetListResponseVariants::Folder inner => folder(inner), + _ => throw new InvalidOperationException(), + }; + } + + public abstract void Validate(); +} + +sealed class AssetListResponseConverter : JsonConverter +{ + public override AssetListResponse? Read( + ref Utf8JsonReader reader, + Type typeToConvert, + JsonSerializerOptions options + ) + { + var json = JsonSerializer.Deserialize(ref reader, options); + string? type; + try + { + type = json.GetProperty("type").GetString(); + } + catch + { + type = null; + } + + switch (type) + { + case "folder": + { + List exceptions = []; + + try + { + var deserialized = JsonSerializer.Deserialize(json, options); + if (deserialized != null) + { + return new AssetListResponseVariants::Folder(deserialized); + } + } + catch (JsonException e) + { + exceptions.Add(e); + } + + throw new AggregateException(exceptions); + } + default: + { + List exceptions = []; + + try + { + var deserialized = JsonSerializer.Deserialize(json, options); + if (deserialized != null) + { + return new AssetListResponseVariants::File(deserialized); + } + } + catch (JsonException e) + { + exceptions.Add(e); + } + + throw new AggregateException(exceptions); + } + } + } + + public override void Write( + Utf8JsonWriter writer, + AssetListResponse value, + JsonSerializerOptions options + ) + { + object variant = value switch + { + AssetListResponseVariants::File(var file) => file, + AssetListResponseVariants::Folder(var folder) => folder, + _ => throw new ArgumentOutOfRangeException(nameof(value)), + }; + JsonSerializer.Serialize(writer, variant, options); + } +} diff --git a/src/Imagekit/Models/Assets/AssetListResponseVariants/All.cs b/src/Imagekit/Models/Assets/AssetListResponseVariants/All.cs new file mode 100644 index 00000000..5bd62993 --- /dev/null +++ b/src/Imagekit/Models/Assets/AssetListResponseVariants/All.cs @@ -0,0 +1,34 @@ +using Files = Imagekit.Models.Files; + +namespace Imagekit.Models.Assets.AssetListResponseVariants; + +/// +/// Object containing details of a file or file version. +/// +public sealed record class File(Files::File Value) : AssetListResponse, IVariant +{ + public static File From(Files::File value) + { + return new(value); + } + + public override void Validate() + { + this.Value.Validate(); + } +} + +public sealed record class Folder(Files::Folder Value) + : AssetListResponse, + IVariant +{ + public static Folder From(Files::Folder value) + { + return new(value); + } + + public override void Validate() + { + this.Value.Validate(); + } +} diff --git a/src/Imagekit/Models/BaseOverlay.cs b/src/Imagekit/Models/BaseOverlay.cs new file mode 100644 index 00000000..b1a9d463 --- /dev/null +++ b/src/Imagekit/Models/BaseOverlay.cs @@ -0,0 +1,70 @@ +using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; +using System.Text.Json; +using System.Text.Json.Serialization; + +namespace Imagekit.Models; + +[JsonConverter(typeof(ModelConverter))] +public sealed record class BaseOverlay : ModelBase, IFromRaw +{ + public OverlayPosition? Position + { + get + { + if (!this.Properties.TryGetValue("position", out JsonElement element)) + return null; + + return JsonSerializer.Deserialize( + element, + ModelBase.SerializerOptions + ); + } + set + { + this.Properties["position"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + public OverlayTiming? Timing + { + get + { + if (!this.Properties.TryGetValue("timing", out JsonElement element)) + return null; + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions); + } + set + { + this.Properties["timing"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + public override void Validate() + { + this.Position?.Validate(); + this.Timing?.Validate(); + } + + public BaseOverlay() { } + +#pragma warning disable CS8618 + [SetsRequiredMembers] + BaseOverlay(Dictionary properties) + { + Properties = properties; + } +#pragma warning restore CS8618 + + public static BaseOverlay FromRawUnchecked(Dictionary properties) + { + return new(properties); + } +} diff --git a/src/Imagekit/Models/Beta/V2/Files/FileUploadParams.cs b/src/Imagekit/Models/Beta/V2/Files/FileUploadParams.cs new file mode 100644 index 00000000..69983989 --- /dev/null +++ b/src/Imagekit/Models/Beta/V2/Files/FileUploadParams.cs @@ -0,0 +1,561 @@ +using System; +using System.Collections.Generic; +using System.Net.Http; +using System.Text; +using System.Text.Json; +using FileUploadParamsProperties = Imagekit.Models.Beta.V2.Files.FileUploadParamsProperties; + +namespace Imagekit.Models.Beta.V2.Files; + +/// +/// The V2 API enhances security by verifying the entire payload using JWT. This +/// API is in beta. +/// +/// ImageKit.io allows you to upload files directly from both the server and client +/// sides. For server-side uploads, private API key authentication is used. For client-side +/// uploads, generate a one-time `token` from your secure backend using private API. +/// [Learn more](/docs/api-reference/upload-file/upload-file-v2#how-to-implement-secure-client-side-file-upload) +/// about how to implement secure client-side file upload. +/// +/// **File size limit** \ On the free plan, the maximum upload file sizes are 20MB +/// for images, audio, and raw files, and 100MB for videos. On the paid plan, these +/// limits increase to 40MB for images, audio, and raw files, and 2GB for videos. +/// These limits can be further increased with higher-tier plans. +/// +/// **Version limit** \ A file can have a maximum of 100 versions. +/// +/// **Demo applications** +/// +/// - A full-fledged [upload widget using Uppy](https://github.com/imagekit-samples/uppy-uploader), +/// supporting file selections from local storage, URL, Dropbox, Google Drive, Instagram, +/// and more. - [Quick start guides](/docs/quick-start-guides) for various frameworks +/// and technologies. +/// +public sealed record class FileUploadParams : ParamsBase +{ + public Dictionary BodyProperties { get; set; } = []; + + /// + /// The API accepts any of the following: + /// + /// - **Binary data** – send the raw bytes as `multipart/form-data`. - **HTTP + /// / HTTPS URL** – a publicly reachable URL that ImageKit’s servers can fetch. + /// - **Base64 string** – the file encoded as a Base64 data URI or plain Base64. + /// + /// When supplying a URL, the server must receive the response headers within + /// 8 seconds; otherwise the request fails with 400 Bad Request. + /// + public required string File + { + get + { + if (!this.BodyProperties.TryGetValue("file", out JsonElement element)) + throw new ArgumentOutOfRangeException("file", "Missing required argument"); + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions) + ?? throw new ArgumentNullException("file"); + } + set + { + this.BodyProperties["file"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + /// + /// The name with which the file has to be uploaded. + /// + public required string FileName + { + get + { + if (!this.BodyProperties.TryGetValue("fileName", out JsonElement element)) + throw new ArgumentOutOfRangeException("fileName", "Missing required argument"); + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions) + ?? throw new ArgumentNullException("fileName"); + } + set + { + this.BodyProperties["fileName"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + /// + /// This is the client-generated JSON Web Token (JWT). The ImageKit.io server + /// uses it to authenticate and check that the upload request parameters have + /// not been tampered with after the token has been generated. Learn how to create + /// the token on the page below. This field is only required for authentication + /// when uploading a file from the client side. + /// + /// **Note**: Sending a JWT that has been used in the past will result in a validation + /// error. Even if your previous request resulted in an error, you should always + /// send a new token. + /// + /// **⚠️Warning**: JWT must be generated on the server-side because it is generated + /// using your account's private API key. This field is required for authentication + /// when uploading a file from the client-side. + /// + public string? Token + { + get + { + if (!this.BodyProperties.TryGetValue("token", out JsonElement element)) + return null; + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions); + } + set + { + this.BodyProperties["token"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + /// + /// Server-side checks to run on the asset. Read more about [Upload API checks](/docs/api-reference/upload-file/upload-file-v2#upload-api-checks). + /// + public string? Checks + { + get + { + if (!this.BodyProperties.TryGetValue("checks", out JsonElement element)) + return null; + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions); + } + set + { + this.BodyProperties["checks"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + /// + /// Define an important area in the image. This is only relevant for image type files. + /// + /// - To be passed as a string with the x and y coordinates of the top-left + /// corner, and width and height of the area of interest in the format `x,y,width,height`. + /// For example - `10,10,100,100` - Can be used with fo-customtransformation. + /// - If this field is not specified and the file is overwritten, then customCoordinates + /// will be removed. + /// + public string? CustomCoordinates + { + get + { + if (!this.BodyProperties.TryGetValue("customCoordinates", out JsonElement element)) + return null; + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions); + } + set + { + this.BodyProperties["customCoordinates"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + /// + /// JSON key-value pairs to associate with the asset. Create the custom metadata + /// fields before setting these values. + /// + public Dictionary? CustomMetadata + { + get + { + if (!this.BodyProperties.TryGetValue("customMetadata", out JsonElement element)) + return null; + + return JsonSerializer.Deserialize?>( + element, + ModelBase.SerializerOptions + ); + } + set + { + this.BodyProperties["customMetadata"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + /// + /// Optional text to describe the contents of the file. + /// + public string? Description + { + get + { + if (!this.BodyProperties.TryGetValue("description", out JsonElement element)) + return null; + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions); + } + set + { + this.BodyProperties["description"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + /// + /// Array of extensions to be applied to the image. Each extension can be configured + /// with specific parameters based on the extension type. + /// + public List? Extensions + { + get + { + if (!this.BodyProperties.TryGetValue("extensions", out JsonElement element)) + return null; + + return JsonSerializer.Deserialize?>( + element, + ModelBase.SerializerOptions + ); + } + set + { + this.BodyProperties["extensions"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + /// + /// The folder path in which the image has to be uploaded. If the folder(s) didn't + /// exist before, a new folder(s) is created. Using multiple `/` creates a nested + /// folder. + /// + public string? Folder + { + get + { + if (!this.BodyProperties.TryGetValue("folder", out JsonElement element)) + return null; + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions); + } + set + { + this.BodyProperties["folder"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + /// + /// Whether to mark the file as private or not. + /// + /// If `true`, the file is marked as private and is accessible only using named + /// transformation or signed URL. + /// + public bool? IsPrivateFile + { + get + { + if (!this.BodyProperties.TryGetValue("isPrivateFile", out JsonElement element)) + return null; + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions); + } + set + { + this.BodyProperties["isPrivateFile"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + /// + /// Whether to upload file as published or not. + /// + /// If `false`, the file is marked as unpublished, which restricts access to the + /// file only via the media library. Files in draft or unpublished state can only + /// be publicly accessed after being published. + /// + /// The option to upload in draft state is only available in custom enterprise + /// pricing plans. + /// + public bool? IsPublished + { + get + { + if (!this.BodyProperties.TryGetValue("isPublished", out JsonElement element)) + return null; + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions); + } + set + { + this.BodyProperties["isPublished"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + /// + /// If set to `true` and a file already exists at the exact location, its AITags + /// will be removed. Set `overwriteAITags` to `false` to preserve AITags. + /// + public bool? OverwriteAITags + { + get + { + if (!this.BodyProperties.TryGetValue("overwriteAITags", out JsonElement element)) + return null; + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions); + } + set + { + this.BodyProperties["overwriteAITags"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + /// + /// If the request does not have `customMetadata`, and a file already exists at + /// the exact location, existing customMetadata will be removed. + /// + public bool? OverwriteCustomMetadata + { + get + { + if ( + !this.BodyProperties.TryGetValue("overwriteCustomMetadata", out JsonElement element) + ) + return null; + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions); + } + set + { + this.BodyProperties["overwriteCustomMetadata"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + /// + /// If `false` and `useUniqueFileName` is also `false`, and a file already exists + /// at the exact location, upload API will return an error immediately. + /// + public bool? OverwriteFile + { + get + { + if (!this.BodyProperties.TryGetValue("overwriteFile", out JsonElement element)) + return null; + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions); + } + set + { + this.BodyProperties["overwriteFile"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + /// + /// If the request does not have `tags`, and a file already exists at the exact + /// location, existing tags will be removed. + /// + public bool? OverwriteTags + { + get + { + if (!this.BodyProperties.TryGetValue("overwriteTags", out JsonElement element)) + return null; + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions); + } + set + { + this.BodyProperties["overwriteTags"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + /// + /// Array of response field keys to include in the API response body. + /// + public List>? ResponseFields + { + get + { + if (!this.BodyProperties.TryGetValue("responseFields", out JsonElement element)) + return null; + + return JsonSerializer.Deserialize + >?>(element, ModelBase.SerializerOptions); + } + set + { + this.BodyProperties["responseFields"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + /// + /// Set the tags while uploading the file. Provide an array of tag strings (e.g. + /// `["tag1", "tag2", "tag3"]`). The combined length of all tag characters must + /// not exceed 500, and the `%` character is not allowed. If this field is not + /// specified and the file is overwritten, the existing tags will be removed. + /// + public List? Tags + { + get + { + if (!this.BodyProperties.TryGetValue("tags", out JsonElement element)) + return null; + + return JsonSerializer.Deserialize?>(element, ModelBase.SerializerOptions); + } + set + { + this.BodyProperties["tags"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + /// + /// Configure pre-processing (`pre`) and post-processing (`post`) transformations. + /// + /// - `pre` — applied before the file is uploaded to the Media Library. Useful + /// for reducing file size or applying basic optimizations upfront (e.g., resize, compress). + /// + /// - `post` — applied immediately after upload. Ideal for generating transformed + /// versions (like video encodes or thumbnails) in advance, so they're ready for + /// delivery without delay. + /// + /// You can mix and match any combination of post-processing types. + /// + public FileUploadParamsProperties::Transformation? Transformation + { + get + { + if (!this.BodyProperties.TryGetValue("transformation", out JsonElement element)) + return null; + + return JsonSerializer.Deserialize( + element, + ModelBase.SerializerOptions + ); + } + set + { + this.BodyProperties["transformation"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + /// + /// Whether to use a unique filename for this file or not. + /// + /// If `true`, ImageKit.io will add a unique suffix to the filename parameter + /// to get a unique filename. + /// + /// If `false`, then the image is uploaded with the provided filename parameter, + /// and any existing file with the same name is replaced. + /// + public bool? UseUniqueFileName + { + get + { + if (!this.BodyProperties.TryGetValue("useUniqueFileName", out JsonElement element)) + return null; + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions); + } + set + { + this.BodyProperties["useUniqueFileName"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + /// + /// The final status of extensions after they have completed execution will be + /// delivered to this endpoint as a POST request. [Learn more](/docs/api-reference/digital-asset-management-dam/managing-assets/update-file-details#webhook-payload-structure) + /// about the webhook payload structure. + /// + public string? WebhookURL + { + get + { + if (!this.BodyProperties.TryGetValue("webhookUrl", out JsonElement element)) + return null; + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions); + } + set + { + this.BodyProperties["webhookUrl"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + public override Uri Url(IImageKitClient client) + { + return new UriBuilder(client.BaseUrl.ToString().TrimEnd('/') + "/api/v2/files/upload") + { + Query = this.QueryString(client), + }.Uri; + } + + public StringContent BodyContent() + { + return new( + JsonSerializer.Serialize(this.BodyProperties), + Encoding.UTF8, + "application/json" + ); + } + + public void AddHeadersToRequest(HttpRequestMessage request, IImageKitClient client) + { + ParamsBase.AddDefaultHeaders(request, client); + foreach (var item in this.HeaderProperties) + { + ParamsBase.AddHeaderElementToRequest(request, item.Key, item.Value); + } + } +} diff --git a/src/Imagekit/Models/Beta/V2/Files/FileUploadParamsProperties/Extension.cs b/src/Imagekit/Models/Beta/V2/Files/FileUploadParamsProperties/Extension.cs new file mode 100644 index 00000000..643fb77a --- /dev/null +++ b/src/Imagekit/Models/Beta/V2/Files/FileUploadParamsProperties/Extension.cs @@ -0,0 +1,177 @@ +using System; +using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; +using System.Text.Json; +using System.Text.Json.Serialization; +using Imagekit.Models.Beta.V2.Files.FileUploadParamsProperties.ExtensionProperties; +using ExtensionVariants = Imagekit.Models.Beta.V2.Files.FileUploadParamsProperties.ExtensionVariants; + +namespace Imagekit.Models.Beta.V2.Files.FileUploadParamsProperties; + +[JsonConverter(typeof(ExtensionConverter))] +public abstract record class Extension +{ + internal Extension() { } + + public static implicit operator Extension(RemoveBg value) => + new ExtensionVariants::RemoveBg(value); + + public static implicit operator Extension(AutoTaggingExtension value) => + new ExtensionVariants::AutoTaggingExtension(value); + + public bool TryPickRemoveBg([NotNullWhen(true)] out RemoveBg? value) + { + value = (this as ExtensionVariants::RemoveBg)?.Value; + return value != null; + } + + public bool TryPickAutoTagging([NotNullWhen(true)] out AutoTaggingExtension? value) + { + value = (this as ExtensionVariants::AutoTaggingExtension)?.Value; + return value != null; + } + + public bool TryPickAIAutoDescription([NotNullWhen(true)] out JsonElement? value) + { + value = (this as ExtensionVariants::AIAutoDescription)?.Value; + return value != null; + } + + public void Switch( + Action removeBg, + Action autoTagging, + Action aiAutoDescription + ) + { + switch (this) + { + case ExtensionVariants::RemoveBg inner: + removeBg(inner); + break; + case ExtensionVariants::AutoTaggingExtension inner: + autoTagging(inner); + break; + case ExtensionVariants::AIAutoDescription inner: + aiAutoDescription(inner); + break; + default: + throw new InvalidOperationException(); + } + } + + public T Match( + Func removeBg, + Func autoTagging, + Func aiAutoDescription + ) + { + return this switch + { + ExtensionVariants::RemoveBg inner => removeBg(inner), + ExtensionVariants::AutoTaggingExtension inner => autoTagging(inner), + ExtensionVariants::AIAutoDescription inner => aiAutoDescription(inner), + _ => throw new InvalidOperationException(), + }; + } + + public abstract void Validate(); +} + +sealed class ExtensionConverter : JsonConverter +{ + public override Extension? Read( + ref Utf8JsonReader reader, + Type typeToConvert, + JsonSerializerOptions options + ) + { + var json = JsonSerializer.Deserialize(ref reader, options); + string? name; + try + { + name = json.GetProperty("name").GetString(); + } + catch + { + name = null; + } + + switch (name) + { + case "remove-bg": + { + List exceptions = []; + + try + { + var deserialized = JsonSerializer.Deserialize(json, options); + if (deserialized != null) + { + return new ExtensionVariants::RemoveBg(deserialized); + } + } + catch (JsonException e) + { + exceptions.Add(e); + } + + throw new AggregateException(exceptions); + } + case "ai-auto-description": + { + List exceptions = []; + + try + { + return new ExtensionVariants::AIAutoDescription( + JsonSerializer.Deserialize(json, options) + ); + } + catch (JsonException e) + { + exceptions.Add(e); + } + + throw new AggregateException(exceptions); + } + default: + { + List exceptions = []; + + try + { + var deserialized = JsonSerializer.Deserialize( + json, + options + ); + if (deserialized != null) + { + return new ExtensionVariants::AutoTaggingExtension(deserialized); + } + } + catch (JsonException e) + { + exceptions.Add(e); + } + + throw new AggregateException(exceptions); + } + } + } + + public override void Write( + Utf8JsonWriter writer, + Extension value, + JsonSerializerOptions options + ) + { + object variant = value switch + { + ExtensionVariants::RemoveBg(var removeBg) => removeBg, + ExtensionVariants::AutoTaggingExtension(var autoTagging) => autoTagging, + ExtensionVariants::AIAutoDescription(var aiAutoDescription) => aiAutoDescription, + _ => throw new ArgumentOutOfRangeException(nameof(value)), + }; + JsonSerializer.Serialize(writer, variant, options); + } +} diff --git a/src/Imagekit/Models/Beta/V2/Files/FileUploadParamsProperties/ExtensionProperties/AutoTaggingExtension.cs b/src/Imagekit/Models/Beta/V2/Files/FileUploadParamsProperties/ExtensionProperties/AutoTaggingExtension.cs new file mode 100644 index 00000000..0d372e84 --- /dev/null +++ b/src/Imagekit/Models/Beta/V2/Files/FileUploadParamsProperties/ExtensionProperties/AutoTaggingExtension.cs @@ -0,0 +1,100 @@ +using System; +using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; +using System.Text.Json; +using System.Text.Json.Serialization; +using Imagekit.Models.Beta.V2.Files.FileUploadParamsProperties.ExtensionProperties.AutoTaggingExtensionProperties; + +namespace Imagekit.Models.Beta.V2.Files.FileUploadParamsProperties.ExtensionProperties; + +[JsonConverter(typeof(ModelConverter))] +public sealed record class AutoTaggingExtension : ModelBase, IFromRaw +{ + /// + /// Maximum number of tags to attach to the asset. + /// + public required long MaxTags + { + get + { + if (!this.Properties.TryGetValue("maxTags", out JsonElement element)) + throw new ArgumentOutOfRangeException("maxTags", "Missing required argument"); + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions); + } + set + { + this.Properties["maxTags"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + /// + /// Minimum confidence level for tags to be considered valid. + /// + public required long MinConfidence + { + get + { + if (!this.Properties.TryGetValue("minConfidence", out JsonElement element)) + throw new ArgumentOutOfRangeException("minConfidence", "Missing required argument"); + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions); + } + set + { + this.Properties["minConfidence"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + /// + /// Specifies the auto-tagging extension used. + /// + public required ApiEnum Name + { + get + { + if (!this.Properties.TryGetValue("name", out JsonElement element)) + throw new ArgumentOutOfRangeException("name", "Missing required argument"); + + return JsonSerializer.Deserialize>( + element, + ModelBase.SerializerOptions + ); + } + set + { + this.Properties["name"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + public override void Validate() + { + _ = this.MaxTags; + _ = this.MinConfidence; + this.Name.Validate(); + } + + public AutoTaggingExtension() { } + +#pragma warning disable CS8618 + [SetsRequiredMembers] + AutoTaggingExtension(Dictionary properties) + { + Properties = properties; + } +#pragma warning restore CS8618 + + public static AutoTaggingExtension FromRawUnchecked(Dictionary properties) + { + return new(properties); + } +} diff --git a/src/Imagekit/Models/Beta/V2/Files/FileUploadParamsProperties/ExtensionProperties/AutoTaggingExtensionProperties/Name.cs b/src/Imagekit/Models/Beta/V2/Files/FileUploadParamsProperties/ExtensionProperties/AutoTaggingExtensionProperties/Name.cs new file mode 100644 index 00000000..d6d37376 --- /dev/null +++ b/src/Imagekit/Models/Beta/V2/Files/FileUploadParamsProperties/ExtensionProperties/AutoTaggingExtensionProperties/Name.cs @@ -0,0 +1,46 @@ +using System; +using System.Text.Json; +using System.Text.Json.Serialization; + +namespace Imagekit.Models.Beta.V2.Files.FileUploadParamsProperties.ExtensionProperties.AutoTaggingExtensionProperties; + +/// +/// Specifies the auto-tagging extension used. +/// +[JsonConverter(typeof(NameConverter))] +public enum Name +{ + GoogleAutoTagging, + AwsAutoTagging, +} + +sealed class NameConverter : JsonConverter +{ + public override Name Read( + ref Utf8JsonReader reader, + Type typeToConvert, + JsonSerializerOptions options + ) + { + return JsonSerializer.Deserialize(ref reader, options) switch + { + "google-auto-tagging" => Name.GoogleAutoTagging, + "aws-auto-tagging" => Name.AwsAutoTagging, + _ => (Name)(-1), + }; + } + + public override void Write(Utf8JsonWriter writer, Name value, JsonSerializerOptions options) + { + JsonSerializer.Serialize( + writer, + value switch + { + Name.GoogleAutoTagging => "google-auto-tagging", + Name.AwsAutoTagging => "aws-auto-tagging", + _ => throw new ArgumentOutOfRangeException(nameof(value)), + }, + options + ); + } +} diff --git a/src/Imagekit/Models/Beta/V2/Files/FileUploadParamsProperties/ExtensionProperties/RemoveBg.cs b/src/Imagekit/Models/Beta/V2/Files/FileUploadParamsProperties/ExtensionProperties/RemoveBg.cs new file mode 100644 index 00000000..fde15cdf --- /dev/null +++ b/src/Imagekit/Models/Beta/V2/Files/FileUploadParamsProperties/ExtensionProperties/RemoveBg.cs @@ -0,0 +1,74 @@ +using System; +using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; +using System.Text.Json; +using System.Text.Json.Serialization; +using Imagekit.Models.Beta.V2.Files.FileUploadParamsProperties.ExtensionProperties.RemoveBgProperties; + +namespace Imagekit.Models.Beta.V2.Files.FileUploadParamsProperties.ExtensionProperties; + +[JsonConverter(typeof(ModelConverter))] +public sealed record class RemoveBg : ModelBase, IFromRaw +{ + /// + /// Specifies the background removal extension. + /// + public JsonElement Name + { + get + { + if (!this.Properties.TryGetValue("name", out JsonElement element)) + throw new ArgumentOutOfRangeException("name", "Missing required argument"); + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions); + } + set + { + this.Properties["name"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + public Options? Options + { + get + { + if (!this.Properties.TryGetValue("options", out JsonElement element)) + return null; + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions); + } + set + { + this.Properties["options"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + public override void Validate() + { + this.Options?.Validate(); + } + + public RemoveBg() + { + this.Name = JsonSerializer.Deserialize("\"remove-bg\""); + } + +#pragma warning disable CS8618 + [SetsRequiredMembers] + RemoveBg(Dictionary properties) + { + Properties = properties; + } +#pragma warning restore CS8618 + + public static RemoveBg FromRawUnchecked(Dictionary properties) + { + return new(properties); + } +} diff --git a/src/Imagekit/Models/Beta/V2/Files/FileUploadParamsProperties/ExtensionProperties/RemoveBgProperties/Options.cs b/src/Imagekit/Models/Beta/V2/Files/FileUploadParamsProperties/ExtensionProperties/RemoveBgProperties/Options.cs new file mode 100644 index 00000000..5b7de9ca --- /dev/null +++ b/src/Imagekit/Models/Beta/V2/Files/FileUploadParamsProperties/ExtensionProperties/RemoveBgProperties/Options.cs @@ -0,0 +1,122 @@ +using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; +using System.Text.Json; +using System.Text.Json.Serialization; + +namespace Imagekit.Models.Beta.V2.Files.FileUploadParamsProperties.ExtensionProperties.RemoveBgProperties; + +[JsonConverter(typeof(ModelConverter))] +public sealed record class Options : ModelBase, IFromRaw +{ + /// + /// Whether to add an artificial shadow to the result. Default is false. Note: + /// Adding shadows is currently only supported for car photos. + /// + public bool? AddShadow + { + get + { + if (!this.Properties.TryGetValue("add_shadow", out JsonElement element)) + return null; + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions); + } + set + { + this.Properties["add_shadow"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + /// + /// Specifies a solid color background using hex code (e.g., "81d4fa", "fff") + /// or color name (e.g., "green"). If this parameter is set, `bg_image_url` must + /// be empty. + /// + public string? BgColor + { + get + { + if (!this.Properties.TryGetValue("bg_color", out JsonElement element)) + return null; + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions); + } + set + { + this.Properties["bg_color"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + /// + /// Sets a background image from a URL. If this parameter is set, `bg_color` + /// must be empty. + /// + public string? BgImageURL + { + get + { + if (!this.Properties.TryGetValue("bg_image_url", out JsonElement element)) + return null; + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions); + } + set + { + this.Properties["bg_image_url"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + /// + /// Allows semi-transparent regions in the result. Default is true. Note: Semitransparency + /// is currently only supported for car windows. + /// + public bool? Semitransparency + { + get + { + if (!this.Properties.TryGetValue("semitransparency", out JsonElement element)) + return null; + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions); + } + set + { + this.Properties["semitransparency"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + public override void Validate() + { + _ = this.AddShadow; + _ = this.BgColor; + _ = this.BgImageURL; + _ = this.Semitransparency; + } + + public Options() { } + +#pragma warning disable CS8618 + [SetsRequiredMembers] + Options(Dictionary properties) + { + Properties = properties; + } +#pragma warning restore CS8618 + + public static Options FromRawUnchecked(Dictionary properties) + { + return new(properties); + } +} diff --git a/src/Imagekit/Models/Beta/V2/Files/FileUploadParamsProperties/ExtensionVariants/All.cs b/src/Imagekit/Models/Beta/V2/Files/FileUploadParamsProperties/ExtensionVariants/All.cs new file mode 100644 index 00000000..8806e3a7 --- /dev/null +++ b/src/Imagekit/Models/Beta/V2/Files/FileUploadParamsProperties/ExtensionVariants/All.cs @@ -0,0 +1,46 @@ +using System.Text.Json; +using ExtensionProperties = Imagekit.Models.Beta.V2.Files.FileUploadParamsProperties.ExtensionProperties; + +namespace Imagekit.Models.Beta.V2.Files.FileUploadParamsProperties.ExtensionVariants; + +public sealed record class RemoveBg(ExtensionProperties::RemoveBg Value) + : Extension, + IVariant +{ + public static RemoveBg From(ExtensionProperties::RemoveBg value) + { + return new(value); + } + + public override void Validate() + { + this.Value.Validate(); + } +} + +public sealed record class AutoTaggingExtension(ExtensionProperties::AutoTaggingExtension Value) + : Extension, + IVariant +{ + public static AutoTaggingExtension From(ExtensionProperties::AutoTaggingExtension value) + { + return new(value); + } + + public override void Validate() + { + this.Value.Validate(); + } +} + +public sealed record class AIAutoDescription(JsonElement Value) + : Extension, + IVariant +{ + public static AIAutoDescription From(JsonElement value) + { + return new(value); + } + + public override void Validate() { } +} diff --git a/src/Imagekit/Models/Beta/V2/Files/FileUploadParamsProperties/ResponseField.cs b/src/Imagekit/Models/Beta/V2/Files/FileUploadParamsProperties/ResponseField.cs new file mode 100644 index 00000000..91a2f19c --- /dev/null +++ b/src/Imagekit/Models/Beta/V2/Files/FileUploadParamsProperties/ResponseField.cs @@ -0,0 +1,62 @@ +using System; +using System.Text.Json; +using System.Text.Json.Serialization; + +namespace Imagekit.Models.Beta.V2.Files.FileUploadParamsProperties; + +[JsonConverter(typeof(ResponseFieldConverter))] +public enum ResponseField +{ + Tags, + CustomCoordinates, + IsPrivateFile, + EmbeddedMetadata, + IsPublished, + CustomMetadata, + Metadata, +} + +sealed class ResponseFieldConverter : JsonConverter +{ + public override ResponseField Read( + ref Utf8JsonReader reader, + Type typeToConvert, + JsonSerializerOptions options + ) + { + return JsonSerializer.Deserialize(ref reader, options) switch + { + "tags" => ResponseField.Tags, + "customCoordinates" => ResponseField.CustomCoordinates, + "isPrivateFile" => ResponseField.IsPrivateFile, + "embeddedMetadata" => ResponseField.EmbeddedMetadata, + "isPublished" => ResponseField.IsPublished, + "customMetadata" => ResponseField.CustomMetadata, + "metadata" => ResponseField.Metadata, + _ => (ResponseField)(-1), + }; + } + + public override void Write( + Utf8JsonWriter writer, + ResponseField value, + JsonSerializerOptions options + ) + { + JsonSerializer.Serialize( + writer, + value switch + { + ResponseField.Tags => "tags", + ResponseField.CustomCoordinates => "customCoordinates", + ResponseField.IsPrivateFile => "isPrivateFile", + ResponseField.EmbeddedMetadata => "embeddedMetadata", + ResponseField.IsPublished => "isPublished", + ResponseField.CustomMetadata => "customMetadata", + ResponseField.Metadata => "metadata", + _ => throw new ArgumentOutOfRangeException(nameof(value)), + }, + options + ); + } +} diff --git a/src/Imagekit/Models/Beta/V2/Files/FileUploadParamsProperties/Transformation.cs b/src/Imagekit/Models/Beta/V2/Files/FileUploadParamsProperties/Transformation.cs new file mode 100644 index 00000000..928b8185 --- /dev/null +++ b/src/Imagekit/Models/Beta/V2/Files/FileUploadParamsProperties/Transformation.cs @@ -0,0 +1,92 @@ +using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; +using System.Text.Json; +using System.Text.Json.Serialization; +using Imagekit.Models.Beta.V2.Files.FileUploadParamsProperties.TransformationProperties; + +namespace Imagekit.Models.Beta.V2.Files.FileUploadParamsProperties; + +/// +/// Configure pre-processing (`pre`) and post-processing (`post`) transformations. +/// +/// - `pre` — applied before the file is uploaded to the Media Library. Useful +/// for reducing file size or applying basic optimizations upfront (e.g., resize, compress). +/// +/// - `post` — applied immediately after upload. Ideal for generating transformed +/// versions (like video encodes or thumbnails) in advance, so they're ready for +/// delivery without delay. +/// +/// You can mix and match any combination of post-processing types. +/// +[JsonConverter(typeof(ModelConverter))] +public sealed record class Transformation : ModelBase, IFromRaw +{ + /// + /// List of transformations to apply *after* the file is uploaded. Each item + /// must match one of the following types: `transformation`, `gif-to-video`, + /// `thumbnail`, `abs`. + /// + public List? Post + { + get + { + if (!this.Properties.TryGetValue("post", out JsonElement element)) + return null; + + return JsonSerializer.Deserialize?>(element, ModelBase.SerializerOptions); + } + set + { + this.Properties["post"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + /// + /// Transformation string to apply before uploading the file to the Media Library. + /// Useful for optimizing files at ingestion. + /// + public string? Pre + { + get + { + if (!this.Properties.TryGetValue("pre", out JsonElement element)) + return null; + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions); + } + set + { + this.Properties["pre"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + public override void Validate() + { + foreach (var item in this.Post ?? []) + { + item.Validate(); + } + _ = this.Pre; + } + + public Transformation() { } + +#pragma warning disable CS8618 + [SetsRequiredMembers] + Transformation(Dictionary properties) + { + Properties = properties; + } +#pragma warning restore CS8618 + + public static Transformation FromRawUnchecked(Dictionary properties) + { + return new(properties); + } +} diff --git a/src/Imagekit/Models/Beta/V2/Files/FileUploadParamsProperties/TransformationProperties/Post.cs b/src/Imagekit/Models/Beta/V2/Files/FileUploadParamsProperties/TransformationProperties/Post.cs new file mode 100644 index 00000000..80ec39d5 --- /dev/null +++ b/src/Imagekit/Models/Beta/V2/Files/FileUploadParamsProperties/TransformationProperties/Post.cs @@ -0,0 +1,225 @@ +using System; +using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; +using System.Text.Json; +using System.Text.Json.Serialization; +using PostProperties = Imagekit.Models.Beta.V2.Files.FileUploadParamsProperties.TransformationProperties.PostProperties; +using PostVariants = Imagekit.Models.Beta.V2.Files.FileUploadParamsProperties.TransformationProperties.PostVariants; + +namespace Imagekit.Models.Beta.V2.Files.FileUploadParamsProperties.TransformationProperties; + +[JsonConverter(typeof(PostConverter))] +public abstract record class Post +{ + internal Post() { } + + public static implicit operator Post(PostProperties::Transformation value) => + new PostVariants::Transformation(value); + + public static implicit operator Post(PostProperties::GifToVideo value) => + new PostVariants::GifToVideo(value); + + public static implicit operator Post(PostProperties::Thumbnail value) => + new PostVariants::Thumbnail(value); + + public static implicit operator Post(PostProperties::Abs value) => new PostVariants::Abs(value); + + public bool TryPickTransformation([NotNullWhen(true)] out PostProperties::Transformation? value) + { + value = (this as PostVariants::Transformation)?.Value; + return value != null; + } + + public bool TryPickGifToVideo([NotNullWhen(true)] out PostProperties::GifToVideo? value) + { + value = (this as PostVariants::GifToVideo)?.Value; + return value != null; + } + + public bool TryPickThumbnail([NotNullWhen(true)] out PostProperties::Thumbnail? value) + { + value = (this as PostVariants::Thumbnail)?.Value; + return value != null; + } + + public bool TryPickAbs([NotNullWhen(true)] out PostProperties::Abs? value) + { + value = (this as PostVariants::Abs)?.Value; + return value != null; + } + + public void Switch( + Action transformation, + Action gifToVideo, + Action thumbnail, + Action abs + ) + { + switch (this) + { + case PostVariants::Transformation inner: + transformation(inner); + break; + case PostVariants::GifToVideo inner: + gifToVideo(inner); + break; + case PostVariants::Thumbnail inner: + thumbnail(inner); + break; + case PostVariants::Abs inner: + abs(inner); + break; + default: + throw new InvalidOperationException(); + } + } + + public T Match( + Func transformation, + Func gifToVideo, + Func thumbnail, + Func abs + ) + { + return this switch + { + PostVariants::Transformation inner => transformation(inner), + PostVariants::GifToVideo inner => gifToVideo(inner), + PostVariants::Thumbnail inner => thumbnail(inner), + PostVariants::Abs inner => abs(inner), + _ => throw new InvalidOperationException(), + }; + } + + public abstract void Validate(); +} + +sealed class PostConverter : JsonConverter +{ + public override Post? Read( + ref Utf8JsonReader reader, + Type typeToConvert, + JsonSerializerOptions options + ) + { + var json = JsonSerializer.Deserialize(ref reader, options); + string? type; + try + { + type = json.GetProperty("type").GetString(); + } + catch + { + type = null; + } + + switch (type) + { + case "transformation": + { + List exceptions = []; + + try + { + var deserialized = JsonSerializer.Deserialize( + json, + options + ); + if (deserialized != null) + { + return new PostVariants::Transformation(deserialized); + } + } + catch (JsonException e) + { + exceptions.Add(e); + } + + throw new AggregateException(exceptions); + } + case "gif-to-video": + { + List exceptions = []; + + try + { + var deserialized = JsonSerializer.Deserialize( + json, + options + ); + if (deserialized != null) + { + return new PostVariants::GifToVideo(deserialized); + } + } + catch (JsonException e) + { + exceptions.Add(e); + } + + throw new AggregateException(exceptions); + } + case "thumbnail": + { + List exceptions = []; + + try + { + var deserialized = JsonSerializer.Deserialize( + json, + options + ); + if (deserialized != null) + { + return new PostVariants::Thumbnail(deserialized); + } + } + catch (JsonException e) + { + exceptions.Add(e); + } + + throw new AggregateException(exceptions); + } + case "abs": + { + List exceptions = []; + + try + { + var deserialized = JsonSerializer.Deserialize( + json, + options + ); + if (deserialized != null) + { + return new PostVariants::Abs(deserialized); + } + } + catch (JsonException e) + { + exceptions.Add(e); + } + + throw new AggregateException(exceptions); + } + default: + { + throw new Exception(); + } + } + } + + public override void Write(Utf8JsonWriter writer, Post value, JsonSerializerOptions options) + { + object variant = value switch + { + PostVariants::Transformation(var transformation) => transformation, + PostVariants::GifToVideo(var gifToVideo) => gifToVideo, + PostVariants::Thumbnail(var thumbnail) => thumbnail, + PostVariants::Abs(var abs) => abs, + _ => throw new ArgumentOutOfRangeException(nameof(value)), + }; + JsonSerializer.Serialize(writer, variant, options); + } +} diff --git a/src/Imagekit/Models/Beta/V2/Files/FileUploadParamsProperties/TransformationProperties/PostProperties/Abs.cs b/src/Imagekit/Models/Beta/V2/Files/FileUploadParamsProperties/TransformationProperties/PostProperties/Abs.cs new file mode 100644 index 00000000..f6369541 --- /dev/null +++ b/src/Imagekit/Models/Beta/V2/Files/FileUploadParamsProperties/TransformationProperties/PostProperties/Abs.cs @@ -0,0 +1,103 @@ +using System; +using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; +using System.Text.Json; +using System.Text.Json.Serialization; +using Imagekit.Models.Beta.V2.Files.FileUploadParamsProperties.TransformationProperties.PostProperties.AbsProperties; + +namespace Imagekit.Models.Beta.V2.Files.FileUploadParamsProperties.TransformationProperties.PostProperties; + +[JsonConverter(typeof(ModelConverter))] +public sealed record class Abs : ModelBase, IFromRaw +{ + /// + /// Streaming protocol to use (`hls` or `dash`). + /// + public required ApiEnum Protocol + { + get + { + if (!this.Properties.TryGetValue("protocol", out JsonElement element)) + throw new ArgumentOutOfRangeException("protocol", "Missing required argument"); + + return JsonSerializer.Deserialize>( + element, + ModelBase.SerializerOptions + ); + } + set + { + this.Properties["protocol"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + /// + /// Adaptive Bitrate Streaming (ABS) setup. + /// + public JsonElement Type + { + get + { + if (!this.Properties.TryGetValue("type", out JsonElement element)) + throw new ArgumentOutOfRangeException("type", "Missing required argument"); + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions); + } + set + { + this.Properties["type"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + /// + /// List of different representations you want to create separated by an underscore. + /// + public required string Value + { + get + { + if (!this.Properties.TryGetValue("value", out JsonElement element)) + throw new ArgumentOutOfRangeException("value", "Missing required argument"); + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions) + ?? throw new ArgumentNullException("value"); + } + set + { + this.Properties["value"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + public override void Validate() + { + this.Protocol.Validate(); + _ = this.Value; + } + + public Abs() + { + this.Type = JsonSerializer.Deserialize("\"abs\""); + } + +#pragma warning disable CS8618 + [SetsRequiredMembers] + Abs(Dictionary properties) + { + Properties = properties; + } +#pragma warning restore CS8618 + + public static Abs FromRawUnchecked(Dictionary properties) + { + return new(properties); + } +} diff --git a/src/Imagekit/Models/Beta/V2/Files/FileUploadParamsProperties/TransformationProperties/PostProperties/AbsProperties/Protocol.cs b/src/Imagekit/Models/Beta/V2/Files/FileUploadParamsProperties/TransformationProperties/PostProperties/AbsProperties/Protocol.cs new file mode 100644 index 00000000..fb83079d --- /dev/null +++ b/src/Imagekit/Models/Beta/V2/Files/FileUploadParamsProperties/TransformationProperties/PostProperties/AbsProperties/Protocol.cs @@ -0,0 +1,46 @@ +using System; +using System.Text.Json; +using System.Text.Json.Serialization; + +namespace Imagekit.Models.Beta.V2.Files.FileUploadParamsProperties.TransformationProperties.PostProperties.AbsProperties; + +/// +/// Streaming protocol to use (`hls` or `dash`). +/// +[JsonConverter(typeof(ProtocolConverter))] +public enum Protocol +{ + Hls, + Dash, +} + +sealed class ProtocolConverter : JsonConverter +{ + public override Protocol Read( + ref Utf8JsonReader reader, + Type typeToConvert, + JsonSerializerOptions options + ) + { + return JsonSerializer.Deserialize(ref reader, options) switch + { + "hls" => Protocol.Hls, + "dash" => Protocol.Dash, + _ => (Protocol)(-1), + }; + } + + public override void Write(Utf8JsonWriter writer, Protocol value, JsonSerializerOptions options) + { + JsonSerializer.Serialize( + writer, + value switch + { + Protocol.Hls => "hls", + Protocol.Dash => "dash", + _ => throw new ArgumentOutOfRangeException(nameof(value)), + }, + options + ); + } +} diff --git a/src/Imagekit/Models/Beta/V2/Files/FileUploadParamsProperties/TransformationProperties/PostProperties/GifToVideo.cs b/src/Imagekit/Models/Beta/V2/Files/FileUploadParamsProperties/TransformationProperties/PostProperties/GifToVideo.cs new file mode 100644 index 00000000..6f180d0b --- /dev/null +++ b/src/Imagekit/Models/Beta/V2/Files/FileUploadParamsProperties/TransformationProperties/PostProperties/GifToVideo.cs @@ -0,0 +1,77 @@ +using System; +using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; +using System.Text.Json; +using System.Text.Json.Serialization; + +namespace Imagekit.Models.Beta.V2.Files.FileUploadParamsProperties.TransformationProperties.PostProperties; + +[JsonConverter(typeof(ModelConverter))] +public sealed record class GifToVideo : ModelBase, IFromRaw +{ + /// + /// Converts an animated GIF into an MP4. + /// + public JsonElement Type + { + get + { + if (!this.Properties.TryGetValue("type", out JsonElement element)) + throw new ArgumentOutOfRangeException("type", "Missing required argument"); + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions); + } + set + { + this.Properties["type"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + /// + /// Optional transformation string to apply to the output video. **Example**: + /// `q-80` + /// + public string? Value + { + get + { + if (!this.Properties.TryGetValue("value", out JsonElement element)) + return null; + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions); + } + set + { + this.Properties["value"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + public override void Validate() + { + _ = this.Value; + } + + public GifToVideo() + { + this.Type = JsonSerializer.Deserialize("\"gif-to-video\""); + } + +#pragma warning disable CS8618 + [SetsRequiredMembers] + GifToVideo(Dictionary properties) + { + Properties = properties; + } +#pragma warning restore CS8618 + + public static GifToVideo FromRawUnchecked(Dictionary properties) + { + return new(properties); + } +} diff --git a/src/Imagekit/Models/Beta/V2/Files/FileUploadParamsProperties/TransformationProperties/PostProperties/Thumbnail.cs b/src/Imagekit/Models/Beta/V2/Files/FileUploadParamsProperties/TransformationProperties/PostProperties/Thumbnail.cs new file mode 100644 index 00000000..b2ee20f1 --- /dev/null +++ b/src/Imagekit/Models/Beta/V2/Files/FileUploadParamsProperties/TransformationProperties/PostProperties/Thumbnail.cs @@ -0,0 +1,76 @@ +using System; +using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; +using System.Text.Json; +using System.Text.Json.Serialization; + +namespace Imagekit.Models.Beta.V2.Files.FileUploadParamsProperties.TransformationProperties.PostProperties; + +[JsonConverter(typeof(ModelConverter))] +public sealed record class Thumbnail : ModelBase, IFromRaw +{ + /// + /// Generates a thumbnail image. + /// + public JsonElement Type + { + get + { + if (!this.Properties.TryGetValue("type", out JsonElement element)) + throw new ArgumentOutOfRangeException("type", "Missing required argument"); + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions); + } + set + { + this.Properties["type"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + /// + /// Optional transformation string. **Example**: `w-150,h-150` + /// + public string? Value + { + get + { + if (!this.Properties.TryGetValue("value", out JsonElement element)) + return null; + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions); + } + set + { + this.Properties["value"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + public override void Validate() + { + _ = this.Value; + } + + public Thumbnail() + { + this.Type = JsonSerializer.Deserialize("\"thumbnail\""); + } + +#pragma warning disable CS8618 + [SetsRequiredMembers] + Thumbnail(Dictionary properties) + { + Properties = properties; + } +#pragma warning restore CS8618 + + public static Thumbnail FromRawUnchecked(Dictionary properties) + { + return new(properties); + } +} diff --git a/src/Imagekit/Models/Beta/V2/Files/FileUploadParamsProperties/TransformationProperties/PostProperties/Transformation.cs b/src/Imagekit/Models/Beta/V2/Files/FileUploadParamsProperties/TransformationProperties/PostProperties/Transformation.cs new file mode 100644 index 00000000..4fdd2185 --- /dev/null +++ b/src/Imagekit/Models/Beta/V2/Files/FileUploadParamsProperties/TransformationProperties/PostProperties/Transformation.cs @@ -0,0 +1,85 @@ +using System; +using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; +using System.Text.Json; +using System.Text.Json.Serialization; + +namespace Imagekit.Models.Beta.V2.Files.FileUploadParamsProperties.TransformationProperties.PostProperties; + +[JsonConverter(typeof(ModelConverter))] +public sealed record class Transformation : ModelBase, IFromRaw +{ + /// + /// Transformation type. + /// + public JsonElement Type + { + get + { + if (!this.Properties.TryGetValue("type", out JsonElement element)) + throw new ArgumentOutOfRangeException("type", "Missing required argument"); + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions); + } + set + { + this.Properties["type"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + /// + /// Transformation string (e.g. `w-200,h-200`). Same syntax as ImageKit URL-based + /// transformations. + /// + public required string Value + { + get + { + if (!this.Properties.TryGetValue("value", out JsonElement element)) + throw new ArgumentOutOfRangeException("value", "Missing required argument"); + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions) + ?? throw new ArgumentNullException("value"); + } + set + { + this.Properties["value"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + public override void Validate() + { + _ = this.Value; + } + + public Transformation() + { + this.Type = JsonSerializer.Deserialize("\"transformation\""); + } + +#pragma warning disable CS8618 + [SetsRequiredMembers] + Transformation(Dictionary properties) + { + Properties = properties; + } +#pragma warning restore CS8618 + + public static Transformation FromRawUnchecked(Dictionary properties) + { + return new(properties); + } + + [SetsRequiredMembers] + public Transformation(string value) + : this() + { + this.Value = value; + } +} diff --git a/src/Imagekit/Models/Beta/V2/Files/FileUploadParamsProperties/TransformationProperties/PostVariants/All.cs b/src/Imagekit/Models/Beta/V2/Files/FileUploadParamsProperties/TransformationProperties/PostVariants/All.cs new file mode 100644 index 00000000..4530dadc --- /dev/null +++ b/src/Imagekit/Models/Beta/V2/Files/FileUploadParamsProperties/TransformationProperties/PostVariants/All.cs @@ -0,0 +1,61 @@ +using PostProperties = Imagekit.Models.Beta.V2.Files.FileUploadParamsProperties.TransformationProperties.PostProperties; + +namespace Imagekit.Models.Beta.V2.Files.FileUploadParamsProperties.TransformationProperties.PostVariants; + +public sealed record class Transformation(PostProperties::Transformation Value) + : Post, + IVariant +{ + public static Transformation From(PostProperties::Transformation value) + { + return new(value); + } + + public override void Validate() + { + this.Value.Validate(); + } +} + +public sealed record class GifToVideo(PostProperties::GifToVideo Value) + : Post, + IVariant +{ + public static GifToVideo From(PostProperties::GifToVideo value) + { + return new(value); + } + + public override void Validate() + { + this.Value.Validate(); + } +} + +public sealed record class Thumbnail(PostProperties::Thumbnail Value) + : Post, + IVariant +{ + public static Thumbnail From(PostProperties::Thumbnail value) + { + return new(value); + } + + public override void Validate() + { + this.Value.Validate(); + } +} + +public sealed record class Abs(PostProperties::Abs Value) : Post, IVariant +{ + public static Abs From(PostProperties::Abs value) + { + return new(value); + } + + public override void Validate() + { + this.Value.Validate(); + } +} diff --git a/src/Imagekit/Models/Beta/V2/Files/FileUploadResponse.cs b/src/Imagekit/Models/Beta/V2/Files/FileUploadResponse.cs new file mode 100644 index 00000000..723b749b --- /dev/null +++ b/src/Imagekit/Models/Beta/V2/Files/FileUploadResponse.cs @@ -0,0 +1,616 @@ +using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; +using System.Text.Json; +using System.Text.Json.Serialization; +using Imagekit.Models.Beta.V2.Files.FileUploadResponseProperties; +using Files = Imagekit.Models.Files; + +namespace Imagekit.Models.Beta.V2.Files; + +/// +/// Object containing details of a successful upload. +/// +[JsonConverter(typeof(ModelConverter))] +public sealed record class FileUploadResponse : ModelBase, IFromRaw +{ + /// + /// An array of tags assigned to the uploaded file by auto tagging. + /// + public List? AITags + { + get + { + if (!this.Properties.TryGetValue("AITags", out JsonElement element)) + return null; + + return JsonSerializer.Deserialize?>(element, ModelBase.SerializerOptions); + } + set + { + this.Properties["AITags"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + /// + /// The audio codec used in the video (only for video). + /// + public string? AudioCodec + { + get + { + if (!this.Properties.TryGetValue("audioCodec", out JsonElement element)) + return null; + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions); + } + set + { + this.Properties["audioCodec"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + /// + /// The bit rate of the video in kbps (only for video). + /// + public long? BitRate + { + get + { + if (!this.Properties.TryGetValue("bitRate", out JsonElement element)) + return null; + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions); + } + set + { + this.Properties["bitRate"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + /// + /// Value of custom coordinates associated with the image in the format `x,y,width,height`. + /// If `customCoordinates` are not defined, then it is `null`. Send `customCoordinates` + /// in `responseFields` in API request to get the value of this field. + /// + public string? CustomCoordinates + { + get + { + if (!this.Properties.TryGetValue("customCoordinates", out JsonElement element)) + return null; + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions); + } + set + { + this.Properties["customCoordinates"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + /// + /// A key-value data associated with the asset. Use `responseField` in API request + /// to get `customMetadata` in the upload API response. Before setting any custom + /// metadata on an asset, you have to create the field using custom metadata + /// fields API. Send `customMetadata` in `responseFields` in API request to get + /// the value of this field. + /// + public Dictionary? CustomMetadata + { + get + { + if (!this.Properties.TryGetValue("customMetadata", out JsonElement element)) + return null; + + return JsonSerializer.Deserialize?>( + element, + ModelBase.SerializerOptions + ); + } + set + { + this.Properties["customMetadata"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + /// + /// Optional text to describe the contents of the file. Can be set by the user + /// or the ai-auto-description extension. + /// + public string? Description + { + get + { + if (!this.Properties.TryGetValue("description", out JsonElement element)) + return null; + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions); + } + set + { + this.Properties["description"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + /// + /// The duration of the video in seconds (only for video). + /// + public long? Duration + { + get + { + if (!this.Properties.TryGetValue("duration", out JsonElement element)) + return null; + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions); + } + set + { + this.Properties["duration"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + /// + /// Consolidated embedded metadata associated with the file. It includes exif, + /// iptc, and xmp data. Send `embeddedMetadata` in `responseFields` in API request + /// to get embeddedMetadata in the upload API response. + /// + public Dictionary? EmbeddedMetadata + { + get + { + if (!this.Properties.TryGetValue("embeddedMetadata", out JsonElement element)) + return null; + + return JsonSerializer.Deserialize?>( + element, + ModelBase.SerializerOptions + ); + } + set + { + this.Properties["embeddedMetadata"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + /// + /// Extension names with their processing status at the time of completion of + /// the request. It could have one of the following status values: + /// + /// `success`: The extension has been successfully applied. `failed`: The extension + /// has failed and will not be retried. `pending`: The extension will finish processing + /// in some time. On completion, the final status (success / failed) will be sent + /// to the `webhookUrl` provided. + /// + /// If no extension was requested, then this parameter is not returned. + /// + public ExtensionStatus? ExtensionStatus + { + get + { + if (!this.Properties.TryGetValue("extensionStatus", out JsonElement element)) + return null; + + return JsonSerializer.Deserialize( + element, + ModelBase.SerializerOptions + ); + } + set + { + this.Properties["extensionStatus"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + /// + /// Unique fileId. Store this fileld in your database, as this will be used to + /// perform update action on this file. + /// + public string? FileID + { + get + { + if (!this.Properties.TryGetValue("fileId", out JsonElement element)) + return null; + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions); + } + set + { + this.Properties["fileId"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + /// + /// The relative path of the file in the media library e.g. `/marketing-assets/new-banner.jpg`. + /// + public string? FilePath + { + get + { + if (!this.Properties.TryGetValue("filePath", out JsonElement element)) + return null; + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions); + } + set + { + this.Properties["filePath"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + /// + /// Type of the uploaded file. Possible values are `image`, `non-image`. + /// + public string? FileType + { + get + { + if (!this.Properties.TryGetValue("fileType", out JsonElement element)) + return null; + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions); + } + set + { + this.Properties["fileType"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + /// + /// Height of the image in pixels (Only for images) + /// + public double? Height + { + get + { + if (!this.Properties.TryGetValue("height", out JsonElement element)) + return null; + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions); + } + set + { + this.Properties["height"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + /// + /// Is the file marked as private. It can be either `true` or `false`. Send `isPrivateFile` + /// in `responseFields` in API request to get the value of this field. + /// + public bool? IsPrivateFile + { + get + { + if (!this.Properties.TryGetValue("isPrivateFile", out JsonElement element)) + return null; + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions); + } + set + { + this.Properties["isPrivateFile"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + /// + /// Is the file published or in draft state. It can be either `true` or `false`. + /// Send `isPublished` in `responseFields` in API request to get the value of + /// this field. + /// + public bool? IsPublished + { + get + { + if (!this.Properties.TryGetValue("isPublished", out JsonElement element)) + return null; + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions); + } + set + { + this.Properties["isPublished"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + /// + /// Legacy metadata. Send `metadata` in `responseFields` in API request to get + /// metadata in the upload API response. + /// + public Files::Metadata? Metadata + { + get + { + if (!this.Properties.TryGetValue("metadata", out JsonElement element)) + return null; + + return JsonSerializer.Deserialize( + element, + ModelBase.SerializerOptions + ); + } + set + { + this.Properties["metadata"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + /// + /// Name of the asset. + /// + public string? Name + { + get + { + if (!this.Properties.TryGetValue("name", out JsonElement element)) + return null; + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions); + } + set + { + this.Properties["name"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + /// + /// Size of the image file in Bytes. + /// + public double? Size + { + get + { + if (!this.Properties.TryGetValue("size", out JsonElement element)) + return null; + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions); + } + set + { + this.Properties["size"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + /// + /// The array of tags associated with the asset. If no tags are set, it will + /// be `null`. Send `tags` in `responseFields` in API request to get the value + /// of this field. + /// + public List? Tags + { + get + { + if (!this.Properties.TryGetValue("tags", out JsonElement element)) + return null; + + return JsonSerializer.Deserialize?>(element, ModelBase.SerializerOptions); + } + set + { + this.Properties["tags"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + /// + /// In the case of an image, a small thumbnail URL. + /// + public string? ThumbnailURL + { + get + { + if (!this.Properties.TryGetValue("thumbnailUrl", out JsonElement element)) + return null; + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions); + } + set + { + this.Properties["thumbnailUrl"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + /// + /// A publicly accessible URL of the file. + /// + public string? URL + { + get + { + if (!this.Properties.TryGetValue("url", out JsonElement element)) + return null; + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions); + } + set + { + this.Properties["url"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + /// + /// An object containing the file or file version's `id` (versionId) and `name`. + /// + public VersionInfo? VersionInfo + { + get + { + if (!this.Properties.TryGetValue("versionInfo", out JsonElement element)) + return null; + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions); + } + set + { + this.Properties["versionInfo"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + /// + /// The video codec used in the video (only for video). + /// + public string? VideoCodec + { + get + { + if (!this.Properties.TryGetValue("videoCodec", out JsonElement element)) + return null; + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions); + } + set + { + this.Properties["videoCodec"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + /// + /// Width of the image in pixels (Only for Images) + /// + public double? Width + { + get + { + if (!this.Properties.TryGetValue("width", out JsonElement element)) + return null; + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions); + } + set + { + this.Properties["width"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + public override void Validate() + { + foreach (var item in this.AITags ?? []) + { + item.Validate(); + } + _ = this.AudioCodec; + _ = this.BitRate; + _ = this.CustomCoordinates; + if (this.CustomMetadata != null) + { + foreach (var item in this.CustomMetadata.Values) + { + _ = item; + } + } + _ = this.Description; + _ = this.Duration; + if (this.EmbeddedMetadata != null) + { + foreach (var item in this.EmbeddedMetadata.Values) + { + _ = item; + } + } + this.ExtensionStatus?.Validate(); + _ = this.FileID; + _ = this.FilePath; + _ = this.FileType; + _ = this.Height; + _ = this.IsPrivateFile; + _ = this.IsPublished; + this.Metadata?.Validate(); + _ = this.Name; + _ = this.Size; + foreach (var item in this.Tags ?? []) + { + _ = item; + } + _ = this.ThumbnailURL; + _ = this.URL; + this.VersionInfo?.Validate(); + _ = this.VideoCodec; + _ = this.Width; + } + + public FileUploadResponse() { } + +#pragma warning disable CS8618 + [SetsRequiredMembers] + FileUploadResponse(Dictionary properties) + { + Properties = properties; + } +#pragma warning restore CS8618 + + public static FileUploadResponse FromRawUnchecked(Dictionary properties) + { + return new(properties); + } +} diff --git a/src/Imagekit/Models/Beta/V2/Files/FileUploadResponseProperties/AITag.cs b/src/Imagekit/Models/Beta/V2/Files/FileUploadResponseProperties/AITag.cs new file mode 100644 index 00000000..a6c52d08 --- /dev/null +++ b/src/Imagekit/Models/Beta/V2/Files/FileUploadResponseProperties/AITag.cs @@ -0,0 +1,96 @@ +using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; +using System.Text.Json; +using System.Text.Json.Serialization; + +namespace Imagekit.Models.Beta.V2.Files.FileUploadResponseProperties; + +[JsonConverter(typeof(ModelConverter))] +public sealed record class AITag : ModelBase, IFromRaw +{ + /// + /// Confidence score of the tag. + /// + public double? Confidence + { + get + { + if (!this.Properties.TryGetValue("confidence", out JsonElement element)) + return null; + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions); + } + set + { + this.Properties["confidence"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + /// + /// Name of the tag. + /// + public string? Name + { + get + { + if (!this.Properties.TryGetValue("name", out JsonElement element)) + return null; + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions); + } + set + { + this.Properties["name"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + /// + /// Array of `AITags` associated with the image. If no `AITags` are set, it will + /// be null. These tags can be added using the `google-auto-tagging` or `aws-auto-tagging` extensions. + /// + public string? Source + { + get + { + if (!this.Properties.TryGetValue("source", out JsonElement element)) + return null; + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions); + } + set + { + this.Properties["source"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + public override void Validate() + { + _ = this.Confidence; + _ = this.Name; + _ = this.Source; + } + + public AITag() { } + +#pragma warning disable CS8618 + [SetsRequiredMembers] + AITag(Dictionary properties) + { + Properties = properties; + } +#pragma warning restore CS8618 + + public static AITag FromRawUnchecked(Dictionary properties) + { + return new(properties); + } +} diff --git a/src/Imagekit/Models/Beta/V2/Files/FileUploadResponseProperties/ExtensionStatus.cs b/src/Imagekit/Models/Beta/V2/Files/FileUploadResponseProperties/ExtensionStatus.cs new file mode 100644 index 00000000..aeff7b7b --- /dev/null +++ b/src/Imagekit/Models/Beta/V2/Files/FileUploadResponseProperties/ExtensionStatus.cs @@ -0,0 +1,129 @@ +using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; +using System.Text.Json; +using System.Text.Json.Serialization; +using Imagekit.Models.Beta.V2.Files.FileUploadResponseProperties.ExtensionStatusProperties; + +namespace Imagekit.Models.Beta.V2.Files.FileUploadResponseProperties; + +/// +/// Extension names with their processing status at the time of completion of the +/// request. It could have one of the following status values: +/// +/// `success`: The extension has been successfully applied. `failed`: The extension +/// has failed and will not be retried. `pending`: The extension will finish processing +/// in some time. On completion, the final status (success / failed) will be sent +/// to the `webhookUrl` provided. +/// +/// If no extension was requested, then this parameter is not returned. +/// +[JsonConverter(typeof(ModelConverter))] +public sealed record class ExtensionStatus : ModelBase, IFromRaw +{ + public ApiEnum? AIAutoDescription + { + get + { + if (!this.Properties.TryGetValue("ai-auto-description", out JsonElement element)) + return null; + + return JsonSerializer.Deserialize?>( + element, + ModelBase.SerializerOptions + ); + } + set + { + this.Properties["ai-auto-description"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + public ApiEnum? AwsAutoTagging + { + get + { + if (!this.Properties.TryGetValue("aws-auto-tagging", out JsonElement element)) + return null; + + return JsonSerializer.Deserialize?>( + element, + ModelBase.SerializerOptions + ); + } + set + { + this.Properties["aws-auto-tagging"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + public ApiEnum? GoogleAutoTagging + { + get + { + if (!this.Properties.TryGetValue("google-auto-tagging", out JsonElement element)) + return null; + + return JsonSerializer.Deserialize?>( + element, + ModelBase.SerializerOptions + ); + } + set + { + this.Properties["google-auto-tagging"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + public ApiEnum? RemoveBg + { + get + { + if (!this.Properties.TryGetValue("remove-bg", out JsonElement element)) + return null; + + return JsonSerializer.Deserialize?>( + element, + ModelBase.SerializerOptions + ); + } + set + { + this.Properties["remove-bg"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + public override void Validate() + { + this.AIAutoDescription?.Validate(); + this.AwsAutoTagging?.Validate(); + this.GoogleAutoTagging?.Validate(); + this.RemoveBg?.Validate(); + } + + public ExtensionStatus() { } + +#pragma warning disable CS8618 + [SetsRequiredMembers] + ExtensionStatus(Dictionary properties) + { + Properties = properties; + } +#pragma warning restore CS8618 + + public static ExtensionStatus FromRawUnchecked(Dictionary properties) + { + return new(properties); + } +} diff --git a/src/Imagekit/Models/Beta/V2/Files/FileUploadResponseProperties/ExtensionStatusProperties/AIAutoDescription.cs b/src/Imagekit/Models/Beta/V2/Files/FileUploadResponseProperties/ExtensionStatusProperties/AIAutoDescription.cs new file mode 100644 index 00000000..e9577c37 --- /dev/null +++ b/src/Imagekit/Models/Beta/V2/Files/FileUploadResponseProperties/ExtensionStatusProperties/AIAutoDescription.cs @@ -0,0 +1,50 @@ +using System; +using System.Text.Json; +using System.Text.Json.Serialization; + +namespace Imagekit.Models.Beta.V2.Files.FileUploadResponseProperties.ExtensionStatusProperties; + +[JsonConverter(typeof(AIAutoDescriptionConverter))] +public enum AIAutoDescription +{ + Success, + Pending, + Failed, +} + +sealed class AIAutoDescriptionConverter : JsonConverter +{ + public override AIAutoDescription Read( + ref Utf8JsonReader reader, + Type typeToConvert, + JsonSerializerOptions options + ) + { + return JsonSerializer.Deserialize(ref reader, options) switch + { + "success" => AIAutoDescription.Success, + "pending" => AIAutoDescription.Pending, + "failed" => AIAutoDescription.Failed, + _ => (AIAutoDescription)(-1), + }; + } + + public override void Write( + Utf8JsonWriter writer, + AIAutoDescription value, + JsonSerializerOptions options + ) + { + JsonSerializer.Serialize( + writer, + value switch + { + AIAutoDescription.Success => "success", + AIAutoDescription.Pending => "pending", + AIAutoDescription.Failed => "failed", + _ => throw new ArgumentOutOfRangeException(nameof(value)), + }, + options + ); + } +} diff --git a/src/Imagekit/Models/Beta/V2/Files/FileUploadResponseProperties/ExtensionStatusProperties/AwsAutoTagging.cs b/src/Imagekit/Models/Beta/V2/Files/FileUploadResponseProperties/ExtensionStatusProperties/AwsAutoTagging.cs new file mode 100644 index 00000000..43ece216 --- /dev/null +++ b/src/Imagekit/Models/Beta/V2/Files/FileUploadResponseProperties/ExtensionStatusProperties/AwsAutoTagging.cs @@ -0,0 +1,50 @@ +using System; +using System.Text.Json; +using System.Text.Json.Serialization; + +namespace Imagekit.Models.Beta.V2.Files.FileUploadResponseProperties.ExtensionStatusProperties; + +[JsonConverter(typeof(AwsAutoTaggingConverter))] +public enum AwsAutoTagging +{ + Success, + Pending, + Failed, +} + +sealed class AwsAutoTaggingConverter : JsonConverter +{ + public override AwsAutoTagging Read( + ref Utf8JsonReader reader, + Type typeToConvert, + JsonSerializerOptions options + ) + { + return JsonSerializer.Deserialize(ref reader, options) switch + { + "success" => AwsAutoTagging.Success, + "pending" => AwsAutoTagging.Pending, + "failed" => AwsAutoTagging.Failed, + _ => (AwsAutoTagging)(-1), + }; + } + + public override void Write( + Utf8JsonWriter writer, + AwsAutoTagging value, + JsonSerializerOptions options + ) + { + JsonSerializer.Serialize( + writer, + value switch + { + AwsAutoTagging.Success => "success", + AwsAutoTagging.Pending => "pending", + AwsAutoTagging.Failed => "failed", + _ => throw new ArgumentOutOfRangeException(nameof(value)), + }, + options + ); + } +} diff --git a/src/Imagekit/Models/Beta/V2/Files/FileUploadResponseProperties/ExtensionStatusProperties/GoogleAutoTagging.cs b/src/Imagekit/Models/Beta/V2/Files/FileUploadResponseProperties/ExtensionStatusProperties/GoogleAutoTagging.cs new file mode 100644 index 00000000..15da92d3 --- /dev/null +++ b/src/Imagekit/Models/Beta/V2/Files/FileUploadResponseProperties/ExtensionStatusProperties/GoogleAutoTagging.cs @@ -0,0 +1,50 @@ +using System; +using System.Text.Json; +using System.Text.Json.Serialization; + +namespace Imagekit.Models.Beta.V2.Files.FileUploadResponseProperties.ExtensionStatusProperties; + +[JsonConverter(typeof(GoogleAutoTaggingConverter))] +public enum GoogleAutoTagging +{ + Success, + Pending, + Failed, +} + +sealed class GoogleAutoTaggingConverter : JsonConverter +{ + public override GoogleAutoTagging Read( + ref Utf8JsonReader reader, + Type typeToConvert, + JsonSerializerOptions options + ) + { + return JsonSerializer.Deserialize(ref reader, options) switch + { + "success" => GoogleAutoTagging.Success, + "pending" => GoogleAutoTagging.Pending, + "failed" => GoogleAutoTagging.Failed, + _ => (GoogleAutoTagging)(-1), + }; + } + + public override void Write( + Utf8JsonWriter writer, + GoogleAutoTagging value, + JsonSerializerOptions options + ) + { + JsonSerializer.Serialize( + writer, + value switch + { + GoogleAutoTagging.Success => "success", + GoogleAutoTagging.Pending => "pending", + GoogleAutoTagging.Failed => "failed", + _ => throw new ArgumentOutOfRangeException(nameof(value)), + }, + options + ); + } +} diff --git a/src/Imagekit/Models/Beta/V2/Files/FileUploadResponseProperties/ExtensionStatusProperties/RemoveBg.cs b/src/Imagekit/Models/Beta/V2/Files/FileUploadResponseProperties/ExtensionStatusProperties/RemoveBg.cs new file mode 100644 index 00000000..9094a0e5 --- /dev/null +++ b/src/Imagekit/Models/Beta/V2/Files/FileUploadResponseProperties/ExtensionStatusProperties/RemoveBg.cs @@ -0,0 +1,46 @@ +using System; +using System.Text.Json; +using System.Text.Json.Serialization; + +namespace Imagekit.Models.Beta.V2.Files.FileUploadResponseProperties.ExtensionStatusProperties; + +[JsonConverter(typeof(RemoveBgConverter))] +public enum RemoveBg +{ + Success, + Pending, + Failed, +} + +sealed class RemoveBgConverter : JsonConverter +{ + public override RemoveBg Read( + ref Utf8JsonReader reader, + Type typeToConvert, + JsonSerializerOptions options + ) + { + return JsonSerializer.Deserialize(ref reader, options) switch + { + "success" => RemoveBg.Success, + "pending" => RemoveBg.Pending, + "failed" => RemoveBg.Failed, + _ => (RemoveBg)(-1), + }; + } + + public override void Write(Utf8JsonWriter writer, RemoveBg value, JsonSerializerOptions options) + { + JsonSerializer.Serialize( + writer, + value switch + { + RemoveBg.Success => "success", + RemoveBg.Pending => "pending", + RemoveBg.Failed => "failed", + _ => throw new ArgumentOutOfRangeException(nameof(value)), + }, + options + ); + } +} diff --git a/src/Imagekit/Models/Beta/V2/Files/FileUploadResponseProperties/VersionInfo.cs b/src/Imagekit/Models/Beta/V2/Files/FileUploadResponseProperties/VersionInfo.cs new file mode 100644 index 00000000..ee7f3784 --- /dev/null +++ b/src/Imagekit/Models/Beta/V2/Files/FileUploadResponseProperties/VersionInfo.cs @@ -0,0 +1,76 @@ +using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; +using System.Text.Json; +using System.Text.Json.Serialization; + +namespace Imagekit.Models.Beta.V2.Files.FileUploadResponseProperties; + +/// +/// An object containing the file or file version's `id` (versionId) and `name`. +/// +[JsonConverter(typeof(ModelConverter))] +public sealed record class VersionInfo : ModelBase, IFromRaw +{ + /// + /// Unique identifier of the file version. + /// + public string? ID + { + get + { + if (!this.Properties.TryGetValue("id", out JsonElement element)) + return null; + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions); + } + set + { + this.Properties["id"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + /// + /// Name of the file version. + /// + public string? Name + { + get + { + if (!this.Properties.TryGetValue("name", out JsonElement element)) + return null; + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions); + } + set + { + this.Properties["name"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + public override void Validate() + { + _ = this.ID; + _ = this.Name; + } + + public VersionInfo() { } + +#pragma warning disable CS8618 + [SetsRequiredMembers] + VersionInfo(Dictionary properties) + { + Properties = properties; + } +#pragma warning restore CS8618 + + public static VersionInfo FromRawUnchecked(Dictionary properties) + { + return new(properties); + } +} diff --git a/src/Imagekit/Models/Cache/Invalidation/InvalidationCreateParams.cs b/src/Imagekit/Models/Cache/Invalidation/InvalidationCreateParams.cs new file mode 100644 index 00000000..2d4a3cd1 --- /dev/null +++ b/src/Imagekit/Models/Cache/Invalidation/InvalidationCreateParams.cs @@ -0,0 +1,65 @@ +using System; +using System.Collections.Generic; +using System.Net.Http; +using System.Text; +using System.Text.Json; + +namespace Imagekit.Models.Cache.Invalidation; + +/// +/// This API will purge CDN cache and ImageKit.io's internal cache for a file. Note: +/// Purge cache is an asynchronous process and it may take some time to reflect the +/// changes. +/// +public sealed record class InvalidationCreateParams : ParamsBase +{ + public Dictionary BodyProperties { get; set; } = []; + + /// + /// The full URL of the file to be purged. + /// + public required string URL + { + get + { + if (!this.BodyProperties.TryGetValue("url", out JsonElement element)) + throw new ArgumentOutOfRangeException("url", "Missing required argument"); + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions) + ?? throw new ArgumentNullException("url"); + } + set + { + this.BodyProperties["url"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + public override Uri Url(IImageKitClient client) + { + return new UriBuilder(client.BaseUrl.ToString().TrimEnd('/') + "/v1/files/purge") + { + Query = this.QueryString(client), + }.Uri; + } + + public StringContent BodyContent() + { + return new( + JsonSerializer.Serialize(this.BodyProperties), + Encoding.UTF8, + "application/json" + ); + } + + public void AddHeadersToRequest(HttpRequestMessage request, IImageKitClient client) + { + ParamsBase.AddDefaultHeaders(request, client); + foreach (var item in this.HeaderProperties) + { + ParamsBase.AddHeaderElementToRequest(request, item.Key, item.Value); + } + } +} diff --git a/src/Imagekit/Models/Cache/Invalidation/InvalidationCreateResponse.cs b/src/Imagekit/Models/Cache/Invalidation/InvalidationCreateResponse.cs new file mode 100644 index 00000000..3fa13c55 --- /dev/null +++ b/src/Imagekit/Models/Cache/Invalidation/InvalidationCreateResponse.cs @@ -0,0 +1,56 @@ +using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; +using System.Text.Json; +using System.Text.Json.Serialization; + +namespace Imagekit.Models.Cache.Invalidation; + +[JsonConverter(typeof(ModelConverter))] +public sealed record class InvalidationCreateResponse + : ModelBase, + IFromRaw +{ + /// + /// Unique identifier of the purge request. This can be used to check the status + /// of the purge request. + /// + public string? RequestID + { + get + { + if (!this.Properties.TryGetValue("requestId", out JsonElement element)) + return null; + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions); + } + set + { + this.Properties["requestId"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + public override void Validate() + { + _ = this.RequestID; + } + + public InvalidationCreateResponse() { } + +#pragma warning disable CS8618 + [SetsRequiredMembers] + InvalidationCreateResponse(Dictionary properties) + { + Properties = properties; + } +#pragma warning restore CS8618 + + public static InvalidationCreateResponse FromRawUnchecked( + Dictionary properties + ) + { + return new(properties); + } +} diff --git a/src/Imagekit/Models/Cache/Invalidation/InvalidationGetParams.cs b/src/Imagekit/Models/Cache/Invalidation/InvalidationGetParams.cs new file mode 100644 index 00000000..b856615c --- /dev/null +++ b/src/Imagekit/Models/Cache/Invalidation/InvalidationGetParams.cs @@ -0,0 +1,32 @@ +using System; +using System.Net.Http; + +namespace Imagekit.Models.Cache.Invalidation; + +/// +/// This API returns the status of a purge cache request. +/// +public sealed record class InvalidationGetParams : ParamsBase +{ + public required string RequestID; + + public override Uri Url(IImageKitClient client) + { + return new UriBuilder( + client.BaseUrl.ToString().TrimEnd('/') + + string.Format("/v1/files/purge/{0}", this.RequestID) + ) + { + Query = this.QueryString(client), + }.Uri; + } + + public void AddHeadersToRequest(HttpRequestMessage request, IImageKitClient client) + { + ParamsBase.AddDefaultHeaders(request, client); + foreach (var item in this.HeaderProperties) + { + ParamsBase.AddHeaderElementToRequest(request, item.Key, item.Value); + } + } +} diff --git a/src/Imagekit/Models/Cache/Invalidation/InvalidationGetResponse.cs b/src/Imagekit/Models/Cache/Invalidation/InvalidationGetResponse.cs new file mode 100644 index 00000000..a61b3779 --- /dev/null +++ b/src/Imagekit/Models/Cache/Invalidation/InvalidationGetResponse.cs @@ -0,0 +1,57 @@ +using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; +using System.Text.Json; +using System.Text.Json.Serialization; +using Imagekit.Models.Cache.Invalidation.InvalidationGetResponseProperties; + +namespace Imagekit.Models.Cache.Invalidation; + +[JsonConverter(typeof(ModelConverter))] +public sealed record class InvalidationGetResponse : ModelBase, IFromRaw +{ + /// + /// Status of the purge request. + /// + public ApiEnum? Status + { + get + { + if (!this.Properties.TryGetValue("status", out JsonElement element)) + return null; + + return JsonSerializer.Deserialize?>( + element, + ModelBase.SerializerOptions + ); + } + set + { + this.Properties["status"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + public override void Validate() + { + this.Status?.Validate(); + } + + public InvalidationGetResponse() { } + +#pragma warning disable CS8618 + [SetsRequiredMembers] + InvalidationGetResponse(Dictionary properties) + { + Properties = properties; + } +#pragma warning restore CS8618 + + public static InvalidationGetResponse FromRawUnchecked( + Dictionary properties + ) + { + return new(properties); + } +} diff --git a/src/Imagekit/Models/Cache/Invalidation/InvalidationGetResponseProperties/Status.cs b/src/Imagekit/Models/Cache/Invalidation/InvalidationGetResponseProperties/Status.cs new file mode 100644 index 00000000..1760eb98 --- /dev/null +++ b/src/Imagekit/Models/Cache/Invalidation/InvalidationGetResponseProperties/Status.cs @@ -0,0 +1,46 @@ +using System; +using System.Text.Json; +using System.Text.Json.Serialization; + +namespace Imagekit.Models.Cache.Invalidation.InvalidationGetResponseProperties; + +/// +/// Status of the purge request. +/// +[JsonConverter(typeof(StatusConverter))] +public enum Status +{ + Pending, + Completed, +} + +sealed class StatusConverter : JsonConverter +{ + public override Status Read( + ref Utf8JsonReader reader, + Type typeToConvert, + JsonSerializerOptions options + ) + { + return JsonSerializer.Deserialize(ref reader, options) switch + { + "Pending" => Status.Pending, + "Completed" => Status.Completed, + _ => (Status)(-1), + }; + } + + public override void Write(Utf8JsonWriter writer, Status value, JsonSerializerOptions options) + { + JsonSerializer.Serialize( + writer, + value switch + { + Status.Pending => "Pending", + Status.Completed => "Completed", + _ => throw new ArgumentOutOfRangeException(nameof(value)), + }, + options + ); + } +} diff --git a/src/Imagekit/Models/CustomMetadataFields/CustomMetadataField.cs b/src/Imagekit/Models/CustomMetadataFields/CustomMetadataField.cs new file mode 100644 index 00000000..a270845e --- /dev/null +++ b/src/Imagekit/Models/CustomMetadataFields/CustomMetadataField.cs @@ -0,0 +1,129 @@ +using System; +using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; +using System.Text.Json; +using System.Text.Json.Serialization; +using Imagekit.Models.CustomMetadataFields.CustomMetadataFieldProperties; + +namespace Imagekit.Models.CustomMetadataFields; + +/// +/// Object containing details of a custom metadata field. +/// +[JsonConverter(typeof(ModelConverter))] +public sealed record class CustomMetadataField : ModelBase, IFromRaw +{ + /// + /// Unique identifier for the custom metadata field. Use this to update the field. + /// + public required string ID + { + get + { + if (!this.Properties.TryGetValue("id", out JsonElement element)) + throw new ArgumentOutOfRangeException("id", "Missing required argument"); + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions) + ?? throw new ArgumentNullException("id"); + } + set + { + this.Properties["id"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + /// + /// Human readable name of the custom metadata field. This name is displayed as + /// form field label to the users while setting field value on the asset in the + /// media library UI. + /// + public required string Label + { + get + { + if (!this.Properties.TryGetValue("label", out JsonElement element)) + throw new ArgumentOutOfRangeException("label", "Missing required argument"); + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions) + ?? throw new ArgumentNullException("label"); + } + set + { + this.Properties["label"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + /// + /// API name of the custom metadata field. This becomes the key while setting + /// `customMetadata` (key-value object) for an asset using upload or update API. + /// + public required string Name + { + get + { + if (!this.Properties.TryGetValue("name", out JsonElement element)) + throw new ArgumentOutOfRangeException("name", "Missing required argument"); + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions) + ?? throw new ArgumentNullException("name"); + } + set + { + this.Properties["name"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + /// + /// An object that describes the rules for the custom metadata field value. + /// + public required Schema Schema + { + get + { + if (!this.Properties.TryGetValue("schema", out JsonElement element)) + throw new ArgumentOutOfRangeException("schema", "Missing required argument"); + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions) + ?? throw new ArgumentNullException("schema"); + } + set + { + this.Properties["schema"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + public override void Validate() + { + _ = this.ID; + _ = this.Label; + _ = this.Name; + this.Schema.Validate(); + } + + public CustomMetadataField() { } + +#pragma warning disable CS8618 + [SetsRequiredMembers] + CustomMetadataField(Dictionary properties) + { + Properties = properties; + } +#pragma warning restore CS8618 + + public static CustomMetadataField FromRawUnchecked(Dictionary properties) + { + return new(properties); + } +} diff --git a/src/Imagekit/Models/CustomMetadataFields/CustomMetadataFieldCreateParams.cs b/src/Imagekit/Models/CustomMetadataFields/CustomMetadataFieldCreateParams.cs new file mode 100644 index 00000000..3b0d94e6 --- /dev/null +++ b/src/Imagekit/Models/CustomMetadataFields/CustomMetadataFieldCreateParams.cs @@ -0,0 +1,111 @@ +using System; +using System.Collections.Generic; +using System.Net.Http; +using System.Text; +using System.Text.Json; +using Imagekit.Models.CustomMetadataFields.CustomMetadataFieldCreateParamsProperties; + +namespace Imagekit.Models.CustomMetadataFields; + +/// +/// This API creates a new custom metadata field. Once a custom metadata field is +/// created either through this API or using the dashboard UI, its value can be set +/// on the assets. The value of a field for an asset can be set using the media library +/// UI or programmatically through upload or update assets API. +/// +public sealed record class CustomMetadataFieldCreateParams : ParamsBase +{ + public Dictionary BodyProperties { get; set; } = []; + + /// + /// Human readable name of the custom metadata field. This should be unique across + /// all non deleted custom metadata fields. This name is displayed as form field + /// label to the users while setting field value on an asset in the media library UI. + /// + public required string Label + { + get + { + if (!this.BodyProperties.TryGetValue("label", out JsonElement element)) + throw new ArgumentOutOfRangeException("label", "Missing required argument"); + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions) + ?? throw new ArgumentNullException("label"); + } + set + { + this.BodyProperties["label"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + /// + /// API name of the custom metadata field. This should be unique across all (including + /// deleted) custom metadata fields. + /// + public required string Name + { + get + { + if (!this.BodyProperties.TryGetValue("name", out JsonElement element)) + throw new ArgumentOutOfRangeException("name", "Missing required argument"); + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions) + ?? throw new ArgumentNullException("name"); + } + set + { + this.BodyProperties["name"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + public required Schema Schema + { + get + { + if (!this.BodyProperties.TryGetValue("schema", out JsonElement element)) + throw new ArgumentOutOfRangeException("schema", "Missing required argument"); + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions) + ?? throw new ArgumentNullException("schema"); + } + set + { + this.BodyProperties["schema"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + public override Uri Url(IImageKitClient client) + { + return new UriBuilder(client.BaseUrl.ToString().TrimEnd('/') + "/v1/customMetadataFields") + { + Query = this.QueryString(client), + }.Uri; + } + + public StringContent BodyContent() + { + return new( + JsonSerializer.Serialize(this.BodyProperties), + Encoding.UTF8, + "application/json" + ); + } + + public void AddHeadersToRequest(HttpRequestMessage request, IImageKitClient client) + { + ParamsBase.AddDefaultHeaders(request, client); + foreach (var item in this.HeaderProperties) + { + ParamsBase.AddHeaderElementToRequest(request, item.Key, item.Value); + } + } +} diff --git a/src/Imagekit/Models/CustomMetadataFields/CustomMetadataFieldCreateParamsProperties/Schema.cs b/src/Imagekit/Models/CustomMetadataFields/CustomMetadataFieldCreateParamsProperties/Schema.cs new file mode 100644 index 00000000..04cbce16 --- /dev/null +++ b/src/Imagekit/Models/CustomMetadataFields/CustomMetadataFieldCreateParamsProperties/Schema.cs @@ -0,0 +1,243 @@ +using System; +using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; +using System.Text.Json; +using System.Text.Json.Serialization; +using SchemaProperties = Imagekit.Models.CustomMetadataFields.CustomMetadataFieldCreateParamsProperties.SchemaProperties; + +namespace Imagekit.Models.CustomMetadataFields.CustomMetadataFieldCreateParamsProperties; + +[JsonConverter(typeof(ModelConverter))] +public sealed record class Schema : ModelBase, IFromRaw +{ + /// + /// Type of the custom metadata field. + /// + public required ApiEnum Type + { + get + { + if (!this.Properties.TryGetValue("type", out JsonElement element)) + throw new ArgumentOutOfRangeException("type", "Missing required argument"); + + return JsonSerializer.Deserialize>( + element, + ModelBase.SerializerOptions + ); + } + set + { + this.Properties["type"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + /// + /// The default value for this custom metadata field. This property is only required + /// if `isValueRequired` property is set to `true`. The value should match the + /// `type` of custom metadata field. + /// + public SchemaProperties::DefaultValue? DefaultValue + { + get + { + if (!this.Properties.TryGetValue("defaultValue", out JsonElement element)) + return null; + + return JsonSerializer.Deserialize( + element, + ModelBase.SerializerOptions + ); + } + set + { + this.Properties["defaultValue"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + /// + /// Sets this custom metadata field as required. Setting custom metadata fields + /// on an asset will throw error if the value for all required fields are not + /// present in upload or update asset API request body. + /// + public bool? IsValueRequired + { + get + { + if (!this.Properties.TryGetValue("isValueRequired", out JsonElement element)) + return null; + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions); + } + set + { + this.Properties["isValueRequired"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + /// + /// Maximum length of string. Only set this property if `type` is set to `Text` + /// or `Textarea`. + /// + public double? MaxLength + { + get + { + if (!this.Properties.TryGetValue("maxLength", out JsonElement element)) + return null; + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions); + } + set + { + this.Properties["maxLength"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + /// + /// Maximum value of the field. Only set this property if field type is `Date` + /// or `Number`. For `Date` type field, set the minimum date in ISO8601 string + /// format. For `Number` type field, set the minimum numeric value. + /// + public SchemaProperties::MaxValue? MaxValue + { + get + { + if (!this.Properties.TryGetValue("maxValue", out JsonElement element)) + return null; + + return JsonSerializer.Deserialize( + element, + ModelBase.SerializerOptions + ); + } + set + { + this.Properties["maxValue"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + /// + /// Minimum length of string. Only set this property if `type` is set to `Text` + /// or `Textarea`. + /// + public double? MinLength + { + get + { + if (!this.Properties.TryGetValue("minLength", out JsonElement element)) + return null; + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions); + } + set + { + this.Properties["minLength"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + /// + /// Minimum value of the field. Only set this property if field type is `Date` + /// or `Number`. For `Date` type field, set the minimum date in ISO8601 string + /// format. For `Number` type field, set the minimum numeric value. + /// + public SchemaProperties::MinValue? MinValue + { + get + { + if (!this.Properties.TryGetValue("minValue", out JsonElement element)) + return null; + + return JsonSerializer.Deserialize( + element, + ModelBase.SerializerOptions + ); + } + set + { + this.Properties["minValue"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + /// + /// An array of allowed values. This property is only required if `type` property + /// is set to `SingleSelect` or `MultiSelect`. + /// + public List? SelectOptions + { + get + { + if (!this.Properties.TryGetValue("selectOptions", out JsonElement element)) + return null; + + return JsonSerializer.Deserialize?>( + element, + ModelBase.SerializerOptions + ); + } + set + { + this.Properties["selectOptions"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + public override void Validate() + { + this.Type.Validate(); + this.DefaultValue?.Validate(); + _ = this.IsValueRequired; + _ = this.MaxLength; + this.MaxValue?.Validate(); + _ = this.MinLength; + this.MinValue?.Validate(); + foreach (var item in this.SelectOptions ?? []) + { + item.Validate(); + } + } + + public Schema() { } + +#pragma warning disable CS8618 + [SetsRequiredMembers] + Schema(Dictionary properties) + { + Properties = properties; + } +#pragma warning restore CS8618 + + public static Schema FromRawUnchecked(Dictionary properties) + { + return new(properties); + } + + [SetsRequiredMembers] + public Schema(ApiEnum type) + : this() + { + this.Type = type; + } +} diff --git a/src/Imagekit/Models/CustomMetadataFields/CustomMetadataFieldCreateParamsProperties/SchemaProperties/DefaultValue.cs b/src/Imagekit/Models/CustomMetadataFields/CustomMetadataFieldCreateParamsProperties/SchemaProperties/DefaultValue.cs new file mode 100644 index 00000000..d18ab6d2 --- /dev/null +++ b/src/Imagekit/Models/CustomMetadataFields/CustomMetadataFieldCreateParamsProperties/SchemaProperties/DefaultValue.cs @@ -0,0 +1,176 @@ +using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; +using System.Text.Json; +using System.Text.Json.Serialization; +using Imagekit.Models.CustomMetadataFields.CustomMetadataFieldCreateParamsProperties.SchemaProperties.DefaultValueProperties; +using Imagekit.Models.CustomMetadataFields.CustomMetadataFieldCreateParamsProperties.SchemaProperties.DefaultValueVariants; +using System = System; + +namespace Imagekit.Models.CustomMetadataFields.CustomMetadataFieldCreateParamsProperties.SchemaProperties; + +/// +/// The default value for this custom metadata field. This property is only required +/// if `isValueRequired` property is set to `true`. The value should match the `type` +/// of custom metadata field. +/// +[JsonConverter(typeof(DefaultValueConverter))] +public abstract record class DefaultValue +{ + internal DefaultValue() { } + + public static implicit operator DefaultValue(string value) => new String(value); + + public static implicit operator DefaultValue(double value) => new Double(value); + + public static implicit operator DefaultValue(bool value) => new Bool(value); + + public static implicit operator DefaultValue(List value) => + new Mixed(value); + + public bool TryPickString([NotNullWhen(true)] out string? value) + { + value = (this as String)?.Value; + return value != null; + } + + public bool TryPickDouble([NotNullWhen(true)] out double? value) + { + value = (this as Double)?.Value; + return value != null; + } + + public bool TryPickBool([NotNullWhen(true)] out bool? value) + { + value = (this as Bool)?.Value; + return value != null; + } + + public bool TryPickMixed([NotNullWhen(true)] out List? value) + { + value = (this as Mixed)?.Value; + return value != null; + } + + public void Switch( + System::Action @string, + System::Action @double, + System::Action @bool, + System::Action mixed + ) + { + switch (this) + { + case String inner: + @string(inner); + break; + case Double inner: + @double(inner); + break; + case Bool inner: + @bool(inner); + break; + case Mixed inner: + mixed(inner); + break; + default: + throw new System::InvalidOperationException(); + } + } + + public T Match( + System::Func @string, + System::Func @double, + System::Func @bool, + System::Func mixed + ) + { + return this switch + { + String inner => @string(inner), + Double inner => @double(inner), + Bool inner => @bool(inner), + Mixed inner => mixed(inner), + _ => throw new System::InvalidOperationException(), + }; + } + + public abstract void Validate(); +} + +sealed class DefaultValueConverter : JsonConverter +{ + public override DefaultValue? Read( + ref Utf8JsonReader reader, + System::Type typeToConvert, + JsonSerializerOptions options + ) + { + List exceptions = []; + + try + { + var deserialized = JsonSerializer.Deserialize(ref reader, options); + if (deserialized != null) + { + return new String(deserialized); + } + } + catch (JsonException e) + { + exceptions.Add(e); + } + + try + { + return new Double(JsonSerializer.Deserialize(ref reader, options)); + } + catch (JsonException e) + { + exceptions.Add(e); + } + + try + { + return new Bool(JsonSerializer.Deserialize(ref reader, options)); + } + catch (JsonException e) + { + exceptions.Add(e); + } + + try + { + var deserialized = JsonSerializer.Deserialize>( + ref reader, + options + ); + if (deserialized != null) + { + return new Mixed(deserialized); + } + } + catch (JsonException e) + { + exceptions.Add(e); + } + + throw new System::AggregateException(exceptions); + } + + public override void Write( + Utf8JsonWriter writer, + DefaultValue value, + JsonSerializerOptions options + ) + { + object variant = value switch + { + String(var @string) => @string, + Double(var @double) => @double, + Bool(var @bool) => @bool, + Mixed(var mixed) => mixed, + _ => throw new System::ArgumentOutOfRangeException(nameof(value)), + }; + JsonSerializer.Serialize(writer, variant, options); + } +} diff --git a/src/Imagekit/Models/CustomMetadataFields/CustomMetadataFieldCreateParamsProperties/SchemaProperties/DefaultValueProperties/UnnamedSchemaWithArrayParent1.cs b/src/Imagekit/Models/CustomMetadataFields/CustomMetadataFieldCreateParamsProperties/SchemaProperties/DefaultValueProperties/UnnamedSchemaWithArrayParent1.cs new file mode 100644 index 00000000..aa9e002a --- /dev/null +++ b/src/Imagekit/Models/CustomMetadataFields/CustomMetadataFieldCreateParamsProperties/SchemaProperties/DefaultValueProperties/UnnamedSchemaWithArrayParent1.cs @@ -0,0 +1,140 @@ +using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; +using System.Text.Json; +using System.Text.Json.Serialization; +using Imagekit.Models.CustomMetadataFields.CustomMetadataFieldCreateParamsProperties.SchemaProperties.DefaultValueProperties.UnnamedSchemaWithArrayParent1Variants; +using System = System; + +namespace Imagekit.Models.CustomMetadataFields.CustomMetadataFieldCreateParamsProperties.SchemaProperties.DefaultValueProperties; + +[JsonConverter(typeof(UnnamedSchemaWithArrayParent1Converter))] +public abstract record class UnnamedSchemaWithArrayParent1 +{ + internal UnnamedSchemaWithArrayParent1() { } + + public static implicit operator UnnamedSchemaWithArrayParent1(string value) => + new String(value); + + public static implicit operator UnnamedSchemaWithArrayParent1(double value) => + new Double(value); + + public static implicit operator UnnamedSchemaWithArrayParent1(bool value) => new Bool(value); + + public bool TryPickString([NotNullWhen(true)] out string? value) + { + value = (this as String)?.Value; + return value != null; + } + + public bool TryPickDouble([NotNullWhen(true)] out double? value) + { + value = (this as Double)?.Value; + return value != null; + } + + public bool TryPickBool([NotNullWhen(true)] out bool? value) + { + value = (this as Bool)?.Value; + return value != null; + } + + public void Switch( + System::Action @string, + System::Action @double, + System::Action @bool + ) + { + switch (this) + { + case String inner: + @string(inner); + break; + case Double inner: + @double(inner); + break; + case Bool inner: + @bool(inner); + break; + default: + throw new System::InvalidOperationException(); + } + } + + public T Match( + System::Func @string, + System::Func @double, + System::Func @bool + ) + { + return this switch + { + String inner => @string(inner), + Double inner => @double(inner), + Bool inner => @bool(inner), + _ => throw new System::InvalidOperationException(), + }; + } + + public abstract void Validate(); +} + +sealed class UnnamedSchemaWithArrayParent1Converter : JsonConverter +{ + public override UnnamedSchemaWithArrayParent1? Read( + ref Utf8JsonReader reader, + System::Type typeToConvert, + JsonSerializerOptions options + ) + { + List exceptions = []; + + try + { + var deserialized = JsonSerializer.Deserialize(ref reader, options); + if (deserialized != null) + { + return new String(deserialized); + } + } + catch (JsonException e) + { + exceptions.Add(e); + } + + try + { + return new Double(JsonSerializer.Deserialize(ref reader, options)); + } + catch (JsonException e) + { + exceptions.Add(e); + } + + try + { + return new Bool(JsonSerializer.Deserialize(ref reader, options)); + } + catch (JsonException e) + { + exceptions.Add(e); + } + + throw new System::AggregateException(exceptions); + } + + public override void Write( + Utf8JsonWriter writer, + UnnamedSchemaWithArrayParent1 value, + JsonSerializerOptions options + ) + { + object variant = value switch + { + String(var @string) => @string, + Double(var @double) => @double, + Bool(var @bool) => @bool, + _ => throw new System::ArgumentOutOfRangeException(nameof(value)), + }; + JsonSerializer.Serialize(writer, variant, options); + } +} diff --git a/src/Imagekit/Models/CustomMetadataFields/CustomMetadataFieldCreateParamsProperties/SchemaProperties/DefaultValueProperties/UnnamedSchemaWithArrayParent1Variants/All.cs b/src/Imagekit/Models/CustomMetadataFields/CustomMetadataFieldCreateParamsProperties/SchemaProperties/DefaultValueProperties/UnnamedSchemaWithArrayParent1Variants/All.cs new file mode 100644 index 00000000..9bde8ea7 --- /dev/null +++ b/src/Imagekit/Models/CustomMetadataFields/CustomMetadataFieldCreateParamsProperties/SchemaProperties/DefaultValueProperties/UnnamedSchemaWithArrayParent1Variants/All.cs @@ -0,0 +1,35 @@ +namespace Imagekit.Models.CustomMetadataFields.CustomMetadataFieldCreateParamsProperties.SchemaProperties.DefaultValueProperties.UnnamedSchemaWithArrayParent1Variants; + +public sealed record class String(string Value) + : UnnamedSchemaWithArrayParent1, + IVariant +{ + public static String From(string value) + { + return new(value); + } + + public override void Validate() { } +} + +public sealed record class Double(double Value) + : UnnamedSchemaWithArrayParent1, + IVariant +{ + public static Double From(double value) + { + return new(value); + } + + public override void Validate() { } +} + +public sealed record class Bool(bool Value) : UnnamedSchemaWithArrayParent1, IVariant +{ + public static Bool From(bool value) + { + return new(value); + } + + public override void Validate() { } +} diff --git a/src/Imagekit/Models/CustomMetadataFields/CustomMetadataFieldCreateParamsProperties/SchemaProperties/DefaultValueVariants/All.cs b/src/Imagekit/Models/CustomMetadataFields/CustomMetadataFieldCreateParamsProperties/SchemaProperties/DefaultValueVariants/All.cs new file mode 100644 index 00000000..43c33479 --- /dev/null +++ b/src/Imagekit/Models/CustomMetadataFields/CustomMetadataFieldCreateParamsProperties/SchemaProperties/DefaultValueVariants/All.cs @@ -0,0 +1,50 @@ +using System.Collections.Generic; +using Imagekit.Models.CustomMetadataFields.CustomMetadataFieldCreateParamsProperties.SchemaProperties.DefaultValueProperties; + +namespace Imagekit.Models.CustomMetadataFields.CustomMetadataFieldCreateParamsProperties.SchemaProperties.DefaultValueVariants; + +public sealed record class String(string Value) : DefaultValue, IVariant +{ + public static String From(string value) + { + return new(value); + } + + public override void Validate() { } +} + +public sealed record class Double(double Value) : DefaultValue, IVariant +{ + public static Double From(double value) + { + return new(value); + } + + public override void Validate() { } +} + +public sealed record class Bool(bool Value) : DefaultValue, IVariant +{ + public static Bool From(bool value) + { + return new(value); + } + + public override void Validate() { } +} + +/// +/// Default value should be of type array when custom metadata field type is set to +/// `MultiSelect`. +/// +public sealed record class Mixed(List Value) + : DefaultValue, + IVariant> +{ + public static Mixed From(List value) + { + return new(value); + } + + public override void Validate() { } +} diff --git a/src/Imagekit/Models/CustomMetadataFields/CustomMetadataFieldCreateParamsProperties/SchemaProperties/MaxValue.cs b/src/Imagekit/Models/CustomMetadataFields/CustomMetadataFieldCreateParamsProperties/SchemaProperties/MaxValue.cs new file mode 100644 index 00000000..0928aece --- /dev/null +++ b/src/Imagekit/Models/CustomMetadataFields/CustomMetadataFieldCreateParamsProperties/SchemaProperties/MaxValue.cs @@ -0,0 +1,109 @@ +using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; +using System.Text.Json; +using System.Text.Json.Serialization; +using Imagekit.Models.CustomMetadataFields.CustomMetadataFieldCreateParamsProperties.SchemaProperties.MaxValueVariants; +using System = System; + +namespace Imagekit.Models.CustomMetadataFields.CustomMetadataFieldCreateParamsProperties.SchemaProperties; + +/// +/// Maximum value of the field. Only set this property if field type is `Date` or +/// `Number`. For `Date` type field, set the minimum date in ISO8601 string format. +/// For `Number` type field, set the minimum numeric value. +/// +[JsonConverter(typeof(MaxValueConverter))] +public abstract record class MaxValue +{ + internal MaxValue() { } + + public static implicit operator MaxValue(string value) => new String(value); + + public static implicit operator MaxValue(double value) => new Double(value); + + public bool TryPickString([NotNullWhen(true)] out string? value) + { + value = (this as String)?.Value; + return value != null; + } + + public bool TryPickDouble([NotNullWhen(true)] out double? value) + { + value = (this as Double)?.Value; + return value != null; + } + + public void Switch(System::Action @string, System::Action @double) + { + switch (this) + { + case String inner: + @string(inner); + break; + case Double inner: + @double(inner); + break; + default: + throw new System::InvalidOperationException(); + } + } + + public T Match(System::Func @string, System::Func @double) + { + return this switch + { + String inner => @string(inner), + Double inner => @double(inner), + _ => throw new System::InvalidOperationException(), + }; + } + + public abstract void Validate(); +} + +sealed class MaxValueConverter : JsonConverter +{ + public override MaxValue? Read( + ref Utf8JsonReader reader, + System::Type typeToConvert, + JsonSerializerOptions options + ) + { + List exceptions = []; + + try + { + var deserialized = JsonSerializer.Deserialize(ref reader, options); + if (deserialized != null) + { + return new String(deserialized); + } + } + catch (JsonException e) + { + exceptions.Add(e); + } + + try + { + return new Double(JsonSerializer.Deserialize(ref reader, options)); + } + catch (JsonException e) + { + exceptions.Add(e); + } + + throw new System::AggregateException(exceptions); + } + + public override void Write(Utf8JsonWriter writer, MaxValue value, JsonSerializerOptions options) + { + object variant = value switch + { + String(var @string) => @string, + Double(var @double) => @double, + _ => throw new System::ArgumentOutOfRangeException(nameof(value)), + }; + JsonSerializer.Serialize(writer, variant, options); + } +} diff --git a/src/Imagekit/Models/CustomMetadataFields/CustomMetadataFieldCreateParamsProperties/SchemaProperties/MaxValueVariants/All.cs b/src/Imagekit/Models/CustomMetadataFields/CustomMetadataFieldCreateParamsProperties/SchemaProperties/MaxValueVariants/All.cs new file mode 100644 index 00000000..0702732b --- /dev/null +++ b/src/Imagekit/Models/CustomMetadataFields/CustomMetadataFieldCreateParamsProperties/SchemaProperties/MaxValueVariants/All.cs @@ -0,0 +1,21 @@ +namespace Imagekit.Models.CustomMetadataFields.CustomMetadataFieldCreateParamsProperties.SchemaProperties.MaxValueVariants; + +public sealed record class String(string Value) : MaxValue, IVariant +{ + public static String From(string value) + { + return new(value); + } + + public override void Validate() { } +} + +public sealed record class Double(double Value) : MaxValue, IVariant +{ + public static Double From(double value) + { + return new(value); + } + + public override void Validate() { } +} diff --git a/src/Imagekit/Models/CustomMetadataFields/CustomMetadataFieldCreateParamsProperties/SchemaProperties/MinValue.cs b/src/Imagekit/Models/CustomMetadataFields/CustomMetadataFieldCreateParamsProperties/SchemaProperties/MinValue.cs new file mode 100644 index 00000000..ccce54d0 --- /dev/null +++ b/src/Imagekit/Models/CustomMetadataFields/CustomMetadataFieldCreateParamsProperties/SchemaProperties/MinValue.cs @@ -0,0 +1,109 @@ +using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; +using System.Text.Json; +using System.Text.Json.Serialization; +using Imagekit.Models.CustomMetadataFields.CustomMetadataFieldCreateParamsProperties.SchemaProperties.MinValueVariants; +using System = System; + +namespace Imagekit.Models.CustomMetadataFields.CustomMetadataFieldCreateParamsProperties.SchemaProperties; + +/// +/// Minimum value of the field. Only set this property if field type is `Date` or +/// `Number`. For `Date` type field, set the minimum date in ISO8601 string format. +/// For `Number` type field, set the minimum numeric value. +/// +[JsonConverter(typeof(MinValueConverter))] +public abstract record class MinValue +{ + internal MinValue() { } + + public static implicit operator MinValue(string value) => new String(value); + + public static implicit operator MinValue(double value) => new Double(value); + + public bool TryPickString([NotNullWhen(true)] out string? value) + { + value = (this as String)?.Value; + return value != null; + } + + public bool TryPickDouble([NotNullWhen(true)] out double? value) + { + value = (this as Double)?.Value; + return value != null; + } + + public void Switch(System::Action @string, System::Action @double) + { + switch (this) + { + case String inner: + @string(inner); + break; + case Double inner: + @double(inner); + break; + default: + throw new System::InvalidOperationException(); + } + } + + public T Match(System::Func @string, System::Func @double) + { + return this switch + { + String inner => @string(inner), + Double inner => @double(inner), + _ => throw new System::InvalidOperationException(), + }; + } + + public abstract void Validate(); +} + +sealed class MinValueConverter : JsonConverter +{ + public override MinValue? Read( + ref Utf8JsonReader reader, + System::Type typeToConvert, + JsonSerializerOptions options + ) + { + List exceptions = []; + + try + { + var deserialized = JsonSerializer.Deserialize(ref reader, options); + if (deserialized != null) + { + return new String(deserialized); + } + } + catch (JsonException e) + { + exceptions.Add(e); + } + + try + { + return new Double(JsonSerializer.Deserialize(ref reader, options)); + } + catch (JsonException e) + { + exceptions.Add(e); + } + + throw new System::AggregateException(exceptions); + } + + public override void Write(Utf8JsonWriter writer, MinValue value, JsonSerializerOptions options) + { + object variant = value switch + { + String(var @string) => @string, + Double(var @double) => @double, + _ => throw new System::ArgumentOutOfRangeException(nameof(value)), + }; + JsonSerializer.Serialize(writer, variant, options); + } +} diff --git a/src/Imagekit/Models/CustomMetadataFields/CustomMetadataFieldCreateParamsProperties/SchemaProperties/MinValueVariants/All.cs b/src/Imagekit/Models/CustomMetadataFields/CustomMetadataFieldCreateParamsProperties/SchemaProperties/MinValueVariants/All.cs new file mode 100644 index 00000000..94c0c48b --- /dev/null +++ b/src/Imagekit/Models/CustomMetadataFields/CustomMetadataFieldCreateParamsProperties/SchemaProperties/MinValueVariants/All.cs @@ -0,0 +1,21 @@ +namespace Imagekit.Models.CustomMetadataFields.CustomMetadataFieldCreateParamsProperties.SchemaProperties.MinValueVariants; + +public sealed record class String(string Value) : MinValue, IVariant +{ + public static String From(string value) + { + return new(value); + } + + public override void Validate() { } +} + +public sealed record class Double(double Value) : MinValue, IVariant +{ + public static Double From(double value) + { + return new(value); + } + + public override void Validate() { } +} diff --git a/src/Imagekit/Models/CustomMetadataFields/CustomMetadataFieldCreateParamsProperties/SchemaProperties/SelectOption.cs b/src/Imagekit/Models/CustomMetadataFields/CustomMetadataFieldCreateParamsProperties/SchemaProperties/SelectOption.cs new file mode 100644 index 00000000..b217c981 --- /dev/null +++ b/src/Imagekit/Models/CustomMetadataFields/CustomMetadataFieldCreateParamsProperties/SchemaProperties/SelectOption.cs @@ -0,0 +1,138 @@ +using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; +using System.Text.Json; +using System.Text.Json.Serialization; +using Imagekit.Models.CustomMetadataFields.CustomMetadataFieldCreateParamsProperties.SchemaProperties.SelectOptionVariants; +using System = System; + +namespace Imagekit.Models.CustomMetadataFields.CustomMetadataFieldCreateParamsProperties.SchemaProperties; + +[JsonConverter(typeof(SelectOptionConverter))] +public abstract record class SelectOption +{ + internal SelectOption() { } + + public static implicit operator SelectOption(string value) => new String(value); + + public static implicit operator SelectOption(double value) => new Double(value); + + public static implicit operator SelectOption(bool value) => new Bool(value); + + public bool TryPickString([NotNullWhen(true)] out string? value) + { + value = (this as String)?.Value; + return value != null; + } + + public bool TryPickDouble([NotNullWhen(true)] out double? value) + { + value = (this as Double)?.Value; + return value != null; + } + + public bool TryPickBool([NotNullWhen(true)] out bool? value) + { + value = (this as Bool)?.Value; + return value != null; + } + + public void Switch( + System::Action @string, + System::Action @double, + System::Action @bool + ) + { + switch (this) + { + case String inner: + @string(inner); + break; + case Double inner: + @double(inner); + break; + case Bool inner: + @bool(inner); + break; + default: + throw new System::InvalidOperationException(); + } + } + + public T Match( + System::Func @string, + System::Func @double, + System::Func @bool + ) + { + return this switch + { + String inner => @string(inner), + Double inner => @double(inner), + Bool inner => @bool(inner), + _ => throw new System::InvalidOperationException(), + }; + } + + public abstract void Validate(); +} + +sealed class SelectOptionConverter : JsonConverter +{ + public override SelectOption? Read( + ref Utf8JsonReader reader, + System::Type typeToConvert, + JsonSerializerOptions options + ) + { + List exceptions = []; + + try + { + var deserialized = JsonSerializer.Deserialize(ref reader, options); + if (deserialized != null) + { + return new String(deserialized); + } + } + catch (JsonException e) + { + exceptions.Add(e); + } + + try + { + return new Double(JsonSerializer.Deserialize(ref reader, options)); + } + catch (JsonException e) + { + exceptions.Add(e); + } + + try + { + return new Bool(JsonSerializer.Deserialize(ref reader, options)); + } + catch (JsonException e) + { + exceptions.Add(e); + } + + throw new System::AggregateException(exceptions); + } + + public override void Write( + Utf8JsonWriter writer, + SelectOption value, + JsonSerializerOptions options + ) + { + object variant = value switch + { + String(var @string) => @string, + Double(var @double) => @double, + Bool(var @bool) => @bool, + _ => throw new System::ArgumentOutOfRangeException(nameof(value)), + }; + JsonSerializer.Serialize(writer, variant, options); + } +} diff --git a/src/Imagekit/Models/CustomMetadataFields/CustomMetadataFieldCreateParamsProperties/SchemaProperties/SelectOptionVariants/All.cs b/src/Imagekit/Models/CustomMetadataFields/CustomMetadataFieldCreateParamsProperties/SchemaProperties/SelectOptionVariants/All.cs new file mode 100644 index 00000000..2e894cad --- /dev/null +++ b/src/Imagekit/Models/CustomMetadataFields/CustomMetadataFieldCreateParamsProperties/SchemaProperties/SelectOptionVariants/All.cs @@ -0,0 +1,31 @@ +namespace Imagekit.Models.CustomMetadataFields.CustomMetadataFieldCreateParamsProperties.SchemaProperties.SelectOptionVariants; + +public sealed record class String(string Value) : SelectOption, IVariant +{ + public static String From(string value) + { + return new(value); + } + + public override void Validate() { } +} + +public sealed record class Double(double Value) : SelectOption, IVariant +{ + public static Double From(double value) + { + return new(value); + } + + public override void Validate() { } +} + +public sealed record class Bool(bool Value) : SelectOption, IVariant +{ + public static Bool From(bool value) + { + return new(value); + } + + public override void Validate() { } +} diff --git a/src/Imagekit/Models/CustomMetadataFields/CustomMetadataFieldCreateParamsProperties/SchemaProperties/Type.cs b/src/Imagekit/Models/CustomMetadataFields/CustomMetadataFieldCreateParamsProperties/SchemaProperties/Type.cs new file mode 100644 index 00000000..d1008752 --- /dev/null +++ b/src/Imagekit/Models/CustomMetadataFields/CustomMetadataFieldCreateParamsProperties/SchemaProperties/Type.cs @@ -0,0 +1,61 @@ +using System.Text.Json; +using System.Text.Json.Serialization; +using System = System; + +namespace Imagekit.Models.CustomMetadataFields.CustomMetadataFieldCreateParamsProperties.SchemaProperties; + +/// +/// Type of the custom metadata field. +/// +[JsonConverter(typeof(TypeConverter))] +public enum Type +{ + Text, + Textarea, + Number, + Date, + Boolean, + SingleSelect, + MultiSelect, +} + +sealed class TypeConverter : JsonConverter +{ + public override Type Read( + ref Utf8JsonReader reader, + System::Type typeToConvert, + JsonSerializerOptions options + ) + { + return JsonSerializer.Deserialize(ref reader, options) switch + { + "Text" => SchemaProperties.Type.Text, + "Textarea" => SchemaProperties.Type.Textarea, + "Number" => SchemaProperties.Type.Number, + "Date" => SchemaProperties.Type.Date, + "Boolean" => SchemaProperties.Type.Boolean, + "SingleSelect" => SchemaProperties.Type.SingleSelect, + "MultiSelect" => SchemaProperties.Type.MultiSelect, + _ => (Type)(-1), + }; + } + + public override void Write(Utf8JsonWriter writer, Type value, JsonSerializerOptions options) + { + JsonSerializer.Serialize( + writer, + value switch + { + SchemaProperties.Type.Text => "Text", + SchemaProperties.Type.Textarea => "Textarea", + SchemaProperties.Type.Number => "Number", + SchemaProperties.Type.Date => "Date", + SchemaProperties.Type.Boolean => "Boolean", + SchemaProperties.Type.SingleSelect => "SingleSelect", + SchemaProperties.Type.MultiSelect => "MultiSelect", + _ => throw new System::ArgumentOutOfRangeException(nameof(value)), + }, + options + ); + } +} diff --git a/src/Imagekit/Models/CustomMetadataFields/CustomMetadataFieldDeleteParams.cs b/src/Imagekit/Models/CustomMetadataFields/CustomMetadataFieldDeleteParams.cs new file mode 100644 index 00000000..ccf4ec98 --- /dev/null +++ b/src/Imagekit/Models/CustomMetadataFields/CustomMetadataFieldDeleteParams.cs @@ -0,0 +1,33 @@ +using System; +using System.Net.Http; + +namespace Imagekit.Models.CustomMetadataFields; + +/// +/// This API deletes a custom metadata field. Even after deleting a custom metadata +/// field, you cannot create any new custom metadata field with the same name. +/// +public sealed record class CustomMetadataFieldDeleteParams : ParamsBase +{ + public required string ID; + + public override Uri Url(IImageKitClient client) + { + return new UriBuilder( + client.BaseUrl.ToString().TrimEnd('/') + + string.Format("/v1/customMetadataFields/{0}", this.ID) + ) + { + Query = this.QueryString(client), + }.Uri; + } + + public void AddHeadersToRequest(HttpRequestMessage request, IImageKitClient client) + { + ParamsBase.AddDefaultHeaders(request, client); + foreach (var item in this.HeaderProperties) + { + ParamsBase.AddHeaderElementToRequest(request, item.Key, item.Value); + } + } +} diff --git a/src/Imagekit/Models/CustomMetadataFields/CustomMetadataFieldDeleteResponse.cs b/src/Imagekit/Models/CustomMetadataFields/CustomMetadataFieldDeleteResponse.cs new file mode 100644 index 00000000..47473126 --- /dev/null +++ b/src/Imagekit/Models/CustomMetadataFields/CustomMetadataFieldDeleteResponse.cs @@ -0,0 +1,31 @@ +using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; +using System.Text.Json; +using System.Text.Json.Serialization; + +namespace Imagekit.Models.CustomMetadataFields; + +[JsonConverter(typeof(ModelConverter))] +public sealed record class CustomMetadataFieldDeleteResponse + : ModelBase, + IFromRaw +{ + public override void Validate() { } + + public CustomMetadataFieldDeleteResponse() { } + +#pragma warning disable CS8618 + [SetsRequiredMembers] + CustomMetadataFieldDeleteResponse(Dictionary properties) + { + Properties = properties; + } +#pragma warning restore CS8618 + + public static CustomMetadataFieldDeleteResponse FromRawUnchecked( + Dictionary properties + ) + { + return new(properties); + } +} diff --git a/src/Imagekit/Models/CustomMetadataFields/CustomMetadataFieldListParams.cs b/src/Imagekit/Models/CustomMetadataFields/CustomMetadataFieldListParams.cs new file mode 100644 index 00000000..72aeee66 --- /dev/null +++ b/src/Imagekit/Models/CustomMetadataFields/CustomMetadataFieldListParams.cs @@ -0,0 +1,51 @@ +using System; +using System.Net.Http; +using System.Text.Json; + +namespace Imagekit.Models.CustomMetadataFields; + +/// +/// This API returns the array of created custom metadata field objects. By default +/// the API returns only non deleted field objects, but you can include deleted fields +/// in the API response. +/// +public sealed record class CustomMetadataFieldListParams : ParamsBase +{ + /// + /// Set it to `true` to include deleted field objects in the API response. + /// + public bool? IncludeDeleted + { + get + { + if (!this.QueryProperties.TryGetValue("includeDeleted", out JsonElement element)) + return null; + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions); + } + set + { + this.QueryProperties["includeDeleted"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + public override Uri Url(IImageKitClient client) + { + return new UriBuilder(client.BaseUrl.ToString().TrimEnd('/') + "/v1/customMetadataFields") + { + Query = this.QueryString(client), + }.Uri; + } + + public void AddHeadersToRequest(HttpRequestMessage request, IImageKitClient client) + { + ParamsBase.AddDefaultHeaders(request, client); + foreach (var item in this.HeaderProperties) + { + ParamsBase.AddHeaderElementToRequest(request, item.Key, item.Value); + } + } +} diff --git a/src/Imagekit/Models/CustomMetadataFields/CustomMetadataFieldProperties/Schema.cs b/src/Imagekit/Models/CustomMetadataFields/CustomMetadataFieldProperties/Schema.cs new file mode 100644 index 00000000..c650c1cf --- /dev/null +++ b/src/Imagekit/Models/CustomMetadataFields/CustomMetadataFieldProperties/Schema.cs @@ -0,0 +1,240 @@ +using System; +using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; +using System.Text.Json; +using System.Text.Json.Serialization; +using SchemaProperties = Imagekit.Models.CustomMetadataFields.CustomMetadataFieldProperties.SchemaProperties; + +namespace Imagekit.Models.CustomMetadataFields.CustomMetadataFieldProperties; + +/// +/// An object that describes the rules for the custom metadata field value. +/// +[JsonConverter(typeof(ModelConverter))] +public sealed record class Schema : ModelBase, IFromRaw +{ + /// + /// Type of the custom metadata field. + /// + public required ApiEnum Type + { + get + { + if (!this.Properties.TryGetValue("type", out JsonElement element)) + throw new ArgumentOutOfRangeException("type", "Missing required argument"); + + return JsonSerializer.Deserialize>( + element, + ModelBase.SerializerOptions + ); + } + set + { + this.Properties["type"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + /// + /// The default value for this custom metadata field. Date type of default value + /// depends on the field type. + /// + public SchemaProperties::DefaultValue? DefaultValue + { + get + { + if (!this.Properties.TryGetValue("defaultValue", out JsonElement element)) + return null; + + return JsonSerializer.Deserialize( + element, + ModelBase.SerializerOptions + ); + } + set + { + this.Properties["defaultValue"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + /// + /// Specifies if the this custom metadata field is required or not. + /// + public bool? IsValueRequired + { + get + { + if (!this.Properties.TryGetValue("isValueRequired", out JsonElement element)) + return null; + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions); + } + set + { + this.Properties["isValueRequired"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + /// + /// Maximum length of string. Only set if `type` is set to `Text` or `Textarea`. + /// + public double? MaxLength + { + get + { + if (!this.Properties.TryGetValue("maxLength", out JsonElement element)) + return null; + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions); + } + set + { + this.Properties["maxLength"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + /// + /// Maximum value of the field. Only set if field type is `Date` or `Number`. + /// For `Date` type field, the value will be in ISO8601 string format. For `Number` + /// type field, it will be a numeric value. + /// + public SchemaProperties::MaxValue? MaxValue + { + get + { + if (!this.Properties.TryGetValue("maxValue", out JsonElement element)) + return null; + + return JsonSerializer.Deserialize( + element, + ModelBase.SerializerOptions + ); + } + set + { + this.Properties["maxValue"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + /// + /// Minimum length of string. Only set if `type` is set to `Text` or `Textarea`. + /// + public double? MinLength + { + get + { + if (!this.Properties.TryGetValue("minLength", out JsonElement element)) + return null; + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions); + } + set + { + this.Properties["minLength"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + /// + /// Minimum value of the field. Only set if field type is `Date` or `Number`. + /// For `Date` type field, the value will be in ISO8601 string format. For `Number` + /// type field, it will be a numeric value. + /// + public SchemaProperties::MinValue? MinValue + { + get + { + if (!this.Properties.TryGetValue("minValue", out JsonElement element)) + return null; + + return JsonSerializer.Deserialize( + element, + ModelBase.SerializerOptions + ); + } + set + { + this.Properties["minValue"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + /// + /// An array of allowed values when field type is `SingleSelect` or `MultiSelect`. + /// + public List? SelectOptions + { + get + { + if (!this.Properties.TryGetValue("selectOptions", out JsonElement element)) + return null; + + return JsonSerializer.Deserialize?>( + element, + ModelBase.SerializerOptions + ); + } + set + { + this.Properties["selectOptions"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + public override void Validate() + { + this.Type.Validate(); + this.DefaultValue?.Validate(); + _ = this.IsValueRequired; + _ = this.MaxLength; + this.MaxValue?.Validate(); + _ = this.MinLength; + this.MinValue?.Validate(); + foreach (var item in this.SelectOptions ?? []) + { + item.Validate(); + } + } + + public Schema() { } + +#pragma warning disable CS8618 + [SetsRequiredMembers] + Schema(Dictionary properties) + { + Properties = properties; + } +#pragma warning restore CS8618 + + public static Schema FromRawUnchecked(Dictionary properties) + { + return new(properties); + } + + [SetsRequiredMembers] + public Schema(ApiEnum type) + : this() + { + this.Type = type; + } +} diff --git a/src/Imagekit/Models/CustomMetadataFields/CustomMetadataFieldProperties/SchemaProperties/DefaultValue.cs b/src/Imagekit/Models/CustomMetadataFields/CustomMetadataFieldProperties/SchemaProperties/DefaultValue.cs new file mode 100644 index 00000000..d825c283 --- /dev/null +++ b/src/Imagekit/Models/CustomMetadataFields/CustomMetadataFieldProperties/SchemaProperties/DefaultValue.cs @@ -0,0 +1,175 @@ +using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; +using System.Text.Json; +using System.Text.Json.Serialization; +using Imagekit.Models.CustomMetadataFields.CustomMetadataFieldProperties.SchemaProperties.DefaultValueProperties; +using Imagekit.Models.CustomMetadataFields.CustomMetadataFieldProperties.SchemaProperties.DefaultValueVariants; +using System = System; + +namespace Imagekit.Models.CustomMetadataFields.CustomMetadataFieldProperties.SchemaProperties; + +/// +/// The default value for this custom metadata field. Date type of default value +/// depends on the field type. +/// +[JsonConverter(typeof(DefaultValueConverter))] +public abstract record class DefaultValue +{ + internal DefaultValue() { } + + public static implicit operator DefaultValue(string value) => new String(value); + + public static implicit operator DefaultValue(double value) => new Double(value); + + public static implicit operator DefaultValue(bool value) => new Bool(value); + + public static implicit operator DefaultValue(List value) => + new Mixed(value); + + public bool TryPickString([NotNullWhen(true)] out string? value) + { + value = (this as String)?.Value; + return value != null; + } + + public bool TryPickDouble([NotNullWhen(true)] out double? value) + { + value = (this as Double)?.Value; + return value != null; + } + + public bool TryPickBool([NotNullWhen(true)] out bool? value) + { + value = (this as Bool)?.Value; + return value != null; + } + + public bool TryPickMixed([NotNullWhen(true)] out List? value) + { + value = (this as Mixed)?.Value; + return value != null; + } + + public void Switch( + System::Action @string, + System::Action @double, + System::Action @bool, + System::Action mixed + ) + { + switch (this) + { + case String inner: + @string(inner); + break; + case Double inner: + @double(inner); + break; + case Bool inner: + @bool(inner); + break; + case Mixed inner: + mixed(inner); + break; + default: + throw new System::InvalidOperationException(); + } + } + + public T Match( + System::Func @string, + System::Func @double, + System::Func @bool, + System::Func mixed + ) + { + return this switch + { + String inner => @string(inner), + Double inner => @double(inner), + Bool inner => @bool(inner), + Mixed inner => mixed(inner), + _ => throw new System::InvalidOperationException(), + }; + } + + public abstract void Validate(); +} + +sealed class DefaultValueConverter : JsonConverter +{ + public override DefaultValue? Read( + ref Utf8JsonReader reader, + System::Type typeToConvert, + JsonSerializerOptions options + ) + { + List exceptions = []; + + try + { + var deserialized = JsonSerializer.Deserialize(ref reader, options); + if (deserialized != null) + { + return new String(deserialized); + } + } + catch (JsonException e) + { + exceptions.Add(e); + } + + try + { + return new Double(JsonSerializer.Deserialize(ref reader, options)); + } + catch (JsonException e) + { + exceptions.Add(e); + } + + try + { + return new Bool(JsonSerializer.Deserialize(ref reader, options)); + } + catch (JsonException e) + { + exceptions.Add(e); + } + + try + { + var deserialized = JsonSerializer.Deserialize>( + ref reader, + options + ); + if (deserialized != null) + { + return new Mixed(deserialized); + } + } + catch (JsonException e) + { + exceptions.Add(e); + } + + throw new System::AggregateException(exceptions); + } + + public override void Write( + Utf8JsonWriter writer, + DefaultValue value, + JsonSerializerOptions options + ) + { + object variant = value switch + { + String(var @string) => @string, + Double(var @double) => @double, + Bool(var @bool) => @bool, + Mixed(var mixed) => mixed, + _ => throw new System::ArgumentOutOfRangeException(nameof(value)), + }; + JsonSerializer.Serialize(writer, variant, options); + } +} diff --git a/src/Imagekit/Models/CustomMetadataFields/CustomMetadataFieldProperties/SchemaProperties/DefaultValueProperties/UnnamedSchemaWithArrayParent0.cs b/src/Imagekit/Models/CustomMetadataFields/CustomMetadataFieldProperties/SchemaProperties/DefaultValueProperties/UnnamedSchemaWithArrayParent0.cs new file mode 100644 index 00000000..2aa86446 --- /dev/null +++ b/src/Imagekit/Models/CustomMetadataFields/CustomMetadataFieldProperties/SchemaProperties/DefaultValueProperties/UnnamedSchemaWithArrayParent0.cs @@ -0,0 +1,140 @@ +using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; +using System.Text.Json; +using System.Text.Json.Serialization; +using Imagekit.Models.CustomMetadataFields.CustomMetadataFieldProperties.SchemaProperties.DefaultValueProperties.UnnamedSchemaWithArrayParent0Variants; +using System = System; + +namespace Imagekit.Models.CustomMetadataFields.CustomMetadataFieldProperties.SchemaProperties.DefaultValueProperties; + +[JsonConverter(typeof(UnnamedSchemaWithArrayParent0Converter))] +public abstract record class UnnamedSchemaWithArrayParent0 +{ + internal UnnamedSchemaWithArrayParent0() { } + + public static implicit operator UnnamedSchemaWithArrayParent0(string value) => + new String(value); + + public static implicit operator UnnamedSchemaWithArrayParent0(double value) => + new Double(value); + + public static implicit operator UnnamedSchemaWithArrayParent0(bool value) => new Bool(value); + + public bool TryPickString([NotNullWhen(true)] out string? value) + { + value = (this as String)?.Value; + return value != null; + } + + public bool TryPickDouble([NotNullWhen(true)] out double? value) + { + value = (this as Double)?.Value; + return value != null; + } + + public bool TryPickBool([NotNullWhen(true)] out bool? value) + { + value = (this as Bool)?.Value; + return value != null; + } + + public void Switch( + System::Action @string, + System::Action @double, + System::Action @bool + ) + { + switch (this) + { + case String inner: + @string(inner); + break; + case Double inner: + @double(inner); + break; + case Bool inner: + @bool(inner); + break; + default: + throw new System::InvalidOperationException(); + } + } + + public T Match( + System::Func @string, + System::Func @double, + System::Func @bool + ) + { + return this switch + { + String inner => @string(inner), + Double inner => @double(inner), + Bool inner => @bool(inner), + _ => throw new System::InvalidOperationException(), + }; + } + + public abstract void Validate(); +} + +sealed class UnnamedSchemaWithArrayParent0Converter : JsonConverter +{ + public override UnnamedSchemaWithArrayParent0? Read( + ref Utf8JsonReader reader, + System::Type typeToConvert, + JsonSerializerOptions options + ) + { + List exceptions = []; + + try + { + var deserialized = JsonSerializer.Deserialize(ref reader, options); + if (deserialized != null) + { + return new String(deserialized); + } + } + catch (JsonException e) + { + exceptions.Add(e); + } + + try + { + return new Double(JsonSerializer.Deserialize(ref reader, options)); + } + catch (JsonException e) + { + exceptions.Add(e); + } + + try + { + return new Bool(JsonSerializer.Deserialize(ref reader, options)); + } + catch (JsonException e) + { + exceptions.Add(e); + } + + throw new System::AggregateException(exceptions); + } + + public override void Write( + Utf8JsonWriter writer, + UnnamedSchemaWithArrayParent0 value, + JsonSerializerOptions options + ) + { + object variant = value switch + { + String(var @string) => @string, + Double(var @double) => @double, + Bool(var @bool) => @bool, + _ => throw new System::ArgumentOutOfRangeException(nameof(value)), + }; + JsonSerializer.Serialize(writer, variant, options); + } +} diff --git a/src/Imagekit/Models/CustomMetadataFields/CustomMetadataFieldProperties/SchemaProperties/DefaultValueProperties/UnnamedSchemaWithArrayParent0Variants/All.cs b/src/Imagekit/Models/CustomMetadataFields/CustomMetadataFieldProperties/SchemaProperties/DefaultValueProperties/UnnamedSchemaWithArrayParent0Variants/All.cs new file mode 100644 index 00000000..30c9b6cb --- /dev/null +++ b/src/Imagekit/Models/CustomMetadataFields/CustomMetadataFieldProperties/SchemaProperties/DefaultValueProperties/UnnamedSchemaWithArrayParent0Variants/All.cs @@ -0,0 +1,35 @@ +namespace Imagekit.Models.CustomMetadataFields.CustomMetadataFieldProperties.SchemaProperties.DefaultValueProperties.UnnamedSchemaWithArrayParent0Variants; + +public sealed record class String(string Value) + : UnnamedSchemaWithArrayParent0, + IVariant +{ + public static String From(string value) + { + return new(value); + } + + public override void Validate() { } +} + +public sealed record class Double(double Value) + : UnnamedSchemaWithArrayParent0, + IVariant +{ + public static Double From(double value) + { + return new(value); + } + + public override void Validate() { } +} + +public sealed record class Bool(bool Value) : UnnamedSchemaWithArrayParent0, IVariant +{ + public static Bool From(bool value) + { + return new(value); + } + + public override void Validate() { } +} diff --git a/src/Imagekit/Models/CustomMetadataFields/CustomMetadataFieldProperties/SchemaProperties/DefaultValueVariants/All.cs b/src/Imagekit/Models/CustomMetadataFields/CustomMetadataFieldProperties/SchemaProperties/DefaultValueVariants/All.cs new file mode 100644 index 00000000..2d59b456 --- /dev/null +++ b/src/Imagekit/Models/CustomMetadataFields/CustomMetadataFieldProperties/SchemaProperties/DefaultValueVariants/All.cs @@ -0,0 +1,50 @@ +using System.Collections.Generic; +using Imagekit.Models.CustomMetadataFields.CustomMetadataFieldProperties.SchemaProperties.DefaultValueProperties; + +namespace Imagekit.Models.CustomMetadataFields.CustomMetadataFieldProperties.SchemaProperties.DefaultValueVariants; + +public sealed record class String(string Value) : DefaultValue, IVariant +{ + public static String From(string value) + { + return new(value); + } + + public override void Validate() { } +} + +public sealed record class Double(double Value) : DefaultValue, IVariant +{ + public static Double From(double value) + { + return new(value); + } + + public override void Validate() { } +} + +public sealed record class Bool(bool Value) : DefaultValue, IVariant +{ + public static Bool From(bool value) + { + return new(value); + } + + public override void Validate() { } +} + +/// +/// Default value should be of type array when custom metadata field type is set to +/// `MultiSelect`. +/// +public sealed record class Mixed(List Value) + : DefaultValue, + IVariant> +{ + public static Mixed From(List value) + { + return new(value); + } + + public override void Validate() { } +} diff --git a/src/Imagekit/Models/CustomMetadataFields/CustomMetadataFieldProperties/SchemaProperties/MaxValue.cs b/src/Imagekit/Models/CustomMetadataFields/CustomMetadataFieldProperties/SchemaProperties/MaxValue.cs new file mode 100644 index 00000000..fb8cbefe --- /dev/null +++ b/src/Imagekit/Models/CustomMetadataFields/CustomMetadataFieldProperties/SchemaProperties/MaxValue.cs @@ -0,0 +1,109 @@ +using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; +using System.Text.Json; +using System.Text.Json.Serialization; +using Imagekit.Models.CustomMetadataFields.CustomMetadataFieldProperties.SchemaProperties.MaxValueVariants; +using System = System; + +namespace Imagekit.Models.CustomMetadataFields.CustomMetadataFieldProperties.SchemaProperties; + +/// +/// Maximum value of the field. Only set if field type is `Date` or `Number`. For +/// `Date` type field, the value will be in ISO8601 string format. For `Number` type +/// field, it will be a numeric value. +/// +[JsonConverter(typeof(MaxValueConverter))] +public abstract record class MaxValue +{ + internal MaxValue() { } + + public static implicit operator MaxValue(string value) => new String(value); + + public static implicit operator MaxValue(double value) => new Double(value); + + public bool TryPickString([NotNullWhen(true)] out string? value) + { + value = (this as String)?.Value; + return value != null; + } + + public bool TryPickDouble([NotNullWhen(true)] out double? value) + { + value = (this as Double)?.Value; + return value != null; + } + + public void Switch(System::Action @string, System::Action @double) + { + switch (this) + { + case String inner: + @string(inner); + break; + case Double inner: + @double(inner); + break; + default: + throw new System::InvalidOperationException(); + } + } + + public T Match(System::Func @string, System::Func @double) + { + return this switch + { + String inner => @string(inner), + Double inner => @double(inner), + _ => throw new System::InvalidOperationException(), + }; + } + + public abstract void Validate(); +} + +sealed class MaxValueConverter : JsonConverter +{ + public override MaxValue? Read( + ref Utf8JsonReader reader, + System::Type typeToConvert, + JsonSerializerOptions options + ) + { + List exceptions = []; + + try + { + var deserialized = JsonSerializer.Deserialize(ref reader, options); + if (deserialized != null) + { + return new String(deserialized); + } + } + catch (JsonException e) + { + exceptions.Add(e); + } + + try + { + return new Double(JsonSerializer.Deserialize(ref reader, options)); + } + catch (JsonException e) + { + exceptions.Add(e); + } + + throw new System::AggregateException(exceptions); + } + + public override void Write(Utf8JsonWriter writer, MaxValue value, JsonSerializerOptions options) + { + object variant = value switch + { + String(var @string) => @string, + Double(var @double) => @double, + _ => throw new System::ArgumentOutOfRangeException(nameof(value)), + }; + JsonSerializer.Serialize(writer, variant, options); + } +} diff --git a/src/Imagekit/Models/CustomMetadataFields/CustomMetadataFieldProperties/SchemaProperties/MaxValueVariants/All.cs b/src/Imagekit/Models/CustomMetadataFields/CustomMetadataFieldProperties/SchemaProperties/MaxValueVariants/All.cs new file mode 100644 index 00000000..40dbd110 --- /dev/null +++ b/src/Imagekit/Models/CustomMetadataFields/CustomMetadataFieldProperties/SchemaProperties/MaxValueVariants/All.cs @@ -0,0 +1,21 @@ +namespace Imagekit.Models.CustomMetadataFields.CustomMetadataFieldProperties.SchemaProperties.MaxValueVariants; + +public sealed record class String(string Value) : MaxValue, IVariant +{ + public static String From(string value) + { + return new(value); + } + + public override void Validate() { } +} + +public sealed record class Double(double Value) : MaxValue, IVariant +{ + public static Double From(double value) + { + return new(value); + } + + public override void Validate() { } +} diff --git a/src/Imagekit/Models/CustomMetadataFields/CustomMetadataFieldProperties/SchemaProperties/MinValue.cs b/src/Imagekit/Models/CustomMetadataFields/CustomMetadataFieldProperties/SchemaProperties/MinValue.cs new file mode 100644 index 00000000..21b6c8a5 --- /dev/null +++ b/src/Imagekit/Models/CustomMetadataFields/CustomMetadataFieldProperties/SchemaProperties/MinValue.cs @@ -0,0 +1,109 @@ +using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; +using System.Text.Json; +using System.Text.Json.Serialization; +using Imagekit.Models.CustomMetadataFields.CustomMetadataFieldProperties.SchemaProperties.MinValueVariants; +using System = System; + +namespace Imagekit.Models.CustomMetadataFields.CustomMetadataFieldProperties.SchemaProperties; + +/// +/// Minimum value of the field. Only set if field type is `Date` or `Number`. For +/// `Date` type field, the value will be in ISO8601 string format. For `Number` type +/// field, it will be a numeric value. +/// +[JsonConverter(typeof(MinValueConverter))] +public abstract record class MinValue +{ + internal MinValue() { } + + public static implicit operator MinValue(string value) => new String(value); + + public static implicit operator MinValue(double value) => new Double(value); + + public bool TryPickString([NotNullWhen(true)] out string? value) + { + value = (this as String)?.Value; + return value != null; + } + + public bool TryPickDouble([NotNullWhen(true)] out double? value) + { + value = (this as Double)?.Value; + return value != null; + } + + public void Switch(System::Action @string, System::Action @double) + { + switch (this) + { + case String inner: + @string(inner); + break; + case Double inner: + @double(inner); + break; + default: + throw new System::InvalidOperationException(); + } + } + + public T Match(System::Func @string, System::Func @double) + { + return this switch + { + String inner => @string(inner), + Double inner => @double(inner), + _ => throw new System::InvalidOperationException(), + }; + } + + public abstract void Validate(); +} + +sealed class MinValueConverter : JsonConverter +{ + public override MinValue? Read( + ref Utf8JsonReader reader, + System::Type typeToConvert, + JsonSerializerOptions options + ) + { + List exceptions = []; + + try + { + var deserialized = JsonSerializer.Deserialize(ref reader, options); + if (deserialized != null) + { + return new String(deserialized); + } + } + catch (JsonException e) + { + exceptions.Add(e); + } + + try + { + return new Double(JsonSerializer.Deserialize(ref reader, options)); + } + catch (JsonException e) + { + exceptions.Add(e); + } + + throw new System::AggregateException(exceptions); + } + + public override void Write(Utf8JsonWriter writer, MinValue value, JsonSerializerOptions options) + { + object variant = value switch + { + String(var @string) => @string, + Double(var @double) => @double, + _ => throw new System::ArgumentOutOfRangeException(nameof(value)), + }; + JsonSerializer.Serialize(writer, variant, options); + } +} diff --git a/src/Imagekit/Models/CustomMetadataFields/CustomMetadataFieldProperties/SchemaProperties/MinValueVariants/All.cs b/src/Imagekit/Models/CustomMetadataFields/CustomMetadataFieldProperties/SchemaProperties/MinValueVariants/All.cs new file mode 100644 index 00000000..6ed3faa4 --- /dev/null +++ b/src/Imagekit/Models/CustomMetadataFields/CustomMetadataFieldProperties/SchemaProperties/MinValueVariants/All.cs @@ -0,0 +1,21 @@ +namespace Imagekit.Models.CustomMetadataFields.CustomMetadataFieldProperties.SchemaProperties.MinValueVariants; + +public sealed record class String(string Value) : MinValue, IVariant +{ + public static String From(string value) + { + return new(value); + } + + public override void Validate() { } +} + +public sealed record class Double(double Value) : MinValue, IVariant +{ + public static Double From(double value) + { + return new(value); + } + + public override void Validate() { } +} diff --git a/src/Imagekit/Models/CustomMetadataFields/CustomMetadataFieldProperties/SchemaProperties/SelectOption.cs b/src/Imagekit/Models/CustomMetadataFields/CustomMetadataFieldProperties/SchemaProperties/SelectOption.cs new file mode 100644 index 00000000..df5e0640 --- /dev/null +++ b/src/Imagekit/Models/CustomMetadataFields/CustomMetadataFieldProperties/SchemaProperties/SelectOption.cs @@ -0,0 +1,138 @@ +using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; +using System.Text.Json; +using System.Text.Json.Serialization; +using Imagekit.Models.CustomMetadataFields.CustomMetadataFieldProperties.SchemaProperties.SelectOptionVariants; +using System = System; + +namespace Imagekit.Models.CustomMetadataFields.CustomMetadataFieldProperties.SchemaProperties; + +[JsonConverter(typeof(SelectOptionConverter))] +public abstract record class SelectOption +{ + internal SelectOption() { } + + public static implicit operator SelectOption(string value) => new String(value); + + public static implicit operator SelectOption(double value) => new Double(value); + + public static implicit operator SelectOption(bool value) => new Bool(value); + + public bool TryPickString([NotNullWhen(true)] out string? value) + { + value = (this as String)?.Value; + return value != null; + } + + public bool TryPickDouble([NotNullWhen(true)] out double? value) + { + value = (this as Double)?.Value; + return value != null; + } + + public bool TryPickBool([NotNullWhen(true)] out bool? value) + { + value = (this as Bool)?.Value; + return value != null; + } + + public void Switch( + System::Action @string, + System::Action @double, + System::Action @bool + ) + { + switch (this) + { + case String inner: + @string(inner); + break; + case Double inner: + @double(inner); + break; + case Bool inner: + @bool(inner); + break; + default: + throw new System::InvalidOperationException(); + } + } + + public T Match( + System::Func @string, + System::Func @double, + System::Func @bool + ) + { + return this switch + { + String inner => @string(inner), + Double inner => @double(inner), + Bool inner => @bool(inner), + _ => throw new System::InvalidOperationException(), + }; + } + + public abstract void Validate(); +} + +sealed class SelectOptionConverter : JsonConverter +{ + public override SelectOption? Read( + ref Utf8JsonReader reader, + System::Type typeToConvert, + JsonSerializerOptions options + ) + { + List exceptions = []; + + try + { + var deserialized = JsonSerializer.Deserialize(ref reader, options); + if (deserialized != null) + { + return new String(deserialized); + } + } + catch (JsonException e) + { + exceptions.Add(e); + } + + try + { + return new Double(JsonSerializer.Deserialize(ref reader, options)); + } + catch (JsonException e) + { + exceptions.Add(e); + } + + try + { + return new Bool(JsonSerializer.Deserialize(ref reader, options)); + } + catch (JsonException e) + { + exceptions.Add(e); + } + + throw new System::AggregateException(exceptions); + } + + public override void Write( + Utf8JsonWriter writer, + SelectOption value, + JsonSerializerOptions options + ) + { + object variant = value switch + { + String(var @string) => @string, + Double(var @double) => @double, + Bool(var @bool) => @bool, + _ => throw new System::ArgumentOutOfRangeException(nameof(value)), + }; + JsonSerializer.Serialize(writer, variant, options); + } +} diff --git a/src/Imagekit/Models/CustomMetadataFields/CustomMetadataFieldProperties/SchemaProperties/SelectOptionVariants/All.cs b/src/Imagekit/Models/CustomMetadataFields/CustomMetadataFieldProperties/SchemaProperties/SelectOptionVariants/All.cs new file mode 100644 index 00000000..7127cf34 --- /dev/null +++ b/src/Imagekit/Models/CustomMetadataFields/CustomMetadataFieldProperties/SchemaProperties/SelectOptionVariants/All.cs @@ -0,0 +1,31 @@ +namespace Imagekit.Models.CustomMetadataFields.CustomMetadataFieldProperties.SchemaProperties.SelectOptionVariants; + +public sealed record class String(string Value) : SelectOption, IVariant +{ + public static String From(string value) + { + return new(value); + } + + public override void Validate() { } +} + +public sealed record class Double(double Value) : SelectOption, IVariant +{ + public static Double From(double value) + { + return new(value); + } + + public override void Validate() { } +} + +public sealed record class Bool(bool Value) : SelectOption, IVariant +{ + public static Bool From(bool value) + { + return new(value); + } + + public override void Validate() { } +} diff --git a/src/Imagekit/Models/CustomMetadataFields/CustomMetadataFieldProperties/SchemaProperties/Type.cs b/src/Imagekit/Models/CustomMetadataFields/CustomMetadataFieldProperties/SchemaProperties/Type.cs new file mode 100644 index 00000000..de0b7408 --- /dev/null +++ b/src/Imagekit/Models/CustomMetadataFields/CustomMetadataFieldProperties/SchemaProperties/Type.cs @@ -0,0 +1,61 @@ +using System.Text.Json; +using System.Text.Json.Serialization; +using System = System; + +namespace Imagekit.Models.CustomMetadataFields.CustomMetadataFieldProperties.SchemaProperties; + +/// +/// Type of the custom metadata field. +/// +[JsonConverter(typeof(TypeConverter))] +public enum Type +{ + Text, + Textarea, + Number, + Date, + Boolean, + SingleSelect, + MultiSelect, +} + +sealed class TypeConverter : JsonConverter +{ + public override Type Read( + ref Utf8JsonReader reader, + System::Type typeToConvert, + JsonSerializerOptions options + ) + { + return JsonSerializer.Deserialize(ref reader, options) switch + { + "Text" => SchemaProperties.Type.Text, + "Textarea" => SchemaProperties.Type.Textarea, + "Number" => SchemaProperties.Type.Number, + "Date" => SchemaProperties.Type.Date, + "Boolean" => SchemaProperties.Type.Boolean, + "SingleSelect" => SchemaProperties.Type.SingleSelect, + "MultiSelect" => SchemaProperties.Type.MultiSelect, + _ => (Type)(-1), + }; + } + + public override void Write(Utf8JsonWriter writer, Type value, JsonSerializerOptions options) + { + JsonSerializer.Serialize( + writer, + value switch + { + SchemaProperties.Type.Text => "Text", + SchemaProperties.Type.Textarea => "Textarea", + SchemaProperties.Type.Number => "Number", + SchemaProperties.Type.Date => "Date", + SchemaProperties.Type.Boolean => "Boolean", + SchemaProperties.Type.SingleSelect => "SingleSelect", + SchemaProperties.Type.MultiSelect => "MultiSelect", + _ => throw new System::ArgumentOutOfRangeException(nameof(value)), + }, + options + ); + } +} diff --git a/src/Imagekit/Models/CustomMetadataFields/CustomMetadataFieldUpdateParams.cs b/src/Imagekit/Models/CustomMetadataFields/CustomMetadataFieldUpdateParams.cs new file mode 100644 index 00000000..3bfb3f73 --- /dev/null +++ b/src/Imagekit/Models/CustomMetadataFields/CustomMetadataFieldUpdateParams.cs @@ -0,0 +1,95 @@ +using System; +using System.Collections.Generic; +using System.Net.Http; +using System.Text; +using System.Text.Json; +using Imagekit.Models.CustomMetadataFields.CustomMetadataFieldUpdateParamsProperties; + +namespace Imagekit.Models.CustomMetadataFields; + +/// +/// This API updates the label or schema of an existing custom metadata field. +/// +public sealed record class CustomMetadataFieldUpdateParams : ParamsBase +{ + public Dictionary BodyProperties { get; set; } = []; + + public required string ID; + + /// + /// Human readable name of the custom metadata field. This should be unique across + /// all non deleted custom metadata fields. This name is displayed as form field + /// label to the users while setting field value on an asset in the media library + /// UI. This parameter is required if `schema` is not provided. + /// + public string? Label + { + get + { + if (!this.BodyProperties.TryGetValue("label", out JsonElement element)) + return null; + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions); + } + set + { + this.BodyProperties["label"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + /// + /// An object that describes the rules for the custom metadata key. This parameter + /// is required if `label` is not provided. Note: `type` cannot be updated and + /// will be ignored if sent with the `schema`. The schema will be validated as + /// per the existing `type`. + /// + public Schema? Schema + { + get + { + if (!this.BodyProperties.TryGetValue("schema", out JsonElement element)) + return null; + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions); + } + set + { + this.BodyProperties["schema"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + public override Uri Url(IImageKitClient client) + { + return new UriBuilder( + client.BaseUrl.ToString().TrimEnd('/') + + string.Format("/v1/customMetadataFields/{0}", this.ID) + ) + { + Query = this.QueryString(client), + }.Uri; + } + + public StringContent BodyContent() + { + return new( + JsonSerializer.Serialize(this.BodyProperties), + Encoding.UTF8, + "application/json" + ); + } + + public void AddHeadersToRequest(HttpRequestMessage request, IImageKitClient client) + { + ParamsBase.AddDefaultHeaders(request, client); + foreach (var item in this.HeaderProperties) + { + ParamsBase.AddHeaderElementToRequest(request, item.Key, item.Value); + } + } +} diff --git a/src/Imagekit/Models/CustomMetadataFields/CustomMetadataFieldUpdateParamsProperties/Schema.cs b/src/Imagekit/Models/CustomMetadataFields/CustomMetadataFieldUpdateParamsProperties/Schema.cs new file mode 100644 index 00000000..634ff465 --- /dev/null +++ b/src/Imagekit/Models/CustomMetadataFields/CustomMetadataFieldUpdateParamsProperties/Schema.cs @@ -0,0 +1,207 @@ +using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; +using System.Text.Json; +using System.Text.Json.Serialization; +using Imagekit.Models.CustomMetadataFields.CustomMetadataFieldUpdateParamsProperties.SchemaProperties; + +namespace Imagekit.Models.CustomMetadataFields.CustomMetadataFieldUpdateParamsProperties; + +/// +/// An object that describes the rules for the custom metadata key. This parameter +/// is required if `label` is not provided. Note: `type` cannot be updated and will +/// be ignored if sent with the `schema`. The schema will be validated as per the +/// existing `type`. +/// +[JsonConverter(typeof(ModelConverter))] +public sealed record class Schema : ModelBase, IFromRaw +{ + /// + /// The default value for this custom metadata field. This property is only required + /// if `isValueRequired` property is set to `true`. The value should match the + /// `type` of custom metadata field. + /// + public DefaultValue? DefaultValue + { + get + { + if (!this.Properties.TryGetValue("defaultValue", out JsonElement element)) + return null; + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions); + } + set + { + this.Properties["defaultValue"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + /// + /// Sets this custom metadata field as required. Setting custom metadata fields + /// on an asset will throw error if the value for all required fields are not + /// present in upload or update asset API request body. + /// + public bool? IsValueRequired + { + get + { + if (!this.Properties.TryGetValue("isValueRequired", out JsonElement element)) + return null; + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions); + } + set + { + this.Properties["isValueRequired"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + /// + /// Maximum length of string. Only set this property if `type` is set to `Text` + /// or `Textarea`. + /// + public double? MaxLength + { + get + { + if (!this.Properties.TryGetValue("maxLength", out JsonElement element)) + return null; + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions); + } + set + { + this.Properties["maxLength"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + /// + /// Maximum value of the field. Only set this property if field type is `Date` + /// or `Number`. For `Date` type field, set the minimum date in ISO8601 string + /// format. For `Number` type field, set the minimum numeric value. + /// + public MaxValue? MaxValue + { + get + { + if (!this.Properties.TryGetValue("maxValue", out JsonElement element)) + return null; + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions); + } + set + { + this.Properties["maxValue"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + /// + /// Minimum length of string. Only set this property if `type` is set to `Text` + /// or `Textarea`. + /// + public double? MinLength + { + get + { + if (!this.Properties.TryGetValue("minLength", out JsonElement element)) + return null; + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions); + } + set + { + this.Properties["minLength"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + /// + /// Minimum value of the field. Only set this property if field type is `Date` + /// or `Number`. For `Date` type field, set the minimum date in ISO8601 string + /// format. For `Number` type field, set the minimum numeric value. + /// + public MinValue? MinValue + { + get + { + if (!this.Properties.TryGetValue("minValue", out JsonElement element)) + return null; + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions); + } + set + { + this.Properties["minValue"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + /// + /// An array of allowed values. This property is only required if `type` property + /// is set to `SingleSelect` or `MultiSelect`. + /// + public List? SelectOptions + { + get + { + if (!this.Properties.TryGetValue("selectOptions", out JsonElement element)) + return null; + + return JsonSerializer.Deserialize?>( + element, + ModelBase.SerializerOptions + ); + } + set + { + this.Properties["selectOptions"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + public override void Validate() + { + this.DefaultValue?.Validate(); + _ = this.IsValueRequired; + _ = this.MaxLength; + this.MaxValue?.Validate(); + _ = this.MinLength; + this.MinValue?.Validate(); + foreach (var item in this.SelectOptions ?? []) + { + item.Validate(); + } + } + + public Schema() { } + +#pragma warning disable CS8618 + [SetsRequiredMembers] + Schema(Dictionary properties) + { + Properties = properties; + } +#pragma warning restore CS8618 + + public static Schema FromRawUnchecked(Dictionary properties) + { + return new(properties); + } +} diff --git a/src/Imagekit/Models/CustomMetadataFields/CustomMetadataFieldUpdateParamsProperties/SchemaProperties/DefaultValue.cs b/src/Imagekit/Models/CustomMetadataFields/CustomMetadataFieldUpdateParamsProperties/SchemaProperties/DefaultValue.cs new file mode 100644 index 00000000..d806401a --- /dev/null +++ b/src/Imagekit/Models/CustomMetadataFields/CustomMetadataFieldUpdateParamsProperties/SchemaProperties/DefaultValue.cs @@ -0,0 +1,183 @@ +using System; +using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; +using System.Text.Json; +using System.Text.Json.Serialization; +using Imagekit.Models.CustomMetadataFields.CustomMetadataFieldUpdateParamsProperties.SchemaProperties.DefaultValueProperties; +using DefaultValueVariants = Imagekit.Models.CustomMetadataFields.CustomMetadataFieldUpdateParamsProperties.SchemaProperties.DefaultValueVariants; + +namespace Imagekit.Models.CustomMetadataFields.CustomMetadataFieldUpdateParamsProperties.SchemaProperties; + +/// +/// The default value for this custom metadata field. This property is only required +/// if `isValueRequired` property is set to `true`. The value should match the `type` +/// of custom metadata field. +/// +[JsonConverter(typeof(DefaultValueConverter))] +public abstract record class DefaultValue +{ + internal DefaultValue() { } + + public static implicit operator DefaultValue(string value) => + new DefaultValueVariants::String(value); + + public static implicit operator DefaultValue(double value) => + new DefaultValueVariants::Double(value); + + public static implicit operator DefaultValue(bool value) => + new DefaultValueVariants::Bool(value); + + public static implicit operator DefaultValue(List value) => + new DefaultValueVariants::Mixed(value); + + public bool TryPickString([NotNullWhen(true)] out string? value) + { + value = (this as DefaultValueVariants::String)?.Value; + return value != null; + } + + public bool TryPickDouble([NotNullWhen(true)] out double? value) + { + value = (this as DefaultValueVariants::Double)?.Value; + return value != null; + } + + public bool TryPickBool([NotNullWhen(true)] out bool? value) + { + value = (this as DefaultValueVariants::Bool)?.Value; + return value != null; + } + + public bool TryPickMixed([NotNullWhen(true)] out List? value) + { + value = (this as DefaultValueVariants::Mixed)?.Value; + return value != null; + } + + public void Switch( + Action @string, + Action @double, + Action @bool, + Action mixed + ) + { + switch (this) + { + case DefaultValueVariants::String inner: + @string(inner); + break; + case DefaultValueVariants::Double inner: + @double(inner); + break; + case DefaultValueVariants::Bool inner: + @bool(inner); + break; + case DefaultValueVariants::Mixed inner: + mixed(inner); + break; + default: + throw new InvalidOperationException(); + } + } + + public T Match( + Func @string, + Func @double, + Func @bool, + Func mixed + ) + { + return this switch + { + DefaultValueVariants::String inner => @string(inner), + DefaultValueVariants::Double inner => @double(inner), + DefaultValueVariants::Bool inner => @bool(inner), + DefaultValueVariants::Mixed inner => mixed(inner), + _ => throw new InvalidOperationException(), + }; + } + + public abstract void Validate(); +} + +sealed class DefaultValueConverter : JsonConverter +{ + public override DefaultValue? Read( + ref Utf8JsonReader reader, + Type typeToConvert, + JsonSerializerOptions options + ) + { + List exceptions = []; + + try + { + var deserialized = JsonSerializer.Deserialize(ref reader, options); + if (deserialized != null) + { + return new DefaultValueVariants::String(deserialized); + } + } + catch (JsonException e) + { + exceptions.Add(e); + } + + try + { + return new DefaultValueVariants::Double( + JsonSerializer.Deserialize(ref reader, options) + ); + } + catch (JsonException e) + { + exceptions.Add(e); + } + + try + { + return new DefaultValueVariants::Bool( + JsonSerializer.Deserialize(ref reader, options) + ); + } + catch (JsonException e) + { + exceptions.Add(e); + } + + try + { + var deserialized = JsonSerializer.Deserialize>( + ref reader, + options + ); + if (deserialized != null) + { + return new DefaultValueVariants::Mixed(deserialized); + } + } + catch (JsonException e) + { + exceptions.Add(e); + } + + throw new AggregateException(exceptions); + } + + public override void Write( + Utf8JsonWriter writer, + DefaultValue value, + JsonSerializerOptions options + ) + { + object variant = value switch + { + DefaultValueVariants::String(var @string) => @string, + DefaultValueVariants::Double(var @double) => @double, + DefaultValueVariants::Bool(var @bool) => @bool, + DefaultValueVariants::Mixed(var mixed) => mixed, + _ => throw new ArgumentOutOfRangeException(nameof(value)), + }; + JsonSerializer.Serialize(writer, variant, options); + } +} diff --git a/src/Imagekit/Models/CustomMetadataFields/CustomMetadataFieldUpdateParamsProperties/SchemaProperties/DefaultValueProperties/UnnamedSchemaWithArrayParent2.cs b/src/Imagekit/Models/CustomMetadataFields/CustomMetadataFieldUpdateParamsProperties/SchemaProperties/DefaultValueProperties/UnnamedSchemaWithArrayParent2.cs new file mode 100644 index 00000000..2534e6a3 --- /dev/null +++ b/src/Imagekit/Models/CustomMetadataFields/CustomMetadataFieldUpdateParamsProperties/SchemaProperties/DefaultValueProperties/UnnamedSchemaWithArrayParent2.cs @@ -0,0 +1,145 @@ +using System; +using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; +using System.Text.Json; +using System.Text.Json.Serialization; +using UnnamedSchemaWithArrayParent2Variants = Imagekit.Models.CustomMetadataFields.CustomMetadataFieldUpdateParamsProperties.SchemaProperties.DefaultValueProperties.UnnamedSchemaWithArrayParent2Variants; + +namespace Imagekit.Models.CustomMetadataFields.CustomMetadataFieldUpdateParamsProperties.SchemaProperties.DefaultValueProperties; + +[JsonConverter(typeof(UnnamedSchemaWithArrayParent2Converter))] +public abstract record class UnnamedSchemaWithArrayParent2 +{ + internal UnnamedSchemaWithArrayParent2() { } + + public static implicit operator UnnamedSchemaWithArrayParent2(string value) => + new UnnamedSchemaWithArrayParent2Variants::String(value); + + public static implicit operator UnnamedSchemaWithArrayParent2(double value) => + new UnnamedSchemaWithArrayParent2Variants::Double(value); + + public static implicit operator UnnamedSchemaWithArrayParent2(bool value) => + new UnnamedSchemaWithArrayParent2Variants::Bool(value); + + public bool TryPickString([NotNullWhen(true)] out string? value) + { + value = (this as UnnamedSchemaWithArrayParent2Variants::String)?.Value; + return value != null; + } + + public bool TryPickDouble([NotNullWhen(true)] out double? value) + { + value = (this as UnnamedSchemaWithArrayParent2Variants::Double)?.Value; + return value != null; + } + + public bool TryPickBool([NotNullWhen(true)] out bool? value) + { + value = (this as UnnamedSchemaWithArrayParent2Variants::Bool)?.Value; + return value != null; + } + + public void Switch( + Action @string, + Action @double, + Action @bool + ) + { + switch (this) + { + case UnnamedSchemaWithArrayParent2Variants::String inner: + @string(inner); + break; + case UnnamedSchemaWithArrayParent2Variants::Double inner: + @double(inner); + break; + case UnnamedSchemaWithArrayParent2Variants::Bool inner: + @bool(inner); + break; + default: + throw new InvalidOperationException(); + } + } + + public T Match( + Func @string, + Func @double, + Func @bool + ) + { + return this switch + { + UnnamedSchemaWithArrayParent2Variants::String inner => @string(inner), + UnnamedSchemaWithArrayParent2Variants::Double inner => @double(inner), + UnnamedSchemaWithArrayParent2Variants::Bool inner => @bool(inner), + _ => throw new InvalidOperationException(), + }; + } + + public abstract void Validate(); +} + +sealed class UnnamedSchemaWithArrayParent2Converter : JsonConverter +{ + public override UnnamedSchemaWithArrayParent2? Read( + ref Utf8JsonReader reader, + Type typeToConvert, + JsonSerializerOptions options + ) + { + List exceptions = []; + + try + { + var deserialized = JsonSerializer.Deserialize(ref reader, options); + if (deserialized != null) + { + return new UnnamedSchemaWithArrayParent2Variants::String(deserialized); + } + } + catch (JsonException e) + { + exceptions.Add(e); + } + + try + { + return new UnnamedSchemaWithArrayParent2Variants::Double( + JsonSerializer.Deserialize(ref reader, options) + ); + } + catch (JsonException e) + { + exceptions.Add(e); + } + + try + { + return new UnnamedSchemaWithArrayParent2Variants::Bool( + JsonSerializer.Deserialize(ref reader, options) + ); + } + catch (JsonException e) + { + exceptions.Add(e); + } + + throw new AggregateException(exceptions); + } + + public override void Write( + Utf8JsonWriter writer, + UnnamedSchemaWithArrayParent2 value, + JsonSerializerOptions options + ) + { + object variant = value switch + { + UnnamedSchemaWithArrayParent2Variants::String(var @string) => @string, + UnnamedSchemaWithArrayParent2Variants::Double(var @double) => @double, + UnnamedSchemaWithArrayParent2Variants::Bool(var @bool) => @bool, + _ => throw new ArgumentOutOfRangeException(nameof(value)), + }; + JsonSerializer.Serialize(writer, variant, options); + } +} diff --git a/src/Imagekit/Models/CustomMetadataFields/CustomMetadataFieldUpdateParamsProperties/SchemaProperties/DefaultValueProperties/UnnamedSchemaWithArrayParent2Variants/All.cs b/src/Imagekit/Models/CustomMetadataFields/CustomMetadataFieldUpdateParamsProperties/SchemaProperties/DefaultValueProperties/UnnamedSchemaWithArrayParent2Variants/All.cs new file mode 100644 index 00000000..9907932a --- /dev/null +++ b/src/Imagekit/Models/CustomMetadataFields/CustomMetadataFieldUpdateParamsProperties/SchemaProperties/DefaultValueProperties/UnnamedSchemaWithArrayParent2Variants/All.cs @@ -0,0 +1,35 @@ +namespace Imagekit.Models.CustomMetadataFields.CustomMetadataFieldUpdateParamsProperties.SchemaProperties.DefaultValueProperties.UnnamedSchemaWithArrayParent2Variants; + +public sealed record class String(string Value) + : UnnamedSchemaWithArrayParent2, + IVariant +{ + public static String From(string value) + { + return new(value); + } + + public override void Validate() { } +} + +public sealed record class Double(double Value) + : UnnamedSchemaWithArrayParent2, + IVariant +{ + public static Double From(double value) + { + return new(value); + } + + public override void Validate() { } +} + +public sealed record class Bool(bool Value) : UnnamedSchemaWithArrayParent2, IVariant +{ + public static Bool From(bool value) + { + return new(value); + } + + public override void Validate() { } +} diff --git a/src/Imagekit/Models/CustomMetadataFields/CustomMetadataFieldUpdateParamsProperties/SchemaProperties/DefaultValueVariants/All.cs b/src/Imagekit/Models/CustomMetadataFields/CustomMetadataFieldUpdateParamsProperties/SchemaProperties/DefaultValueVariants/All.cs new file mode 100644 index 00000000..0dec8fad --- /dev/null +++ b/src/Imagekit/Models/CustomMetadataFields/CustomMetadataFieldUpdateParamsProperties/SchemaProperties/DefaultValueVariants/All.cs @@ -0,0 +1,50 @@ +using System.Collections.Generic; +using Imagekit.Models.CustomMetadataFields.CustomMetadataFieldUpdateParamsProperties.SchemaProperties.DefaultValueProperties; + +namespace Imagekit.Models.CustomMetadataFields.CustomMetadataFieldUpdateParamsProperties.SchemaProperties.DefaultValueVariants; + +public sealed record class String(string Value) : DefaultValue, IVariant +{ + public static String From(string value) + { + return new(value); + } + + public override void Validate() { } +} + +public sealed record class Double(double Value) : DefaultValue, IVariant +{ + public static Double From(double value) + { + return new(value); + } + + public override void Validate() { } +} + +public sealed record class Bool(bool Value) : DefaultValue, IVariant +{ + public static Bool From(bool value) + { + return new(value); + } + + public override void Validate() { } +} + +/// +/// Default value should be of type array when custom metadata field type is set to +/// `MultiSelect`. +/// +public sealed record class Mixed(List Value) + : DefaultValue, + IVariant> +{ + public static Mixed From(List value) + { + return new(value); + } + + public override void Validate() { } +} diff --git a/src/Imagekit/Models/CustomMetadataFields/CustomMetadataFieldUpdateParamsProperties/SchemaProperties/MaxValue.cs b/src/Imagekit/Models/CustomMetadataFields/CustomMetadataFieldUpdateParamsProperties/SchemaProperties/MaxValue.cs new file mode 100644 index 00000000..362c3574 --- /dev/null +++ b/src/Imagekit/Models/CustomMetadataFields/CustomMetadataFieldUpdateParamsProperties/SchemaProperties/MaxValue.cs @@ -0,0 +1,117 @@ +using System; +using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; +using System.Text.Json; +using System.Text.Json.Serialization; +using MaxValueVariants = Imagekit.Models.CustomMetadataFields.CustomMetadataFieldUpdateParamsProperties.SchemaProperties.MaxValueVariants; + +namespace Imagekit.Models.CustomMetadataFields.CustomMetadataFieldUpdateParamsProperties.SchemaProperties; + +/// +/// Maximum value of the field. Only set this property if field type is `Date` or +/// `Number`. For `Date` type field, set the minimum date in ISO8601 string format. +/// For `Number` type field, set the minimum numeric value. +/// +[JsonConverter(typeof(MaxValueConverter))] +public abstract record class MaxValue +{ + internal MaxValue() { } + + public static implicit operator MaxValue(string value) => new MaxValueVariants::String(value); + + public static implicit operator MaxValue(double value) => new MaxValueVariants::Double(value); + + public bool TryPickString([NotNullWhen(true)] out string? value) + { + value = (this as MaxValueVariants::String)?.Value; + return value != null; + } + + public bool TryPickDouble([NotNullWhen(true)] out double? value) + { + value = (this as MaxValueVariants::Double)?.Value; + return value != null; + } + + public void Switch( + Action @string, + Action @double + ) + { + switch (this) + { + case MaxValueVariants::String inner: + @string(inner); + break; + case MaxValueVariants::Double inner: + @double(inner); + break; + default: + throw new InvalidOperationException(); + } + } + + public T Match( + Func @string, + Func @double + ) + { + return this switch + { + MaxValueVariants::String inner => @string(inner), + MaxValueVariants::Double inner => @double(inner), + _ => throw new InvalidOperationException(), + }; + } + + public abstract void Validate(); +} + +sealed class MaxValueConverter : JsonConverter +{ + public override MaxValue? Read( + ref Utf8JsonReader reader, + Type typeToConvert, + JsonSerializerOptions options + ) + { + List exceptions = []; + + try + { + var deserialized = JsonSerializer.Deserialize(ref reader, options); + if (deserialized != null) + { + return new MaxValueVariants::String(deserialized); + } + } + catch (JsonException e) + { + exceptions.Add(e); + } + + try + { + return new MaxValueVariants::Double( + JsonSerializer.Deserialize(ref reader, options) + ); + } + catch (JsonException e) + { + exceptions.Add(e); + } + + throw new AggregateException(exceptions); + } + + public override void Write(Utf8JsonWriter writer, MaxValue value, JsonSerializerOptions options) + { + object variant = value switch + { + MaxValueVariants::String(var @string) => @string, + MaxValueVariants::Double(var @double) => @double, + _ => throw new ArgumentOutOfRangeException(nameof(value)), + }; + JsonSerializer.Serialize(writer, variant, options); + } +} diff --git a/src/Imagekit/Models/CustomMetadataFields/CustomMetadataFieldUpdateParamsProperties/SchemaProperties/MaxValueVariants/All.cs b/src/Imagekit/Models/CustomMetadataFields/CustomMetadataFieldUpdateParamsProperties/SchemaProperties/MaxValueVariants/All.cs new file mode 100644 index 00000000..77dc33f7 --- /dev/null +++ b/src/Imagekit/Models/CustomMetadataFields/CustomMetadataFieldUpdateParamsProperties/SchemaProperties/MaxValueVariants/All.cs @@ -0,0 +1,21 @@ +namespace Imagekit.Models.CustomMetadataFields.CustomMetadataFieldUpdateParamsProperties.SchemaProperties.MaxValueVariants; + +public sealed record class String(string Value) : MaxValue, IVariant +{ + public static String From(string value) + { + return new(value); + } + + public override void Validate() { } +} + +public sealed record class Double(double Value) : MaxValue, IVariant +{ + public static Double From(double value) + { + return new(value); + } + + public override void Validate() { } +} diff --git a/src/Imagekit/Models/CustomMetadataFields/CustomMetadataFieldUpdateParamsProperties/SchemaProperties/MinValue.cs b/src/Imagekit/Models/CustomMetadataFields/CustomMetadataFieldUpdateParamsProperties/SchemaProperties/MinValue.cs new file mode 100644 index 00000000..7ab361fc --- /dev/null +++ b/src/Imagekit/Models/CustomMetadataFields/CustomMetadataFieldUpdateParamsProperties/SchemaProperties/MinValue.cs @@ -0,0 +1,117 @@ +using System; +using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; +using System.Text.Json; +using System.Text.Json.Serialization; +using MinValueVariants = Imagekit.Models.CustomMetadataFields.CustomMetadataFieldUpdateParamsProperties.SchemaProperties.MinValueVariants; + +namespace Imagekit.Models.CustomMetadataFields.CustomMetadataFieldUpdateParamsProperties.SchemaProperties; + +/// +/// Minimum value of the field. Only set this property if field type is `Date` or +/// `Number`. For `Date` type field, set the minimum date in ISO8601 string format. +/// For `Number` type field, set the minimum numeric value. +/// +[JsonConverter(typeof(MinValueConverter))] +public abstract record class MinValue +{ + internal MinValue() { } + + public static implicit operator MinValue(string value) => new MinValueVariants::String(value); + + public static implicit operator MinValue(double value) => new MinValueVariants::Double(value); + + public bool TryPickString([NotNullWhen(true)] out string? value) + { + value = (this as MinValueVariants::String)?.Value; + return value != null; + } + + public bool TryPickDouble([NotNullWhen(true)] out double? value) + { + value = (this as MinValueVariants::Double)?.Value; + return value != null; + } + + public void Switch( + Action @string, + Action @double + ) + { + switch (this) + { + case MinValueVariants::String inner: + @string(inner); + break; + case MinValueVariants::Double inner: + @double(inner); + break; + default: + throw new InvalidOperationException(); + } + } + + public T Match( + Func @string, + Func @double + ) + { + return this switch + { + MinValueVariants::String inner => @string(inner), + MinValueVariants::Double inner => @double(inner), + _ => throw new InvalidOperationException(), + }; + } + + public abstract void Validate(); +} + +sealed class MinValueConverter : JsonConverter +{ + public override MinValue? Read( + ref Utf8JsonReader reader, + Type typeToConvert, + JsonSerializerOptions options + ) + { + List exceptions = []; + + try + { + var deserialized = JsonSerializer.Deserialize(ref reader, options); + if (deserialized != null) + { + return new MinValueVariants::String(deserialized); + } + } + catch (JsonException e) + { + exceptions.Add(e); + } + + try + { + return new MinValueVariants::Double( + JsonSerializer.Deserialize(ref reader, options) + ); + } + catch (JsonException e) + { + exceptions.Add(e); + } + + throw new AggregateException(exceptions); + } + + public override void Write(Utf8JsonWriter writer, MinValue value, JsonSerializerOptions options) + { + object variant = value switch + { + MinValueVariants::String(var @string) => @string, + MinValueVariants::Double(var @double) => @double, + _ => throw new ArgumentOutOfRangeException(nameof(value)), + }; + JsonSerializer.Serialize(writer, variant, options); + } +} diff --git a/src/Imagekit/Models/CustomMetadataFields/CustomMetadataFieldUpdateParamsProperties/SchemaProperties/MinValueVariants/All.cs b/src/Imagekit/Models/CustomMetadataFields/CustomMetadataFieldUpdateParamsProperties/SchemaProperties/MinValueVariants/All.cs new file mode 100644 index 00000000..c0acd9c9 --- /dev/null +++ b/src/Imagekit/Models/CustomMetadataFields/CustomMetadataFieldUpdateParamsProperties/SchemaProperties/MinValueVariants/All.cs @@ -0,0 +1,21 @@ +namespace Imagekit.Models.CustomMetadataFields.CustomMetadataFieldUpdateParamsProperties.SchemaProperties.MinValueVariants; + +public sealed record class String(string Value) : MinValue, IVariant +{ + public static String From(string value) + { + return new(value); + } + + public override void Validate() { } +} + +public sealed record class Double(double Value) : MinValue, IVariant +{ + public static Double From(double value) + { + return new(value); + } + + public override void Validate() { } +} diff --git a/src/Imagekit/Models/CustomMetadataFields/CustomMetadataFieldUpdateParamsProperties/SchemaProperties/SelectOption.cs b/src/Imagekit/Models/CustomMetadataFields/CustomMetadataFieldUpdateParamsProperties/SchemaProperties/SelectOption.cs new file mode 100644 index 00000000..172d2d2f --- /dev/null +++ b/src/Imagekit/Models/CustomMetadataFields/CustomMetadataFieldUpdateParamsProperties/SchemaProperties/SelectOption.cs @@ -0,0 +1,145 @@ +using System; +using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; +using System.Text.Json; +using System.Text.Json.Serialization; +using SelectOptionVariants = Imagekit.Models.CustomMetadataFields.CustomMetadataFieldUpdateParamsProperties.SchemaProperties.SelectOptionVariants; + +namespace Imagekit.Models.CustomMetadataFields.CustomMetadataFieldUpdateParamsProperties.SchemaProperties; + +[JsonConverter(typeof(SelectOptionConverter))] +public abstract record class SelectOption +{ + internal SelectOption() { } + + public static implicit operator SelectOption(string value) => + new SelectOptionVariants::String(value); + + public static implicit operator SelectOption(double value) => + new SelectOptionVariants::Double(value); + + public static implicit operator SelectOption(bool value) => + new SelectOptionVariants::Bool(value); + + public bool TryPickString([NotNullWhen(true)] out string? value) + { + value = (this as SelectOptionVariants::String)?.Value; + return value != null; + } + + public bool TryPickDouble([NotNullWhen(true)] out double? value) + { + value = (this as SelectOptionVariants::Double)?.Value; + return value != null; + } + + public bool TryPickBool([NotNullWhen(true)] out bool? value) + { + value = (this as SelectOptionVariants::Bool)?.Value; + return value != null; + } + + public void Switch( + Action @string, + Action @double, + Action @bool + ) + { + switch (this) + { + case SelectOptionVariants::String inner: + @string(inner); + break; + case SelectOptionVariants::Double inner: + @double(inner); + break; + case SelectOptionVariants::Bool inner: + @bool(inner); + break; + default: + throw new InvalidOperationException(); + } + } + + public T Match( + Func @string, + Func @double, + Func @bool + ) + { + return this switch + { + SelectOptionVariants::String inner => @string(inner), + SelectOptionVariants::Double inner => @double(inner), + SelectOptionVariants::Bool inner => @bool(inner), + _ => throw new InvalidOperationException(), + }; + } + + public abstract void Validate(); +} + +sealed class SelectOptionConverter : JsonConverter +{ + public override SelectOption? Read( + ref Utf8JsonReader reader, + Type typeToConvert, + JsonSerializerOptions options + ) + { + List exceptions = []; + + try + { + var deserialized = JsonSerializer.Deserialize(ref reader, options); + if (deserialized != null) + { + return new SelectOptionVariants::String(deserialized); + } + } + catch (JsonException e) + { + exceptions.Add(e); + } + + try + { + return new SelectOptionVariants::Double( + JsonSerializer.Deserialize(ref reader, options) + ); + } + catch (JsonException e) + { + exceptions.Add(e); + } + + try + { + return new SelectOptionVariants::Bool( + JsonSerializer.Deserialize(ref reader, options) + ); + } + catch (JsonException e) + { + exceptions.Add(e); + } + + throw new AggregateException(exceptions); + } + + public override void Write( + Utf8JsonWriter writer, + SelectOption value, + JsonSerializerOptions options + ) + { + object variant = value switch + { + SelectOptionVariants::String(var @string) => @string, + SelectOptionVariants::Double(var @double) => @double, + SelectOptionVariants::Bool(var @bool) => @bool, + _ => throw new ArgumentOutOfRangeException(nameof(value)), + }; + JsonSerializer.Serialize(writer, variant, options); + } +} diff --git a/src/Imagekit/Models/CustomMetadataFields/CustomMetadataFieldUpdateParamsProperties/SchemaProperties/SelectOptionVariants/All.cs b/src/Imagekit/Models/CustomMetadataFields/CustomMetadataFieldUpdateParamsProperties/SchemaProperties/SelectOptionVariants/All.cs new file mode 100644 index 00000000..419bfb5c --- /dev/null +++ b/src/Imagekit/Models/CustomMetadataFields/CustomMetadataFieldUpdateParamsProperties/SchemaProperties/SelectOptionVariants/All.cs @@ -0,0 +1,31 @@ +namespace Imagekit.Models.CustomMetadataFields.CustomMetadataFieldUpdateParamsProperties.SchemaProperties.SelectOptionVariants; + +public sealed record class String(string Value) : SelectOption, IVariant +{ + public static String From(string value) + { + return new(value); + } + + public override void Validate() { } +} + +public sealed record class Double(double Value) : SelectOption, IVariant +{ + public static Double From(double value) + { + return new(value); + } + + public override void Validate() { } +} + +public sealed record class Bool(bool Value) : SelectOption, IVariant +{ + public static Bool From(bool value) + { + return new(value); + } + + public override void Validate() { } +} diff --git a/src/Imagekit/Models/Files/Bulk/BulkAddTagsParams.cs b/src/Imagekit/Models/Files/Bulk/BulkAddTagsParams.cs new file mode 100644 index 00000000..6cd055a9 --- /dev/null +++ b/src/Imagekit/Models/Files/Bulk/BulkAddTagsParams.cs @@ -0,0 +1,86 @@ +using System; +using System.Collections.Generic; +using System.Net.Http; +using System.Text; +using System.Text.Json; + +namespace Imagekit.Models.Files.Bulk; + +/// +/// This API adds tags to multiple files in bulk. A maximum of 50 files can be specified +/// at a time. +/// +public sealed record class BulkAddTagsParams : ParamsBase +{ + public Dictionary BodyProperties { get; set; } = []; + + /// + /// An array of fileIds to which you want to add tags. + /// + public required List FileIDs + { + get + { + if (!this.BodyProperties.TryGetValue("fileIds", out JsonElement element)) + throw new ArgumentOutOfRangeException("fileIds", "Missing required argument"); + + return JsonSerializer.Deserialize>(element, ModelBase.SerializerOptions) + ?? throw new ArgumentNullException("fileIds"); + } + set + { + this.BodyProperties["fileIds"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + /// + /// An array of tags that you want to add to the files. + /// + public required List Tags + { + get + { + if (!this.BodyProperties.TryGetValue("tags", out JsonElement element)) + throw new ArgumentOutOfRangeException("tags", "Missing required argument"); + + return JsonSerializer.Deserialize>(element, ModelBase.SerializerOptions) + ?? throw new ArgumentNullException("tags"); + } + set + { + this.BodyProperties["tags"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + public override Uri Url(IImageKitClient client) + { + return new UriBuilder(client.BaseUrl.ToString().TrimEnd('/') + "/v1/files/addTags") + { + Query = this.QueryString(client), + }.Uri; + } + + public StringContent BodyContent() + { + return new( + JsonSerializer.Serialize(this.BodyProperties), + Encoding.UTF8, + "application/json" + ); + } + + public void AddHeadersToRequest(HttpRequestMessage request, IImageKitClient client) + { + ParamsBase.AddDefaultHeaders(request, client); + foreach (var item in this.HeaderProperties) + { + ParamsBase.AddHeaderElementToRequest(request, item.Key, item.Value); + } + } +} diff --git a/src/Imagekit/Models/Files/Bulk/BulkAddTagsResponse.cs b/src/Imagekit/Models/Files/Bulk/BulkAddTagsResponse.cs new file mode 100644 index 00000000..c346fd8b --- /dev/null +++ b/src/Imagekit/Models/Files/Bulk/BulkAddTagsResponse.cs @@ -0,0 +1,54 @@ +using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; +using System.Text.Json; +using System.Text.Json.Serialization; + +namespace Imagekit.Models.Files.Bulk; + +[JsonConverter(typeof(ModelConverter))] +public sealed record class BulkAddTagsResponse : ModelBase, IFromRaw +{ + /// + /// An array of fileIds that in which tags were successfully added. + /// + public List? SuccessfullyUpdatedFileIDs + { + get + { + if (!this.Properties.TryGetValue("successfullyUpdatedFileIds", out JsonElement element)) + return null; + + return JsonSerializer.Deserialize?>(element, ModelBase.SerializerOptions); + } + set + { + this.Properties["successfullyUpdatedFileIds"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + public override void Validate() + { + foreach (var item in this.SuccessfullyUpdatedFileIDs ?? []) + { + _ = item; + } + } + + public BulkAddTagsResponse() { } + +#pragma warning disable CS8618 + [SetsRequiredMembers] + BulkAddTagsResponse(Dictionary properties) + { + Properties = properties; + } +#pragma warning restore CS8618 + + public static BulkAddTagsResponse FromRawUnchecked(Dictionary properties) + { + return new(properties); + } +} diff --git a/src/Imagekit/Models/Files/Bulk/BulkDeleteParams.cs b/src/Imagekit/Models/Files/Bulk/BulkDeleteParams.cs new file mode 100644 index 00000000..abca4e63 --- /dev/null +++ b/src/Imagekit/Models/Files/Bulk/BulkDeleteParams.cs @@ -0,0 +1,71 @@ +using System; +using System.Collections.Generic; +using System.Net.Http; +using System.Text; +using System.Text.Json; + +namespace Imagekit.Models.Files.Bulk; + +/// +/// This API deletes multiple files and all their file versions permanently. +/// +/// Note: If a file or specific transformation has been requested in the past, then +/// the response is cached. Deleting a file does not purge the cache. You can purge +/// the cache using purge cache API. +/// +/// A maximum of 100 files can be deleted at a time. +/// +public sealed record class BulkDeleteParams : ParamsBase +{ + public Dictionary BodyProperties { get; set; } = []; + + /// + /// An array of fileIds which you want to delete. + /// + public required List FileIDs + { + get + { + if (!this.BodyProperties.TryGetValue("fileIds", out JsonElement element)) + throw new ArgumentOutOfRangeException("fileIds", "Missing required argument"); + + return JsonSerializer.Deserialize>(element, ModelBase.SerializerOptions) + ?? throw new ArgumentNullException("fileIds"); + } + set + { + this.BodyProperties["fileIds"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + public override Uri Url(IImageKitClient client) + { + return new UriBuilder( + client.BaseUrl.ToString().TrimEnd('/') + "/v1/files/batch/deleteByFileIds" + ) + { + Query = this.QueryString(client), + }.Uri; + } + + public StringContent BodyContent() + { + return new( + JsonSerializer.Serialize(this.BodyProperties), + Encoding.UTF8, + "application/json" + ); + } + + public void AddHeadersToRequest(HttpRequestMessage request, IImageKitClient client) + { + ParamsBase.AddDefaultHeaders(request, client); + foreach (var item in this.HeaderProperties) + { + ParamsBase.AddHeaderElementToRequest(request, item.Key, item.Value); + } + } +} diff --git a/src/Imagekit/Models/Files/Bulk/BulkDeleteResponse.cs b/src/Imagekit/Models/Files/Bulk/BulkDeleteResponse.cs new file mode 100644 index 00000000..e62d675a --- /dev/null +++ b/src/Imagekit/Models/Files/Bulk/BulkDeleteResponse.cs @@ -0,0 +1,54 @@ +using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; +using System.Text.Json; +using System.Text.Json.Serialization; + +namespace Imagekit.Models.Files.Bulk; + +[JsonConverter(typeof(ModelConverter))] +public sealed record class BulkDeleteResponse : ModelBase, IFromRaw +{ + /// + /// An array of fileIds that were successfully deleted. + /// + public List? SuccessfullyDeletedFileIDs + { + get + { + if (!this.Properties.TryGetValue("successfullyDeletedFileIds", out JsonElement element)) + return null; + + return JsonSerializer.Deserialize?>(element, ModelBase.SerializerOptions); + } + set + { + this.Properties["successfullyDeletedFileIds"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + public override void Validate() + { + foreach (var item in this.SuccessfullyDeletedFileIDs ?? []) + { + _ = item; + } + } + + public BulkDeleteResponse() { } + +#pragma warning disable CS8618 + [SetsRequiredMembers] + BulkDeleteResponse(Dictionary properties) + { + Properties = properties; + } +#pragma warning restore CS8618 + + public static BulkDeleteResponse FromRawUnchecked(Dictionary properties) + { + return new(properties); + } +} diff --git a/src/Imagekit/Models/Files/Bulk/BulkRemoveAITagsParams.cs b/src/Imagekit/Models/Files/Bulk/BulkRemoveAITagsParams.cs new file mode 100644 index 00000000..358f851d --- /dev/null +++ b/src/Imagekit/Models/Files/Bulk/BulkRemoveAITagsParams.cs @@ -0,0 +1,86 @@ +using System; +using System.Collections.Generic; +using System.Net.Http; +using System.Text; +using System.Text.Json; + +namespace Imagekit.Models.Files.Bulk; + +/// +/// This API removes AITags from multiple files in bulk. A maximum of 50 files can +/// be specified at a time. +/// +public sealed record class BulkRemoveAITagsParams : ParamsBase +{ + public Dictionary BodyProperties { get; set; } = []; + + /// + /// An array of AITags that you want to remove from the files. + /// + public required List AITags + { + get + { + if (!this.BodyProperties.TryGetValue("AITags", out JsonElement element)) + throw new ArgumentOutOfRangeException("AITags", "Missing required argument"); + + return JsonSerializer.Deserialize>(element, ModelBase.SerializerOptions) + ?? throw new ArgumentNullException("AITags"); + } + set + { + this.BodyProperties["AITags"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + /// + /// An array of fileIds from which you want to remove AITags. + /// + public required List FileIDs + { + get + { + if (!this.BodyProperties.TryGetValue("fileIds", out JsonElement element)) + throw new ArgumentOutOfRangeException("fileIds", "Missing required argument"); + + return JsonSerializer.Deserialize>(element, ModelBase.SerializerOptions) + ?? throw new ArgumentNullException("fileIds"); + } + set + { + this.BodyProperties["fileIds"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + public override Uri Url(IImageKitClient client) + { + return new UriBuilder(client.BaseUrl.ToString().TrimEnd('/') + "/v1/files/removeAITags") + { + Query = this.QueryString(client), + }.Uri; + } + + public StringContent BodyContent() + { + return new( + JsonSerializer.Serialize(this.BodyProperties), + Encoding.UTF8, + "application/json" + ); + } + + public void AddHeadersToRequest(HttpRequestMessage request, IImageKitClient client) + { + ParamsBase.AddDefaultHeaders(request, client); + foreach (var item in this.HeaderProperties) + { + ParamsBase.AddHeaderElementToRequest(request, item.Key, item.Value); + } + } +} diff --git a/src/Imagekit/Models/Files/Bulk/BulkRemoveAITagsResponse.cs b/src/Imagekit/Models/Files/Bulk/BulkRemoveAITagsResponse.cs new file mode 100644 index 00000000..8eb52d35 --- /dev/null +++ b/src/Imagekit/Models/Files/Bulk/BulkRemoveAITagsResponse.cs @@ -0,0 +1,56 @@ +using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; +using System.Text.Json; +using System.Text.Json.Serialization; + +namespace Imagekit.Models.Files.Bulk; + +[JsonConverter(typeof(ModelConverter))] +public sealed record class BulkRemoveAITagsResponse : ModelBase, IFromRaw +{ + /// + /// An array of fileIds that in which AITags were successfully removed. + /// + public List? SuccessfullyUpdatedFileIDs + { + get + { + if (!this.Properties.TryGetValue("successfullyUpdatedFileIds", out JsonElement element)) + return null; + + return JsonSerializer.Deserialize?>(element, ModelBase.SerializerOptions); + } + set + { + this.Properties["successfullyUpdatedFileIds"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + public override void Validate() + { + foreach (var item in this.SuccessfullyUpdatedFileIDs ?? []) + { + _ = item; + } + } + + public BulkRemoveAITagsResponse() { } + +#pragma warning disable CS8618 + [SetsRequiredMembers] + BulkRemoveAITagsResponse(Dictionary properties) + { + Properties = properties; + } +#pragma warning restore CS8618 + + public static BulkRemoveAITagsResponse FromRawUnchecked( + Dictionary properties + ) + { + return new(properties); + } +} diff --git a/src/Imagekit/Models/Files/Bulk/BulkRemoveTagsParams.cs b/src/Imagekit/Models/Files/Bulk/BulkRemoveTagsParams.cs new file mode 100644 index 00000000..db0b9eff --- /dev/null +++ b/src/Imagekit/Models/Files/Bulk/BulkRemoveTagsParams.cs @@ -0,0 +1,86 @@ +using System; +using System.Collections.Generic; +using System.Net.Http; +using System.Text; +using System.Text.Json; + +namespace Imagekit.Models.Files.Bulk; + +/// +/// This API removes tags from multiple files in bulk. A maximum of 50 files can +/// be specified at a time. +/// +public sealed record class BulkRemoveTagsParams : ParamsBase +{ + public Dictionary BodyProperties { get; set; } = []; + + /// + /// An array of fileIds from which you want to remove tags. + /// + public required List FileIDs + { + get + { + if (!this.BodyProperties.TryGetValue("fileIds", out JsonElement element)) + throw new ArgumentOutOfRangeException("fileIds", "Missing required argument"); + + return JsonSerializer.Deserialize>(element, ModelBase.SerializerOptions) + ?? throw new ArgumentNullException("fileIds"); + } + set + { + this.BodyProperties["fileIds"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + /// + /// An array of tags that you want to remove from the files. + /// + public required List Tags + { + get + { + if (!this.BodyProperties.TryGetValue("tags", out JsonElement element)) + throw new ArgumentOutOfRangeException("tags", "Missing required argument"); + + return JsonSerializer.Deserialize>(element, ModelBase.SerializerOptions) + ?? throw new ArgumentNullException("tags"); + } + set + { + this.BodyProperties["tags"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + public override Uri Url(IImageKitClient client) + { + return new UriBuilder(client.BaseUrl.ToString().TrimEnd('/') + "/v1/files/removeTags") + { + Query = this.QueryString(client), + }.Uri; + } + + public StringContent BodyContent() + { + return new( + JsonSerializer.Serialize(this.BodyProperties), + Encoding.UTF8, + "application/json" + ); + } + + public void AddHeadersToRequest(HttpRequestMessage request, IImageKitClient client) + { + ParamsBase.AddDefaultHeaders(request, client); + foreach (var item in this.HeaderProperties) + { + ParamsBase.AddHeaderElementToRequest(request, item.Key, item.Value); + } + } +} diff --git a/src/Imagekit/Models/Files/Bulk/BulkRemoveTagsResponse.cs b/src/Imagekit/Models/Files/Bulk/BulkRemoveTagsResponse.cs new file mode 100644 index 00000000..453899cb --- /dev/null +++ b/src/Imagekit/Models/Files/Bulk/BulkRemoveTagsResponse.cs @@ -0,0 +1,56 @@ +using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; +using System.Text.Json; +using System.Text.Json.Serialization; + +namespace Imagekit.Models.Files.Bulk; + +[JsonConverter(typeof(ModelConverter))] +public sealed record class BulkRemoveTagsResponse : ModelBase, IFromRaw +{ + /// + /// An array of fileIds that in which tags were successfully removed. + /// + public List? SuccessfullyUpdatedFileIDs + { + get + { + if (!this.Properties.TryGetValue("successfullyUpdatedFileIds", out JsonElement element)) + return null; + + return JsonSerializer.Deserialize?>(element, ModelBase.SerializerOptions); + } + set + { + this.Properties["successfullyUpdatedFileIds"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + public override void Validate() + { + foreach (var item in this.SuccessfullyUpdatedFileIDs ?? []) + { + _ = item; + } + } + + public BulkRemoveTagsResponse() { } + +#pragma warning disable CS8618 + [SetsRequiredMembers] + BulkRemoveTagsResponse(Dictionary properties) + { + Properties = properties; + } +#pragma warning restore CS8618 + + public static BulkRemoveTagsResponse FromRawUnchecked( + Dictionary properties + ) + { + return new(properties); + } +} diff --git a/src/Imagekit/Models/Files/File.cs b/src/Imagekit/Models/Files/File.cs new file mode 100644 index 00000000..0840cb97 --- /dev/null +++ b/src/Imagekit/Models/Files/File.cs @@ -0,0 +1,550 @@ +using System; +using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; +using System.Text.Json; +using System.Text.Json.Serialization; +using FileProperties = Imagekit.Models.Files.FileProperties; + +namespace Imagekit.Models.Files; + +/// +/// Object containing details of a file or file version. +/// +[JsonConverter(typeof(ModelConverter))] +public sealed record class File : ModelBase, IFromRaw +{ + /// + /// An array of tags assigned to the file by auto tagging. + /// + public List? AITags + { + get + { + if (!this.Properties.TryGetValue("AITags", out JsonElement element)) + return null; + + return JsonSerializer.Deserialize?>( + element, + ModelBase.SerializerOptions + ); + } + set + { + this.Properties["AITags"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + /// + /// Date and time when the file was uploaded. The date and time is in ISO8601 + /// format. + /// + public DateTime? CreatedAt + { + get + { + if (!this.Properties.TryGetValue("createdAt", out JsonElement element)) + return null; + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions); + } + set + { + this.Properties["createdAt"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + /// + /// An string with custom coordinates of the file. + /// + public string? CustomCoordinates + { + get + { + if (!this.Properties.TryGetValue("customCoordinates", out JsonElement element)) + return null; + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions); + } + set + { + this.Properties["customCoordinates"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + /// + /// An object with custom metadata for the file. + /// + public Dictionary? CustomMetadata + { + get + { + if (!this.Properties.TryGetValue("customMetadata", out JsonElement element)) + return null; + + return JsonSerializer.Deserialize?>( + element, + ModelBase.SerializerOptions + ); + } + set + { + this.Properties["customMetadata"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + /// + /// Optional text to describe the contents of the file. Can be set by the user + /// or the ai-auto-description extension. + /// + public string? Description + { + get + { + if (!this.Properties.TryGetValue("description", out JsonElement element)) + return null; + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions); + } + set + { + this.Properties["description"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + /// + /// Unique identifier of the asset. + /// + public string? FileID + { + get + { + if (!this.Properties.TryGetValue("fileId", out JsonElement element)) + return null; + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions); + } + set + { + this.Properties["fileId"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + /// + /// Path of the file. This is the path you would use in the URL to access the + /// file. For example, if the file is at the root of the media library, the path + /// will be `/file.jpg`. If the file is inside a folder named `images`, the path + /// will be `/images/file.jpg`. + /// + public string? FilePath + { + get + { + if (!this.Properties.TryGetValue("filePath", out JsonElement element)) + return null; + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions); + } + set + { + this.Properties["filePath"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + /// + /// Type of the file. Possible values are `image`, `non-image`. + /// + public string? FileType + { + get + { + if (!this.Properties.TryGetValue("fileType", out JsonElement element)) + return null; + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions); + } + set + { + this.Properties["fileType"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + /// + /// Specifies if the image has an alpha channel. + /// + public bool? HasAlpha + { + get + { + if (!this.Properties.TryGetValue("hasAlpha", out JsonElement element)) + return null; + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions); + } + set + { + this.Properties["hasAlpha"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + /// + /// Height of the file. + /// + public double? Height + { + get + { + if (!this.Properties.TryGetValue("height", out JsonElement element)) + return null; + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions); + } + set + { + this.Properties["height"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + /// + /// Specifies if the file is private or not. + /// + public bool? IsPrivateFile + { + get + { + if (!this.Properties.TryGetValue("isPrivateFile", out JsonElement element)) + return null; + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions); + } + set + { + this.Properties["isPrivateFile"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + /// + /// Specifies if the file is published or not. + /// + public bool? IsPublished + { + get + { + if (!this.Properties.TryGetValue("isPublished", out JsonElement element)) + return null; + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions); + } + set + { + this.Properties["isPublished"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + /// + /// MIME type of the file. + /// + public string? Mime + { + get + { + if (!this.Properties.TryGetValue("mime", out JsonElement element)) + return null; + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions); + } + set + { + this.Properties["mime"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + /// + /// Name of the asset. + /// + public string? Name + { + get + { + if (!this.Properties.TryGetValue("name", out JsonElement element)) + return null; + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions); + } + set + { + this.Properties["name"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + /// + /// Size of the file in bytes. + /// + public double? Size + { + get + { + if (!this.Properties.TryGetValue("size", out JsonElement element)) + return null; + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions); + } + set + { + this.Properties["size"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + /// + /// An array of tags assigned to the file. Tags are used to search files in the + /// media library. + /// + public List? Tags + { + get + { + if (!this.Properties.TryGetValue("tags", out JsonElement element)) + return null; + + return JsonSerializer.Deserialize?>(element, ModelBase.SerializerOptions); + } + set + { + this.Properties["tags"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + /// + /// URL of the thumbnail image. This URL is used to access the thumbnail image + /// of the file in the media library. + /// + public string? Thumbnail + { + get + { + if (!this.Properties.TryGetValue("thumbnail", out JsonElement element)) + return null; + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions); + } + set + { + this.Properties["thumbnail"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + /// + /// Type of the asset. + /// + public ApiEnum? Type + { + get + { + if (!this.Properties.TryGetValue("type", out JsonElement element)) + return null; + + return JsonSerializer.Deserialize?>( + element, + ModelBase.SerializerOptions + ); + } + set + { + this.Properties["type"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + /// + /// Date and time when the file was last updated. The date and time is in ISO8601 + /// format. + /// + public DateTime? UpdatedAt + { + get + { + if (!this.Properties.TryGetValue("updatedAt", out JsonElement element)) + return null; + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions); + } + set + { + this.Properties["updatedAt"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + /// + /// URL of the file. + /// + public string? URL + { + get + { + if (!this.Properties.TryGetValue("url", out JsonElement element)) + return null; + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions); + } + set + { + this.Properties["url"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + /// + /// An object with details of the file version. + /// + public FileProperties::VersionInfo? VersionInfo + { + get + { + if (!this.Properties.TryGetValue("versionInfo", out JsonElement element)) + return null; + + return JsonSerializer.Deserialize( + element, + ModelBase.SerializerOptions + ); + } + set + { + this.Properties["versionInfo"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + /// + /// Width of the file. + /// + public double? Width + { + get + { + if (!this.Properties.TryGetValue("width", out JsonElement element)) + return null; + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions); + } + set + { + this.Properties["width"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + public override void Validate() + { + foreach (var item in this.AITags ?? []) + { + item.Validate(); + } + _ = this.CreatedAt; + _ = this.CustomCoordinates; + if (this.CustomMetadata != null) + { + foreach (var item in this.CustomMetadata.Values) + { + _ = item; + } + } + _ = this.Description; + _ = this.FileID; + _ = this.FilePath; + _ = this.FileType; + _ = this.HasAlpha; + _ = this.Height; + _ = this.IsPrivateFile; + _ = this.IsPublished; + _ = this.Mime; + _ = this.Name; + _ = this.Size; + foreach (var item in this.Tags ?? []) + { + _ = item; + } + _ = this.Thumbnail; + this.Type?.Validate(); + _ = this.UpdatedAt; + _ = this.URL; + this.VersionInfo?.Validate(); + _ = this.Width; + } + + public File() { } + +#pragma warning disable CS8618 + [SetsRequiredMembers] + File(Dictionary properties) + { + Properties = properties; + } +#pragma warning restore CS8618 + + public static File FromRawUnchecked(Dictionary properties) + { + return new(properties); + } +} diff --git a/src/Imagekit/Models/Files/FileCopyParams.cs b/src/Imagekit/Models/Files/FileCopyParams.cs new file mode 100644 index 00000000..0dc5ca78 --- /dev/null +++ b/src/Imagekit/Models/Files/FileCopyParams.cs @@ -0,0 +1,118 @@ +using System; +using System.Collections.Generic; +using System.Net.Http; +using System.Text; +using System.Text.Json; + +namespace Imagekit.Models.Files; + +/// +/// This will copy a file from one folder to another. +/// +/// Note: If any file at the destination has the same name as the source file, then +/// the source file and its versions (if `includeFileVersions` is set to true) will +/// be appended to the destination file version history. +/// +public sealed record class FileCopyParams : ParamsBase +{ + public Dictionary BodyProperties { get; set; } = []; + + /// + /// Full path to the folder you want to copy the above file into. + /// + public required string DestinationPath + { + get + { + if (!this.BodyProperties.TryGetValue("destinationPath", out JsonElement element)) + throw new ArgumentOutOfRangeException( + "destinationPath", + "Missing required argument" + ); + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions) + ?? throw new ArgumentNullException("destinationPath"); + } + set + { + this.BodyProperties["destinationPath"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + /// + /// The full path of the file you want to copy. + /// + public required string SourceFilePath + { + get + { + if (!this.BodyProperties.TryGetValue("sourceFilePath", out JsonElement element)) + throw new ArgumentOutOfRangeException( + "sourceFilePath", + "Missing required argument" + ); + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions) + ?? throw new ArgumentNullException("sourceFilePath"); + } + set + { + this.BodyProperties["sourceFilePath"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + /// + /// Option to copy all versions of a file. By default, only the current version + /// of the file is copied. When set to true, all versions of the file will be + /// copied. Default value - `false`. + /// + public bool? IncludeFileVersions + { + get + { + if (!this.BodyProperties.TryGetValue("includeFileVersions", out JsonElement element)) + return null; + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions); + } + set + { + this.BodyProperties["includeFileVersions"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + public override Uri Url(IImageKitClient client) + { + return new UriBuilder(client.BaseUrl.ToString().TrimEnd('/') + "/v1/files/copy") + { + Query = this.QueryString(client), + }.Uri; + } + + public StringContent BodyContent() + { + return new( + JsonSerializer.Serialize(this.BodyProperties), + Encoding.UTF8, + "application/json" + ); + } + + public void AddHeadersToRequest(HttpRequestMessage request, IImageKitClient client) + { + ParamsBase.AddDefaultHeaders(request, client); + foreach (var item in this.HeaderProperties) + { + ParamsBase.AddHeaderElementToRequest(request, item.Key, item.Value); + } + } +} diff --git a/src/Imagekit/Models/Files/FileCopyResponse.cs b/src/Imagekit/Models/Files/FileCopyResponse.cs new file mode 100644 index 00000000..bac4ecbb --- /dev/null +++ b/src/Imagekit/Models/Files/FileCopyResponse.cs @@ -0,0 +1,27 @@ +using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; +using System.Text.Json; +using System.Text.Json.Serialization; + +namespace Imagekit.Models.Files; + +[JsonConverter(typeof(ModelConverter))] +public sealed record class FileCopyResponse : ModelBase, IFromRaw +{ + public override void Validate() { } + + public FileCopyResponse() { } + +#pragma warning disable CS8618 + [SetsRequiredMembers] + FileCopyResponse(Dictionary properties) + { + Properties = properties; + } +#pragma warning restore CS8618 + + public static FileCopyResponse FromRawUnchecked(Dictionary properties) + { + return new(properties); + } +} diff --git a/src/Imagekit/Models/Files/FileDeleteParams.cs b/src/Imagekit/Models/Files/FileDeleteParams.cs new file mode 100644 index 00000000..aac0dab1 --- /dev/null +++ b/src/Imagekit/Models/Files/FileDeleteParams.cs @@ -0,0 +1,35 @@ +using System; +using System.Net.Http; + +namespace Imagekit.Models.Files; + +/// +/// This API deletes the file and all its file versions permanently. +/// +/// Note: If a file or specific transformation has been requested in the past, then +/// the response is cached. Deleting a file does not purge the cache. You can purge +/// the cache using purge cache API. +/// +public sealed record class FileDeleteParams : ParamsBase +{ + public required string FileID; + + public override Uri Url(IImageKitClient client) + { + return new UriBuilder( + client.BaseUrl.ToString().TrimEnd('/') + string.Format("/v1/files/{0}", this.FileID) + ) + { + Query = this.QueryString(client), + }.Uri; + } + + public void AddHeadersToRequest(HttpRequestMessage request, IImageKitClient client) + { + ParamsBase.AddDefaultHeaders(request, client); + foreach (var item in this.HeaderProperties) + { + ParamsBase.AddHeaderElementToRequest(request, item.Key, item.Value); + } + } +} diff --git a/src/Imagekit/Models/Files/FileGetParams.cs b/src/Imagekit/Models/Files/FileGetParams.cs new file mode 100644 index 00000000..5f8dbc1a --- /dev/null +++ b/src/Imagekit/Models/Files/FileGetParams.cs @@ -0,0 +1,33 @@ +using System; +using System.Net.Http; + +namespace Imagekit.Models.Files; + +/// +/// This API returns an object with details or attributes about the current version +/// of the file. +/// +public sealed record class FileGetParams : ParamsBase +{ + public required string FileID; + + public override Uri Url(IImageKitClient client) + { + return new UriBuilder( + client.BaseUrl.ToString().TrimEnd('/') + + string.Format("/v1/files/{0}/details", this.FileID) + ) + { + Query = this.QueryString(client), + }.Uri; + } + + public void AddHeadersToRequest(HttpRequestMessage request, IImageKitClient client) + { + ParamsBase.AddDefaultHeaders(request, client); + foreach (var item in this.HeaderProperties) + { + ParamsBase.AddHeaderElementToRequest(request, item.Key, item.Value); + } + } +} diff --git a/src/Imagekit/Models/Files/FileMoveParams.cs b/src/Imagekit/Models/Files/FileMoveParams.cs new file mode 100644 index 00000000..66cc32b5 --- /dev/null +++ b/src/Imagekit/Models/Files/FileMoveParams.cs @@ -0,0 +1,94 @@ +using System; +using System.Collections.Generic; +using System.Net.Http; +using System.Text; +using System.Text.Json; + +namespace Imagekit.Models.Files; + +/// +/// This will move a file and all its versions from one folder to another. +/// +/// Note: If any file at the destination has the same name as the source file, then +/// the source file and its versions will be appended to the destination file. +/// +public sealed record class FileMoveParams : ParamsBase +{ + public Dictionary BodyProperties { get; set; } = []; + + /// + /// Full path to the folder you want to move the above file into. + /// + public required string DestinationPath + { + get + { + if (!this.BodyProperties.TryGetValue("destinationPath", out JsonElement element)) + throw new ArgumentOutOfRangeException( + "destinationPath", + "Missing required argument" + ); + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions) + ?? throw new ArgumentNullException("destinationPath"); + } + set + { + this.BodyProperties["destinationPath"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + /// + /// The full path of the file you want to move. + /// + public required string SourceFilePath + { + get + { + if (!this.BodyProperties.TryGetValue("sourceFilePath", out JsonElement element)) + throw new ArgumentOutOfRangeException( + "sourceFilePath", + "Missing required argument" + ); + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions) + ?? throw new ArgumentNullException("sourceFilePath"); + } + set + { + this.BodyProperties["sourceFilePath"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + public override Uri Url(IImageKitClient client) + { + return new UriBuilder(client.BaseUrl.ToString().TrimEnd('/') + "/v1/files/move") + { + Query = this.QueryString(client), + }.Uri; + } + + public StringContent BodyContent() + { + return new( + JsonSerializer.Serialize(this.BodyProperties), + Encoding.UTF8, + "application/json" + ); + } + + public void AddHeadersToRequest(HttpRequestMessage request, IImageKitClient client) + { + ParamsBase.AddDefaultHeaders(request, client); + foreach (var item in this.HeaderProperties) + { + ParamsBase.AddHeaderElementToRequest(request, item.Key, item.Value); + } + } +} diff --git a/src/Imagekit/Models/Files/FileMoveResponse.cs b/src/Imagekit/Models/Files/FileMoveResponse.cs new file mode 100644 index 00000000..ebcffab9 --- /dev/null +++ b/src/Imagekit/Models/Files/FileMoveResponse.cs @@ -0,0 +1,27 @@ +using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; +using System.Text.Json; +using System.Text.Json.Serialization; + +namespace Imagekit.Models.Files; + +[JsonConverter(typeof(ModelConverter))] +public sealed record class FileMoveResponse : ModelBase, IFromRaw +{ + public override void Validate() { } + + public FileMoveResponse() { } + +#pragma warning disable CS8618 + [SetsRequiredMembers] + FileMoveResponse(Dictionary properties) + { + Properties = properties; + } +#pragma warning restore CS8618 + + public static FileMoveResponse FromRawUnchecked(Dictionary properties) + { + return new(properties); + } +} diff --git a/src/Imagekit/Models/Files/FileProperties/AITag.cs b/src/Imagekit/Models/Files/FileProperties/AITag.cs new file mode 100644 index 00000000..f5bacb0e --- /dev/null +++ b/src/Imagekit/Models/Files/FileProperties/AITag.cs @@ -0,0 +1,95 @@ +using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; +using System.Text.Json; +using System.Text.Json.Serialization; + +namespace Imagekit.Models.Files.FileProperties; + +[JsonConverter(typeof(ModelConverter))] +public sealed record class AITag : ModelBase, IFromRaw +{ + /// + /// Confidence score of the tag. + /// + public double? Confidence + { + get + { + if (!this.Properties.TryGetValue("confidence", out JsonElement element)) + return null; + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions); + } + set + { + this.Properties["confidence"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + /// + /// Name of the tag. + /// + public string? Name + { + get + { + if (!this.Properties.TryGetValue("name", out JsonElement element)) + return null; + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions); + } + set + { + this.Properties["name"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + /// + /// Source of the tag. Possible values are `google-auto-tagging` and `aws-auto-tagging`. + /// + public string? Source + { + get + { + if (!this.Properties.TryGetValue("source", out JsonElement element)) + return null; + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions); + } + set + { + this.Properties["source"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + public override void Validate() + { + _ = this.Confidence; + _ = this.Name; + _ = this.Source; + } + + public AITag() { } + +#pragma warning disable CS8618 + [SetsRequiredMembers] + AITag(Dictionary properties) + { + Properties = properties; + } +#pragma warning restore CS8618 + + public static AITag FromRawUnchecked(Dictionary properties) + { + return new(properties); + } +} diff --git a/src/Imagekit/Models/Files/FileProperties/Type.cs b/src/Imagekit/Models/Files/FileProperties/Type.cs new file mode 100644 index 00000000..6062c976 --- /dev/null +++ b/src/Imagekit/Models/Files/FileProperties/Type.cs @@ -0,0 +1,46 @@ +using System.Text.Json; +using System.Text.Json.Serialization; +using System = System; + +namespace Imagekit.Models.Files.FileProperties; + +/// +/// Type of the asset. +/// +[JsonConverter(typeof(TypeConverter))] +public enum Type +{ + File, + FileVersion, +} + +sealed class TypeConverter : JsonConverter +{ + public override Type Read( + ref Utf8JsonReader reader, + System::Type typeToConvert, + JsonSerializerOptions options + ) + { + return JsonSerializer.Deserialize(ref reader, options) switch + { + "file" => FileProperties.Type.File, + "file-version" => FileProperties.Type.FileVersion, + _ => (Type)(-1), + }; + } + + public override void Write(Utf8JsonWriter writer, Type value, JsonSerializerOptions options) + { + JsonSerializer.Serialize( + writer, + value switch + { + FileProperties.Type.File => "file", + FileProperties.Type.FileVersion => "file-version", + _ => throw new System::ArgumentOutOfRangeException(nameof(value)), + }, + options + ); + } +} diff --git a/src/Imagekit/Models/Files/FileProperties/VersionInfo.cs b/src/Imagekit/Models/Files/FileProperties/VersionInfo.cs new file mode 100644 index 00000000..48e2faf5 --- /dev/null +++ b/src/Imagekit/Models/Files/FileProperties/VersionInfo.cs @@ -0,0 +1,76 @@ +using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; +using System.Text.Json; +using System.Text.Json.Serialization; + +namespace Imagekit.Models.Files.FileProperties; + +/// +/// An object with details of the file version. +/// +[JsonConverter(typeof(ModelConverter))] +public sealed record class VersionInfo : ModelBase, IFromRaw +{ + /// + /// Unique identifier of the file version. + /// + public string? ID + { + get + { + if (!this.Properties.TryGetValue("id", out JsonElement element)) + return null; + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions); + } + set + { + this.Properties["id"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + /// + /// Name of the file version. + /// + public string? Name + { + get + { + if (!this.Properties.TryGetValue("name", out JsonElement element)) + return null; + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions); + } + set + { + this.Properties["name"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + public override void Validate() + { + _ = this.ID; + _ = this.Name; + } + + public VersionInfo() { } + +#pragma warning disable CS8618 + [SetsRequiredMembers] + VersionInfo(Dictionary properties) + { + Properties = properties; + } +#pragma warning restore CS8618 + + public static VersionInfo FromRawUnchecked(Dictionary properties) + { + return new(properties); + } +} diff --git a/src/Imagekit/Models/Files/FileRenameParams.cs b/src/Imagekit/Models/Files/FileRenameParams.cs new file mode 100644 index 00000000..8c378757 --- /dev/null +++ b/src/Imagekit/Models/Files/FileRenameParams.cs @@ -0,0 +1,129 @@ +using System; +using System.Collections.Generic; +using System.Net.Http; +using System.Text; +using System.Text.Json; + +namespace Imagekit.Models.Files; + +/// +/// You can rename an already existing file in the media library using rename file +/// API. This operation would rename all file versions of the file. +/// +/// Note: The old URLs will stop working. The file/file version URLs cached on CDN +/// will continue to work unless a purge is requested. +/// +public sealed record class FileRenameParams : ParamsBase +{ + public Dictionary BodyProperties { get; set; } = []; + + /// + /// The full path of the file you want to rename. + /// + public required string FilePath + { + get + { + if (!this.BodyProperties.TryGetValue("filePath", out JsonElement element)) + throw new ArgumentOutOfRangeException("filePath", "Missing required argument"); + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions) + ?? throw new ArgumentNullException("filePath"); + } + set + { + this.BodyProperties["filePath"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + /// + /// The new name of the file. A filename can contain: + /// + /// Alphanumeric Characters: `a-z`, `A-Z`, `0-9` (including Unicode letters, marks, + /// and numerals in other languages). Special Characters: `.`, `_`, and `-`. + /// + /// Any other character, including space, will be replaced by `_`. + /// + public required string NewFileName + { + get + { + if (!this.BodyProperties.TryGetValue("newFileName", out JsonElement element)) + throw new ArgumentOutOfRangeException("newFileName", "Missing required argument"); + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions) + ?? throw new ArgumentNullException("newFileName"); + } + set + { + this.BodyProperties["newFileName"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + /// + /// Option to purge cache for the old file and its versions' URLs. + /// + /// When set to true, it will internally issue a purge cache request on CDN to + /// remove cached content of old file and its versions. This purge request is + /// counted against your monthly purge quota. + /// + /// Note: If the old file were accessible at `https://ik.imagekit.io/demo/old-filename.jpg`, + /// a purge cache request would be issued against `https://ik.imagekit.io/demo/old-filename.jpg*` + /// (with a wildcard at the end). It will remove the file and its versions' URLs + /// and any transformations made using query parameters on this file or its versions. + /// However, the cache for file transformations made using path parameters will + /// persist. You can purge them using the purge API. For more details, refer to + /// the purge API documentation. + /// + /// Default value - `false` + /// + public bool? PurgeCache + { + get + { + if (!this.BodyProperties.TryGetValue("purgeCache", out JsonElement element)) + return null; + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions); + } + set + { + this.BodyProperties["purgeCache"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + public override Uri Url(IImageKitClient client) + { + return new UriBuilder(client.BaseUrl.ToString().TrimEnd('/') + "/v1/files/rename") + { + Query = this.QueryString(client), + }.Uri; + } + + public StringContent BodyContent() + { + return new( + JsonSerializer.Serialize(this.BodyProperties), + Encoding.UTF8, + "application/json" + ); + } + + public void AddHeadersToRequest(HttpRequestMessage request, IImageKitClient client) + { + ParamsBase.AddDefaultHeaders(request, client); + foreach (var item in this.HeaderProperties) + { + ParamsBase.AddHeaderElementToRequest(request, item.Key, item.Value); + } + } +} diff --git a/src/Imagekit/Models/Files/FileRenameResponse.cs b/src/Imagekit/Models/Files/FileRenameResponse.cs new file mode 100644 index 00000000..29001165 --- /dev/null +++ b/src/Imagekit/Models/Files/FileRenameResponse.cs @@ -0,0 +1,52 @@ +using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; +using System.Text.Json; +using System.Text.Json.Serialization; + +namespace Imagekit.Models.Files; + +[JsonConverter(typeof(ModelConverter))] +public sealed record class FileRenameResponse : ModelBase, IFromRaw +{ + /// + /// Unique identifier of the purge request. This can be used to check the status + /// of the purge request. + /// + public string? PurgeRequestID + { + get + { + if (!this.Properties.TryGetValue("purgeRequestId", out JsonElement element)) + return null; + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions); + } + set + { + this.Properties["purgeRequestId"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + public override void Validate() + { + _ = this.PurgeRequestID; + } + + public FileRenameResponse() { } + +#pragma warning disable CS8618 + [SetsRequiredMembers] + FileRenameResponse(Dictionary properties) + { + Properties = properties; + } +#pragma warning restore CS8618 + + public static FileRenameResponse FromRawUnchecked(Dictionary properties) + { + return new(properties); + } +} diff --git a/src/Imagekit/Models/Files/FileUpdateParams.cs b/src/Imagekit/Models/Files/FileUpdateParams.cs new file mode 100644 index 00000000..100f51ab --- /dev/null +++ b/src/Imagekit/Models/Files/FileUpdateParams.cs @@ -0,0 +1,67 @@ +using System; +using System.Collections.Generic; +using System.Net.Http; +using System.Text; +using System.Text.Json; +using Imagekit.Models.Files.FileUpdateParamsProperties; + +namespace Imagekit.Models.Files; + +/// +/// This API updates the details or attributes of the current version of the file. +/// You can update `tags`, `customCoordinates`, `customMetadata`, publication status, +/// remove existing `AITags` and apply extensions using this API. +/// +public sealed record class FileUpdateParams : ParamsBase +{ + public Dictionary BodyProperties { get; set; } = []; + + public required string FileID; + + public Update? Update + { + get + { + if (!this.BodyProperties.TryGetValue("update", out JsonElement element)) + return null; + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions); + } + set + { + this.BodyProperties["update"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + public override Uri Url(IImageKitClient client) + { + return new UriBuilder( + client.BaseUrl.ToString().TrimEnd('/') + + string.Format("/v1/files/{0}/details", this.FileID) + ) + { + Query = this.QueryString(client), + }.Uri; + } + + public StringContent BodyContent() + { + return new( + JsonSerializer.Serialize(this.BodyProperties), + Encoding.UTF8, + "application/json" + ); + } + + public void AddHeadersToRequest(HttpRequestMessage request, IImageKitClient client) + { + ParamsBase.AddDefaultHeaders(request, client); + foreach (var item in this.HeaderProperties) + { + ParamsBase.AddHeaderElementToRequest(request, item.Key, item.Value); + } + } +} diff --git a/src/Imagekit/Models/Files/FileUpdateParamsProperties/Update.cs b/src/Imagekit/Models/Files/FileUpdateParamsProperties/Update.cs new file mode 100644 index 00000000..2e507646 --- /dev/null +++ b/src/Imagekit/Models/Files/FileUpdateParamsProperties/Update.cs @@ -0,0 +1,123 @@ +using System; +using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; +using System.Text.Json; +using System.Text.Json.Serialization; +using Imagekit.Models.Files.FileUpdateParamsProperties.UpdateProperties; +using UpdateVariants = Imagekit.Models.Files.FileUpdateParamsProperties.UpdateVariants; + +namespace Imagekit.Models.Files.FileUpdateParamsProperties; + +[JsonConverter(typeof(UpdateConverter))] +public abstract record class Update +{ + internal Update() { } + + public static implicit operator Update(UpdateFileDetails value) => + new UpdateVariants::UpdateFileDetails(value); + + public static implicit operator Update(ChangePublicationStatus value) => + new UpdateVariants::ChangePublicationStatus(value); + + public bool TryPickFileDetails([NotNullWhen(true)] out UpdateFileDetails? value) + { + value = (this as UpdateVariants::UpdateFileDetails)?.Value; + return value != null; + } + + public bool TryPickChangePublicationStatus( + [NotNullWhen(true)] out ChangePublicationStatus? value + ) + { + value = (this as UpdateVariants::ChangePublicationStatus)?.Value; + return value != null; + } + + public void Switch( + Action fileDetails, + Action changePublicationStatus + ) + { + switch (this) + { + case UpdateVariants::UpdateFileDetails inner: + fileDetails(inner); + break; + case UpdateVariants::ChangePublicationStatus inner: + changePublicationStatus(inner); + break; + default: + throw new InvalidOperationException(); + } + } + + public T Match( + Func fileDetails, + Func changePublicationStatus + ) + { + return this switch + { + UpdateVariants::UpdateFileDetails inner => fileDetails(inner), + UpdateVariants::ChangePublicationStatus inner => changePublicationStatus(inner), + _ => throw new InvalidOperationException(), + }; + } + + public abstract void Validate(); +} + +sealed class UpdateConverter : JsonConverter +{ + public override Update? Read( + ref Utf8JsonReader reader, + Type typeToConvert, + JsonSerializerOptions options + ) + { + List exceptions = []; + + try + { + var deserialized = JsonSerializer.Deserialize(ref reader, options); + if (deserialized != null) + { + return new UpdateVariants::UpdateFileDetails(deserialized); + } + } + catch (JsonException e) + { + exceptions.Add(e); + } + + try + { + var deserialized = JsonSerializer.Deserialize( + ref reader, + options + ); + if (deserialized != null) + { + return new UpdateVariants::ChangePublicationStatus(deserialized); + } + } + catch (JsonException e) + { + exceptions.Add(e); + } + + throw new AggregateException(exceptions); + } + + public override void Write(Utf8JsonWriter writer, Update value, JsonSerializerOptions options) + { + object variant = value switch + { + UpdateVariants::UpdateFileDetails(var fileDetails) => fileDetails, + UpdateVariants::ChangePublicationStatus(var changePublicationStatus) => + changePublicationStatus, + _ => throw new ArgumentOutOfRangeException(nameof(value)), + }; + JsonSerializer.Serialize(writer, variant, options); + } +} diff --git a/src/Imagekit/Models/Files/FileUpdateParamsProperties/UpdateProperties/ChangePublicationStatus.cs b/src/Imagekit/Models/Files/FileUpdateParamsProperties/UpdateProperties/ChangePublicationStatus.cs new file mode 100644 index 00000000..7de8ec8b --- /dev/null +++ b/src/Imagekit/Models/Files/FileUpdateParamsProperties/UpdateProperties/ChangePublicationStatus.cs @@ -0,0 +1,54 @@ +using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; +using System.Text.Json; +using System.Text.Json.Serialization; +using Imagekit.Models.Files.FileUpdateParamsProperties.UpdateProperties.ChangePublicationStatusProperties; + +namespace Imagekit.Models.Files.FileUpdateParamsProperties.UpdateProperties; + +[JsonConverter(typeof(ModelConverter))] +public sealed record class ChangePublicationStatus : ModelBase, IFromRaw +{ + /// + /// Configure the publication status of a file and its versions. + /// + public Publish? Publish + { + get + { + if (!this.Properties.TryGetValue("publish", out JsonElement element)) + return null; + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions); + } + set + { + this.Properties["publish"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + public override void Validate() + { + this.Publish?.Validate(); + } + + public ChangePublicationStatus() { } + +#pragma warning disable CS8618 + [SetsRequiredMembers] + ChangePublicationStatus(Dictionary properties) + { + Properties = properties; + } +#pragma warning restore CS8618 + + public static ChangePublicationStatus FromRawUnchecked( + Dictionary properties + ) + { + return new(properties); + } +} diff --git a/src/Imagekit/Models/Files/FileUpdateParamsProperties/UpdateProperties/ChangePublicationStatusProperties/Publish.cs b/src/Imagekit/Models/Files/FileUpdateParamsProperties/UpdateProperties/ChangePublicationStatusProperties/Publish.cs new file mode 100644 index 00000000..acd8feb0 --- /dev/null +++ b/src/Imagekit/Models/Files/FileUpdateParamsProperties/UpdateProperties/ChangePublicationStatusProperties/Publish.cs @@ -0,0 +1,85 @@ +using System; +using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; +using System.Text.Json; +using System.Text.Json.Serialization; + +namespace Imagekit.Models.Files.FileUpdateParamsProperties.UpdateProperties.ChangePublicationStatusProperties; + +/// +/// Configure the publication status of a file and its versions. +/// +[JsonConverter(typeof(ModelConverter))] +public sealed record class Publish : ModelBase, IFromRaw +{ + /// + /// Set to `true` to publish the file. Set to `false` to unpublish the file. + /// + public required bool IsPublished + { + get + { + if (!this.Properties.TryGetValue("isPublished", out JsonElement element)) + throw new ArgumentOutOfRangeException("isPublished", "Missing required argument"); + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions); + } + set + { + this.Properties["isPublished"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + /// + /// Set to `true` to publish/unpublish all versions of the file. Set to `false` + /// to publish/unpublish only the current version of the file. + /// + public bool? IncludeFileVersions + { + get + { + if (!this.Properties.TryGetValue("includeFileVersions", out JsonElement element)) + return null; + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions); + } + set + { + this.Properties["includeFileVersions"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + public override void Validate() + { + _ = this.IsPublished; + _ = this.IncludeFileVersions; + } + + public Publish() { } + +#pragma warning disable CS8618 + [SetsRequiredMembers] + Publish(Dictionary properties) + { + Properties = properties; + } +#pragma warning restore CS8618 + + public static Publish FromRawUnchecked(Dictionary properties) + { + return new(properties); + } + + [SetsRequiredMembers] + public Publish(bool isPublished) + : this() + { + this.IsPublished = isPublished; + } +} diff --git a/src/Imagekit/Models/Files/FileUpdateParamsProperties/UpdateProperties/UpdateFileDetails.cs b/src/Imagekit/Models/Files/FileUpdateParamsProperties/UpdateProperties/UpdateFileDetails.cs new file mode 100644 index 00000000..54fbecbe --- /dev/null +++ b/src/Imagekit/Models/Files/FileUpdateParamsProperties/UpdateProperties/UpdateFileDetails.cs @@ -0,0 +1,215 @@ +using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; +using System.Text.Json; +using System.Text.Json.Serialization; +using Imagekit.Models.Files.FileUpdateParamsProperties.UpdateProperties.UpdateFileDetailsProperties; + +namespace Imagekit.Models.Files.FileUpdateParamsProperties.UpdateProperties; + +[JsonConverter(typeof(ModelConverter))] +public sealed record class UpdateFileDetails : ModelBase, IFromRaw +{ + /// + /// Define an important area in the image in the format `x,y,width,height` e.g. + /// `10,10,100,100`. Send `null` to unset this value. + /// + public string? CustomCoordinates + { + get + { + if (!this.Properties.TryGetValue("customCoordinates", out JsonElement element)) + return null; + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions); + } + set + { + this.Properties["customCoordinates"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + /// + /// A key-value data to be associated with the asset. To unset a key, send `null` + /// value for that key. Before setting any custom metadata on an asset you have + /// to create the field using custom metadata fields API. + /// + public Dictionary? CustomMetadata + { + get + { + if (!this.Properties.TryGetValue("customMetadata", out JsonElement element)) + return null; + + return JsonSerializer.Deserialize?>( + element, + ModelBase.SerializerOptions + ); + } + set + { + this.Properties["customMetadata"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + /// + /// Optional text to describe the contents of the file. + /// + public string? Description + { + get + { + if (!this.Properties.TryGetValue("description", out JsonElement element)) + return null; + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions); + } + set + { + this.Properties["description"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + /// + /// Array of extensions to be applied to the asset. Each extension can be configured + /// with specific parameters based on the extension type. + /// + public List? Extensions + { + get + { + if (!this.Properties.TryGetValue("extensions", out JsonElement element)) + return null; + + return JsonSerializer.Deserialize?>( + element, + ModelBase.SerializerOptions + ); + } + set + { + this.Properties["extensions"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + /// + /// An array of AITags associated with the file that you want to remove, e.g. + /// `["car", "vehicle", "motorsports"]`. + /// + /// If you want to remove all AITags associated with the file, send a string - "all". + /// + /// Note: The remove operation for `AITags` executes before any of the `extensions` + /// are processed. + /// + public RemoveAITags? RemoveAITags + { + get + { + if (!this.Properties.TryGetValue("removeAITags", out JsonElement element)) + return null; + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions); + } + set + { + this.Properties["removeAITags"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + /// + /// An array of tags associated with the file, such as `["tag1", "tag2"]`. Send + /// `null` to unset all tags associated with the file. + /// + public List? Tags + { + get + { + if (!this.Properties.TryGetValue("tags", out JsonElement element)) + return null; + + return JsonSerializer.Deserialize?>(element, ModelBase.SerializerOptions); + } + set + { + this.Properties["tags"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + /// + /// The final status of extensions after they have completed execution will be + /// delivered to this endpoint as a POST request. [Learn more](/docs/api-reference/digital-asset-management-dam/managing-assets/update-file-details#webhook-payload-structure) + /// about the webhook payload structure. + /// + public string? WebhookURL + { + get + { + if (!this.Properties.TryGetValue("webhookUrl", out JsonElement element)) + return null; + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions); + } + set + { + this.Properties["webhookUrl"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + public override void Validate() + { + _ = this.CustomCoordinates; + if (this.CustomMetadata != null) + { + foreach (var item in this.CustomMetadata.Values) + { + _ = item; + } + } + _ = this.Description; + foreach (var item in this.Extensions ?? []) + { + item.Validate(); + } + this.RemoveAITags?.Validate(); + foreach (var item in this.Tags ?? []) + { + _ = item; + } + _ = this.WebhookURL; + } + + public UpdateFileDetails() { } + +#pragma warning disable CS8618 + [SetsRequiredMembers] + UpdateFileDetails(Dictionary properties) + { + Properties = properties; + } +#pragma warning restore CS8618 + + public static UpdateFileDetails FromRawUnchecked(Dictionary properties) + { + return new(properties); + } +} diff --git a/src/Imagekit/Models/Files/FileUpdateParamsProperties/UpdateProperties/UpdateFileDetailsProperties/Extension.cs b/src/Imagekit/Models/Files/FileUpdateParamsProperties/UpdateProperties/UpdateFileDetailsProperties/Extension.cs new file mode 100644 index 00000000..4eaae50d --- /dev/null +++ b/src/Imagekit/Models/Files/FileUpdateParamsProperties/UpdateProperties/UpdateFileDetailsProperties/Extension.cs @@ -0,0 +1,177 @@ +using System; +using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; +using System.Text.Json; +using System.Text.Json.Serialization; +using Imagekit.Models.Files.FileUpdateParamsProperties.UpdateProperties.UpdateFileDetailsProperties.ExtensionProperties; +using ExtensionVariants = Imagekit.Models.Files.FileUpdateParamsProperties.UpdateProperties.UpdateFileDetailsProperties.ExtensionVariants; + +namespace Imagekit.Models.Files.FileUpdateParamsProperties.UpdateProperties.UpdateFileDetailsProperties; + +[JsonConverter(typeof(ExtensionConverter))] +public abstract record class Extension +{ + internal Extension() { } + + public static implicit operator Extension(RemoveBg value) => + new ExtensionVariants::RemoveBg(value); + + public static implicit operator Extension(AutoTaggingExtension value) => + new ExtensionVariants::AutoTaggingExtension(value); + + public bool TryPickRemoveBg([NotNullWhen(true)] out RemoveBg? value) + { + value = (this as ExtensionVariants::RemoveBg)?.Value; + return value != null; + } + + public bool TryPickAutoTagging([NotNullWhen(true)] out AutoTaggingExtension? value) + { + value = (this as ExtensionVariants::AutoTaggingExtension)?.Value; + return value != null; + } + + public bool TryPickAIAutoDescription([NotNullWhen(true)] out JsonElement? value) + { + value = (this as ExtensionVariants::AIAutoDescription)?.Value; + return value != null; + } + + public void Switch( + Action removeBg, + Action autoTagging, + Action aiAutoDescription + ) + { + switch (this) + { + case ExtensionVariants::RemoveBg inner: + removeBg(inner); + break; + case ExtensionVariants::AutoTaggingExtension inner: + autoTagging(inner); + break; + case ExtensionVariants::AIAutoDescription inner: + aiAutoDescription(inner); + break; + default: + throw new InvalidOperationException(); + } + } + + public T Match( + Func removeBg, + Func autoTagging, + Func aiAutoDescription + ) + { + return this switch + { + ExtensionVariants::RemoveBg inner => removeBg(inner), + ExtensionVariants::AutoTaggingExtension inner => autoTagging(inner), + ExtensionVariants::AIAutoDescription inner => aiAutoDescription(inner), + _ => throw new InvalidOperationException(), + }; + } + + public abstract void Validate(); +} + +sealed class ExtensionConverter : JsonConverter +{ + public override Extension? Read( + ref Utf8JsonReader reader, + Type typeToConvert, + JsonSerializerOptions options + ) + { + var json = JsonSerializer.Deserialize(ref reader, options); + string? name; + try + { + name = json.GetProperty("name").GetString(); + } + catch + { + name = null; + } + + switch (name) + { + case "remove-bg": + { + List exceptions = []; + + try + { + var deserialized = JsonSerializer.Deserialize(json, options); + if (deserialized != null) + { + return new ExtensionVariants::RemoveBg(deserialized); + } + } + catch (JsonException e) + { + exceptions.Add(e); + } + + throw new AggregateException(exceptions); + } + case "ai-auto-description": + { + List exceptions = []; + + try + { + return new ExtensionVariants::AIAutoDescription( + JsonSerializer.Deserialize(json, options) + ); + } + catch (JsonException e) + { + exceptions.Add(e); + } + + throw new AggregateException(exceptions); + } + default: + { + List exceptions = []; + + try + { + var deserialized = JsonSerializer.Deserialize( + json, + options + ); + if (deserialized != null) + { + return new ExtensionVariants::AutoTaggingExtension(deserialized); + } + } + catch (JsonException e) + { + exceptions.Add(e); + } + + throw new AggregateException(exceptions); + } + } + } + + public override void Write( + Utf8JsonWriter writer, + Extension value, + JsonSerializerOptions options + ) + { + object variant = value switch + { + ExtensionVariants::RemoveBg(var removeBg) => removeBg, + ExtensionVariants::AutoTaggingExtension(var autoTagging) => autoTagging, + ExtensionVariants::AIAutoDescription(var aiAutoDescription) => aiAutoDescription, + _ => throw new ArgumentOutOfRangeException(nameof(value)), + }; + JsonSerializer.Serialize(writer, variant, options); + } +} diff --git a/src/Imagekit/Models/Files/FileUpdateParamsProperties/UpdateProperties/UpdateFileDetailsProperties/ExtensionProperties/AutoTaggingExtension.cs b/src/Imagekit/Models/Files/FileUpdateParamsProperties/UpdateProperties/UpdateFileDetailsProperties/ExtensionProperties/AutoTaggingExtension.cs new file mode 100644 index 00000000..61e0caf0 --- /dev/null +++ b/src/Imagekit/Models/Files/FileUpdateParamsProperties/UpdateProperties/UpdateFileDetailsProperties/ExtensionProperties/AutoTaggingExtension.cs @@ -0,0 +1,100 @@ +using System; +using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; +using System.Text.Json; +using System.Text.Json.Serialization; +using Imagekit.Models.Files.FileUpdateParamsProperties.UpdateProperties.UpdateFileDetailsProperties.ExtensionProperties.AutoTaggingExtensionProperties; + +namespace Imagekit.Models.Files.FileUpdateParamsProperties.UpdateProperties.UpdateFileDetailsProperties.ExtensionProperties; + +[JsonConverter(typeof(ModelConverter))] +public sealed record class AutoTaggingExtension : ModelBase, IFromRaw +{ + /// + /// Maximum number of tags to attach to the asset. + /// + public required long MaxTags + { + get + { + if (!this.Properties.TryGetValue("maxTags", out JsonElement element)) + throw new ArgumentOutOfRangeException("maxTags", "Missing required argument"); + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions); + } + set + { + this.Properties["maxTags"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + /// + /// Minimum confidence level for tags to be considered valid. + /// + public required long MinConfidence + { + get + { + if (!this.Properties.TryGetValue("minConfidence", out JsonElement element)) + throw new ArgumentOutOfRangeException("minConfidence", "Missing required argument"); + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions); + } + set + { + this.Properties["minConfidence"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + /// + /// Specifies the auto-tagging extension used. + /// + public required ApiEnum Name + { + get + { + if (!this.Properties.TryGetValue("name", out JsonElement element)) + throw new ArgumentOutOfRangeException("name", "Missing required argument"); + + return JsonSerializer.Deserialize>( + element, + ModelBase.SerializerOptions + ); + } + set + { + this.Properties["name"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + public override void Validate() + { + _ = this.MaxTags; + _ = this.MinConfidence; + this.Name.Validate(); + } + + public AutoTaggingExtension() { } + +#pragma warning disable CS8618 + [SetsRequiredMembers] + AutoTaggingExtension(Dictionary properties) + { + Properties = properties; + } +#pragma warning restore CS8618 + + public static AutoTaggingExtension FromRawUnchecked(Dictionary properties) + { + return new(properties); + } +} diff --git a/src/Imagekit/Models/Files/FileUpdateParamsProperties/UpdateProperties/UpdateFileDetailsProperties/ExtensionProperties/AutoTaggingExtensionProperties/Name.cs b/src/Imagekit/Models/Files/FileUpdateParamsProperties/UpdateProperties/UpdateFileDetailsProperties/ExtensionProperties/AutoTaggingExtensionProperties/Name.cs new file mode 100644 index 00000000..2f988a2d --- /dev/null +++ b/src/Imagekit/Models/Files/FileUpdateParamsProperties/UpdateProperties/UpdateFileDetailsProperties/ExtensionProperties/AutoTaggingExtensionProperties/Name.cs @@ -0,0 +1,46 @@ +using System; +using System.Text.Json; +using System.Text.Json.Serialization; + +namespace Imagekit.Models.Files.FileUpdateParamsProperties.UpdateProperties.UpdateFileDetailsProperties.ExtensionProperties.AutoTaggingExtensionProperties; + +/// +/// Specifies the auto-tagging extension used. +/// +[JsonConverter(typeof(NameConverter))] +public enum Name +{ + GoogleAutoTagging, + AwsAutoTagging, +} + +sealed class NameConverter : JsonConverter +{ + public override Name Read( + ref Utf8JsonReader reader, + Type typeToConvert, + JsonSerializerOptions options + ) + { + return JsonSerializer.Deserialize(ref reader, options) switch + { + "google-auto-tagging" => Name.GoogleAutoTagging, + "aws-auto-tagging" => Name.AwsAutoTagging, + _ => (Name)(-1), + }; + } + + public override void Write(Utf8JsonWriter writer, Name value, JsonSerializerOptions options) + { + JsonSerializer.Serialize( + writer, + value switch + { + Name.GoogleAutoTagging => "google-auto-tagging", + Name.AwsAutoTagging => "aws-auto-tagging", + _ => throw new ArgumentOutOfRangeException(nameof(value)), + }, + options + ); + } +} diff --git a/src/Imagekit/Models/Files/FileUpdateParamsProperties/UpdateProperties/UpdateFileDetailsProperties/ExtensionProperties/RemoveBg.cs b/src/Imagekit/Models/Files/FileUpdateParamsProperties/UpdateProperties/UpdateFileDetailsProperties/ExtensionProperties/RemoveBg.cs new file mode 100644 index 00000000..195549a9 --- /dev/null +++ b/src/Imagekit/Models/Files/FileUpdateParamsProperties/UpdateProperties/UpdateFileDetailsProperties/ExtensionProperties/RemoveBg.cs @@ -0,0 +1,74 @@ +using System; +using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; +using System.Text.Json; +using System.Text.Json.Serialization; +using Imagekit.Models.Files.FileUpdateParamsProperties.UpdateProperties.UpdateFileDetailsProperties.ExtensionProperties.RemoveBgProperties; + +namespace Imagekit.Models.Files.FileUpdateParamsProperties.UpdateProperties.UpdateFileDetailsProperties.ExtensionProperties; + +[JsonConverter(typeof(ModelConverter))] +public sealed record class RemoveBg : ModelBase, IFromRaw +{ + /// + /// Specifies the background removal extension. + /// + public JsonElement Name + { + get + { + if (!this.Properties.TryGetValue("name", out JsonElement element)) + throw new ArgumentOutOfRangeException("name", "Missing required argument"); + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions); + } + set + { + this.Properties["name"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + public Options? Options + { + get + { + if (!this.Properties.TryGetValue("options", out JsonElement element)) + return null; + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions); + } + set + { + this.Properties["options"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + public override void Validate() + { + this.Options?.Validate(); + } + + public RemoveBg() + { + this.Name = JsonSerializer.Deserialize("\"remove-bg\""); + } + +#pragma warning disable CS8618 + [SetsRequiredMembers] + RemoveBg(Dictionary properties) + { + Properties = properties; + } +#pragma warning restore CS8618 + + public static RemoveBg FromRawUnchecked(Dictionary properties) + { + return new(properties); + } +} diff --git a/src/Imagekit/Models/Files/FileUpdateParamsProperties/UpdateProperties/UpdateFileDetailsProperties/ExtensionProperties/RemoveBgProperties/Options.cs b/src/Imagekit/Models/Files/FileUpdateParamsProperties/UpdateProperties/UpdateFileDetailsProperties/ExtensionProperties/RemoveBgProperties/Options.cs new file mode 100644 index 00000000..b2051fb0 --- /dev/null +++ b/src/Imagekit/Models/Files/FileUpdateParamsProperties/UpdateProperties/UpdateFileDetailsProperties/ExtensionProperties/RemoveBgProperties/Options.cs @@ -0,0 +1,122 @@ +using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; +using System.Text.Json; +using System.Text.Json.Serialization; + +namespace Imagekit.Models.Files.FileUpdateParamsProperties.UpdateProperties.UpdateFileDetailsProperties.ExtensionProperties.RemoveBgProperties; + +[JsonConverter(typeof(ModelConverter))] +public sealed record class Options : ModelBase, IFromRaw +{ + /// + /// Whether to add an artificial shadow to the result. Default is false. Note: + /// Adding shadows is currently only supported for car photos. + /// + public bool? AddShadow + { + get + { + if (!this.Properties.TryGetValue("add_shadow", out JsonElement element)) + return null; + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions); + } + set + { + this.Properties["add_shadow"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + /// + /// Specifies a solid color background using hex code (e.g., "81d4fa", "fff") + /// or color name (e.g., "green"). If this parameter is set, `bg_image_url` must + /// be empty. + /// + public string? BgColor + { + get + { + if (!this.Properties.TryGetValue("bg_color", out JsonElement element)) + return null; + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions); + } + set + { + this.Properties["bg_color"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + /// + /// Sets a background image from a URL. If this parameter is set, `bg_color` + /// must be empty. + /// + public string? BgImageURL + { + get + { + if (!this.Properties.TryGetValue("bg_image_url", out JsonElement element)) + return null; + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions); + } + set + { + this.Properties["bg_image_url"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + /// + /// Allows semi-transparent regions in the result. Default is true. Note: Semitransparency + /// is currently only supported for car windows. + /// + public bool? Semitransparency + { + get + { + if (!this.Properties.TryGetValue("semitransparency", out JsonElement element)) + return null; + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions); + } + set + { + this.Properties["semitransparency"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + public override void Validate() + { + _ = this.AddShadow; + _ = this.BgColor; + _ = this.BgImageURL; + _ = this.Semitransparency; + } + + public Options() { } + +#pragma warning disable CS8618 + [SetsRequiredMembers] + Options(Dictionary properties) + { + Properties = properties; + } +#pragma warning restore CS8618 + + public static Options FromRawUnchecked(Dictionary properties) + { + return new(properties); + } +} diff --git a/src/Imagekit/Models/Files/FileUpdateParamsProperties/UpdateProperties/UpdateFileDetailsProperties/ExtensionVariants/All.cs b/src/Imagekit/Models/Files/FileUpdateParamsProperties/UpdateProperties/UpdateFileDetailsProperties/ExtensionVariants/All.cs new file mode 100644 index 00000000..b1d2c160 --- /dev/null +++ b/src/Imagekit/Models/Files/FileUpdateParamsProperties/UpdateProperties/UpdateFileDetailsProperties/ExtensionVariants/All.cs @@ -0,0 +1,46 @@ +using System.Text.Json; +using ExtensionProperties = Imagekit.Models.Files.FileUpdateParamsProperties.UpdateProperties.UpdateFileDetailsProperties.ExtensionProperties; + +namespace Imagekit.Models.Files.FileUpdateParamsProperties.UpdateProperties.UpdateFileDetailsProperties.ExtensionVariants; + +public sealed record class RemoveBg(ExtensionProperties::RemoveBg Value) + : Extension, + IVariant +{ + public static RemoveBg From(ExtensionProperties::RemoveBg value) + { + return new(value); + } + + public override void Validate() + { + this.Value.Validate(); + } +} + +public sealed record class AutoTaggingExtension(ExtensionProperties::AutoTaggingExtension Value) + : Extension, + IVariant +{ + public static AutoTaggingExtension From(ExtensionProperties::AutoTaggingExtension value) + { + return new(value); + } + + public override void Validate() + { + this.Value.Validate(); + } +} + +public sealed record class AIAutoDescription(JsonElement Value) + : Extension, + IVariant +{ + public static AIAutoDescription From(JsonElement value) + { + return new(value); + } + + public override void Validate() { } +} diff --git a/src/Imagekit/Models/Files/FileUpdateParamsProperties/UpdateProperties/UpdateFileDetailsProperties/RemoveAITags.cs b/src/Imagekit/Models/Files/FileUpdateParamsProperties/UpdateProperties/UpdateFileDetailsProperties/RemoveAITags.cs new file mode 100644 index 00000000..f47a66cb --- /dev/null +++ b/src/Imagekit/Models/Files/FileUpdateParamsProperties/UpdateProperties/UpdateFileDetailsProperties/RemoveAITags.cs @@ -0,0 +1,115 @@ +using System; +using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; +using System.Text.Json; +using System.Text.Json.Serialization; +using Imagekit.Models.Files.FileUpdateParamsProperties.UpdateProperties.UpdateFileDetailsProperties.RemoveAITagsVariants; + +namespace Imagekit.Models.Files.FileUpdateParamsProperties.UpdateProperties.UpdateFileDetailsProperties; + +/// +/// An array of AITags associated with the file that you want to remove, e.g. `["car", +/// "vehicle", "motorsports"]`. +/// +/// If you want to remove all AITags associated with the file, send a string - "all". +/// +/// Note: The remove operation for `AITags` executes before any of the `extensions` +/// are processed. +/// +[JsonConverter(typeof(RemoveAITagsConverter))] +public abstract record class RemoveAITags +{ + internal RemoveAITags() { } + + public static implicit operator RemoveAITags(List value) => new Strings(value); + + public bool TryPickStrings([NotNullWhen(true)] out List? value) + { + value = (this as Strings)?.Value; + return value != null; + } + + public bool TryPickAll([NotNullWhen(true)] out JsonElement? value) + { + value = (this as All)?.Value; + return value != null; + } + + public void Switch(Action strings, Action all) + { + switch (this) + { + case Strings inner: + strings(inner); + break; + case All inner: + all(inner); + break; + default: + throw new InvalidOperationException(); + } + } + + public T Match(Func strings, Func all) + { + return this switch + { + Strings inner => strings(inner), + All inner => all(inner), + _ => throw new InvalidOperationException(), + }; + } + + public abstract void Validate(); +} + +sealed class RemoveAITagsConverter : JsonConverter +{ + public override RemoveAITags? Read( + ref Utf8JsonReader reader, + Type typeToConvert, + JsonSerializerOptions options + ) + { + List exceptions = []; + + try + { + return new All(JsonSerializer.Deserialize(ref reader, options)); + } + catch (JsonException e) + { + exceptions.Add(e); + } + + try + { + var deserialized = JsonSerializer.Deserialize>(ref reader, options); + if (deserialized != null) + { + return new Strings(deserialized); + } + } + catch (JsonException e) + { + exceptions.Add(e); + } + + throw new AggregateException(exceptions); + } + + public override void Write( + Utf8JsonWriter writer, + RemoveAITags value, + JsonSerializerOptions options + ) + { + object variant = value switch + { + Strings(var strings) => strings, + All(var all) => all, + _ => throw new ArgumentOutOfRangeException(nameof(value)), + }; + JsonSerializer.Serialize(writer, variant, options); + } +} diff --git a/src/Imagekit/Models/Files/FileUpdateParamsProperties/UpdateProperties/UpdateFileDetailsProperties/RemoveAITagsVariants/All.cs b/src/Imagekit/Models/Files/FileUpdateParamsProperties/UpdateProperties/UpdateFileDetailsProperties/RemoveAITagsVariants/All.cs new file mode 100644 index 00000000..4fd3a772 --- /dev/null +++ b/src/Imagekit/Models/Files/FileUpdateParamsProperties/UpdateProperties/UpdateFileDetailsProperties/RemoveAITagsVariants/All.cs @@ -0,0 +1,26 @@ +using System.Collections.Generic; +using System.Text.Json; + +namespace Imagekit.Models.Files.FileUpdateParamsProperties.UpdateProperties.UpdateFileDetailsProperties.RemoveAITagsVariants; + +public sealed record class Strings(List Value) + : RemoveAITags, + IVariant> +{ + public static Strings From(List value) + { + return new(value); + } + + public override void Validate() { } +} + +public sealed record class All(JsonElement Value) : RemoveAITags, IVariant +{ + public static All From(JsonElement value) + { + return new(value); + } + + public override void Validate() { } +} diff --git a/src/Imagekit/Models/Files/FileUpdateParamsProperties/UpdateVariants/All.cs b/src/Imagekit/Models/Files/FileUpdateParamsProperties/UpdateVariants/All.cs new file mode 100644 index 00000000..aea0129a --- /dev/null +++ b/src/Imagekit/Models/Files/FileUpdateParamsProperties/UpdateVariants/All.cs @@ -0,0 +1,33 @@ +using UpdateProperties = Imagekit.Models.Files.FileUpdateParamsProperties.UpdateProperties; + +namespace Imagekit.Models.Files.FileUpdateParamsProperties.UpdateVariants; + +public sealed record class UpdateFileDetails(UpdateProperties::UpdateFileDetails Value) + : Update, + IVariant +{ + public static UpdateFileDetails From(UpdateProperties::UpdateFileDetails value) + { + return new(value); + } + + public override void Validate() + { + this.Value.Validate(); + } +} + +public sealed record class ChangePublicationStatus(UpdateProperties::ChangePublicationStatus Value) + : Update, + IVariant +{ + public static ChangePublicationStatus From(UpdateProperties::ChangePublicationStatus value) + { + return new(value); + } + + public override void Validate() + { + this.Value.Validate(); + } +} diff --git a/src/Imagekit/Models/Files/FileUpdateResponse.cs b/src/Imagekit/Models/Files/FileUpdateResponse.cs new file mode 100644 index 00000000..8f361123 --- /dev/null +++ b/src/Imagekit/Models/Files/FileUpdateResponse.cs @@ -0,0 +1,600 @@ +using System; +using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; +using System.Text.Json; +using System.Text.Json.Serialization; +using Imagekit.Models.Files.FileUpdateResponseProperties.IntersectionMember1Properties; +using FileProperties = Imagekit.Models.Files.FileProperties; + +namespace Imagekit.Models.Files; + +/// +/// Object containing details of a file or file version. +/// +[JsonConverter(typeof(ModelConverter))] +public sealed record class FileUpdateResponse : ModelBase, IFromRaw +{ + /// + /// An array of tags assigned to the file by auto tagging. + /// + public List? AITags + { + get + { + if (!this.Properties.TryGetValue("AITags", out JsonElement element)) + return null; + + return JsonSerializer.Deserialize?>( + element, + ModelBase.SerializerOptions + ); + } + set + { + this.Properties["AITags"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + /// + /// Date and time when the file was uploaded. The date and time is in ISO8601 + /// format. + /// + public DateTime? CreatedAt + { + get + { + if (!this.Properties.TryGetValue("createdAt", out JsonElement element)) + return null; + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions); + } + set + { + this.Properties["createdAt"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + /// + /// An string with custom coordinates of the file. + /// + public string? CustomCoordinates + { + get + { + if (!this.Properties.TryGetValue("customCoordinates", out JsonElement element)) + return null; + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions); + } + set + { + this.Properties["customCoordinates"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + /// + /// An object with custom metadata for the file. + /// + public Dictionary? CustomMetadata + { + get + { + if (!this.Properties.TryGetValue("customMetadata", out JsonElement element)) + return null; + + return JsonSerializer.Deserialize?>( + element, + ModelBase.SerializerOptions + ); + } + set + { + this.Properties["customMetadata"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + /// + /// Optional text to describe the contents of the file. Can be set by the user + /// or the ai-auto-description extension. + /// + public string? Description + { + get + { + if (!this.Properties.TryGetValue("description", out JsonElement element)) + return null; + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions); + } + set + { + this.Properties["description"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + /// + /// Unique identifier of the asset. + /// + public string? FileID + { + get + { + if (!this.Properties.TryGetValue("fileId", out JsonElement element)) + return null; + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions); + } + set + { + this.Properties["fileId"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + /// + /// Path of the file. This is the path you would use in the URL to access the + /// file. For example, if the file is at the root of the media library, the path + /// will be `/file.jpg`. If the file is inside a folder named `images`, the path + /// will be `/images/file.jpg`. + /// + public string? FilePath + { + get + { + if (!this.Properties.TryGetValue("filePath", out JsonElement element)) + return null; + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions); + } + set + { + this.Properties["filePath"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + /// + /// Type of the file. Possible values are `image`, `non-image`. + /// + public string? FileType + { + get + { + if (!this.Properties.TryGetValue("fileType", out JsonElement element)) + return null; + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions); + } + set + { + this.Properties["fileType"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + /// + /// Specifies if the image has an alpha channel. + /// + public bool? HasAlpha + { + get + { + if (!this.Properties.TryGetValue("hasAlpha", out JsonElement element)) + return null; + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions); + } + set + { + this.Properties["hasAlpha"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + /// + /// Height of the file. + /// + public double? Height + { + get + { + if (!this.Properties.TryGetValue("height", out JsonElement element)) + return null; + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions); + } + set + { + this.Properties["height"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + /// + /// Specifies if the file is private or not. + /// + public bool? IsPrivateFile + { + get + { + if (!this.Properties.TryGetValue("isPrivateFile", out JsonElement element)) + return null; + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions); + } + set + { + this.Properties["isPrivateFile"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + /// + /// Specifies if the file is published or not. + /// + public bool? IsPublished + { + get + { + if (!this.Properties.TryGetValue("isPublished", out JsonElement element)) + return null; + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions); + } + set + { + this.Properties["isPublished"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + /// + /// MIME type of the file. + /// + public string? Mime + { + get + { + if (!this.Properties.TryGetValue("mime", out JsonElement element)) + return null; + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions); + } + set + { + this.Properties["mime"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + /// + /// Name of the asset. + /// + public string? Name + { + get + { + if (!this.Properties.TryGetValue("name", out JsonElement element)) + return null; + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions); + } + set + { + this.Properties["name"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + /// + /// Size of the file in bytes. + /// + public double? Size + { + get + { + if (!this.Properties.TryGetValue("size", out JsonElement element)) + return null; + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions); + } + set + { + this.Properties["size"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + /// + /// An array of tags assigned to the file. Tags are used to search files in the + /// media library. + /// + public List? Tags + { + get + { + if (!this.Properties.TryGetValue("tags", out JsonElement element)) + return null; + + return JsonSerializer.Deserialize?>(element, ModelBase.SerializerOptions); + } + set + { + this.Properties["tags"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + /// + /// URL of the thumbnail image. This URL is used to access the thumbnail image + /// of the file in the media library. + /// + public string? Thumbnail + { + get + { + if (!this.Properties.TryGetValue("thumbnail", out JsonElement element)) + return null; + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions); + } + set + { + this.Properties["thumbnail"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + /// + /// Type of the asset. + /// + public ApiEnum? Type + { + get + { + if (!this.Properties.TryGetValue("type", out JsonElement element)) + return null; + + return JsonSerializer.Deserialize?>( + element, + ModelBase.SerializerOptions + ); + } + set + { + this.Properties["type"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + /// + /// Date and time when the file was last updated. The date and time is in ISO8601 + /// format. + /// + public DateTime? UpdatedAt + { + get + { + if (!this.Properties.TryGetValue("updatedAt", out JsonElement element)) + return null; + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions); + } + set + { + this.Properties["updatedAt"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + /// + /// URL of the file. + /// + public string? URL + { + get + { + if (!this.Properties.TryGetValue("url", out JsonElement element)) + return null; + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions); + } + set + { + this.Properties["url"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + /// + /// An object with details of the file version. + /// + public FileProperties::VersionInfo? VersionInfo + { + get + { + if (!this.Properties.TryGetValue("versionInfo", out JsonElement element)) + return null; + + return JsonSerializer.Deserialize( + element, + ModelBase.SerializerOptions + ); + } + set + { + this.Properties["versionInfo"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + /// + /// Width of the file. + /// + public double? Width + { + get + { + if (!this.Properties.TryGetValue("width", out JsonElement element)) + return null; + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions); + } + set + { + this.Properties["width"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + public ExtensionStatus? ExtensionStatus + { + get + { + if (!this.Properties.TryGetValue("extensionStatus", out JsonElement element)) + return null; + + return JsonSerializer.Deserialize( + element, + ModelBase.SerializerOptions + ); + } + set + { + this.Properties["extensionStatus"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + public static implicit operator File(FileUpdateResponse fileUpdateResponse) => + new() + { + AITags = fileUpdateResponse.AITags, + CreatedAt = fileUpdateResponse.CreatedAt, + CustomCoordinates = fileUpdateResponse.CustomCoordinates, + CustomMetadata = fileUpdateResponse.CustomMetadata, + Description = fileUpdateResponse.Description, + FileID = fileUpdateResponse.FileID, + FilePath = fileUpdateResponse.FilePath, + FileType = fileUpdateResponse.FileType, + HasAlpha = fileUpdateResponse.HasAlpha, + Height = fileUpdateResponse.Height, + IsPrivateFile = fileUpdateResponse.IsPrivateFile, + IsPublished = fileUpdateResponse.IsPublished, + Mime = fileUpdateResponse.Mime, + Name = fileUpdateResponse.Name, + Size = fileUpdateResponse.Size, + Tags = fileUpdateResponse.Tags, + Thumbnail = fileUpdateResponse.Thumbnail, + Type = fileUpdateResponse.Type, + UpdatedAt = fileUpdateResponse.UpdatedAt, + URL = fileUpdateResponse.URL, + VersionInfo = fileUpdateResponse.VersionInfo, + Width = fileUpdateResponse.Width, + }; + + public override void Validate() + { + foreach (var item in this.AITags ?? []) + { + item.Validate(); + } + _ = this.CreatedAt; + _ = this.CustomCoordinates; + if (this.CustomMetadata != null) + { + foreach (var item in this.CustomMetadata.Values) + { + _ = item; + } + } + _ = this.Description; + _ = this.FileID; + _ = this.FilePath; + _ = this.FileType; + _ = this.HasAlpha; + _ = this.Height; + _ = this.IsPrivateFile; + _ = this.IsPublished; + _ = this.Mime; + _ = this.Name; + _ = this.Size; + foreach (var item in this.Tags ?? []) + { + _ = item; + } + _ = this.Thumbnail; + this.Type?.Validate(); + _ = this.UpdatedAt; + _ = this.URL; + this.VersionInfo?.Validate(); + _ = this.Width; + this.ExtensionStatus?.Validate(); + } + + public FileUpdateResponse() { } + +#pragma warning disable CS8618 + [SetsRequiredMembers] + FileUpdateResponse(Dictionary properties) + { + Properties = properties; + } +#pragma warning restore CS8618 + + public static FileUpdateResponse FromRawUnchecked(Dictionary properties) + { + return new(properties); + } +} diff --git a/src/Imagekit/Models/Files/FileUpdateResponseProperties/IntersectionMember1.cs b/src/Imagekit/Models/Files/FileUpdateResponseProperties/IntersectionMember1.cs new file mode 100644 index 00000000..18f1f617 --- /dev/null +++ b/src/Imagekit/Models/Files/FileUpdateResponseProperties/IntersectionMember1.cs @@ -0,0 +1,52 @@ +using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; +using System.Text.Json; +using System.Text.Json.Serialization; +using Imagekit.Models.Files.FileUpdateResponseProperties.IntersectionMember1Properties; + +namespace Imagekit.Models.Files.FileUpdateResponseProperties; + +[JsonConverter(typeof(ModelConverter))] +public sealed record class IntersectionMember1 : ModelBase, IFromRaw +{ + public ExtensionStatus? ExtensionStatus + { + get + { + if (!this.Properties.TryGetValue("extensionStatus", out JsonElement element)) + return null; + + return JsonSerializer.Deserialize( + element, + ModelBase.SerializerOptions + ); + } + set + { + this.Properties["extensionStatus"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + public override void Validate() + { + this.ExtensionStatus?.Validate(); + } + + public IntersectionMember1() { } + +#pragma warning disable CS8618 + [SetsRequiredMembers] + IntersectionMember1(Dictionary properties) + { + Properties = properties; + } +#pragma warning restore CS8618 + + public static IntersectionMember1 FromRawUnchecked(Dictionary properties) + { + return new(properties); + } +} diff --git a/src/Imagekit/Models/Files/FileUpdateResponseProperties/IntersectionMember1Properties/ExtensionStatus.cs b/src/Imagekit/Models/Files/FileUpdateResponseProperties/IntersectionMember1Properties/ExtensionStatus.cs new file mode 100644 index 00000000..c540e9b8 --- /dev/null +++ b/src/Imagekit/Models/Files/FileUpdateResponseProperties/IntersectionMember1Properties/ExtensionStatus.cs @@ -0,0 +1,118 @@ +using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; +using System.Text.Json; +using System.Text.Json.Serialization; +using Imagekit.Models.Files.FileUpdateResponseProperties.IntersectionMember1Properties.ExtensionStatusProperties; + +namespace Imagekit.Models.Files.FileUpdateResponseProperties.IntersectionMember1Properties; + +[JsonConverter(typeof(ModelConverter))] +public sealed record class ExtensionStatus : ModelBase, IFromRaw +{ + public ApiEnum? AIAutoDescription + { + get + { + if (!this.Properties.TryGetValue("ai-auto-description", out JsonElement element)) + return null; + + return JsonSerializer.Deserialize?>( + element, + ModelBase.SerializerOptions + ); + } + set + { + this.Properties["ai-auto-description"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + public ApiEnum? AwsAutoTagging + { + get + { + if (!this.Properties.TryGetValue("aws-auto-tagging", out JsonElement element)) + return null; + + return JsonSerializer.Deserialize?>( + element, + ModelBase.SerializerOptions + ); + } + set + { + this.Properties["aws-auto-tagging"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + public ApiEnum? GoogleAutoTagging + { + get + { + if (!this.Properties.TryGetValue("google-auto-tagging", out JsonElement element)) + return null; + + return JsonSerializer.Deserialize?>( + element, + ModelBase.SerializerOptions + ); + } + set + { + this.Properties["google-auto-tagging"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + public ApiEnum? RemoveBg + { + get + { + if (!this.Properties.TryGetValue("remove-bg", out JsonElement element)) + return null; + + return JsonSerializer.Deserialize?>( + element, + ModelBase.SerializerOptions + ); + } + set + { + this.Properties["remove-bg"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + public override void Validate() + { + this.AIAutoDescription?.Validate(); + this.AwsAutoTagging?.Validate(); + this.GoogleAutoTagging?.Validate(); + this.RemoveBg?.Validate(); + } + + public ExtensionStatus() { } + +#pragma warning disable CS8618 + [SetsRequiredMembers] + ExtensionStatus(Dictionary properties) + { + Properties = properties; + } +#pragma warning restore CS8618 + + public static ExtensionStatus FromRawUnchecked(Dictionary properties) + { + return new(properties); + } +} diff --git a/src/Imagekit/Models/Files/FileUpdateResponseProperties/IntersectionMember1Properties/ExtensionStatusProperties/AIAutoDescription.cs b/src/Imagekit/Models/Files/FileUpdateResponseProperties/IntersectionMember1Properties/ExtensionStatusProperties/AIAutoDescription.cs new file mode 100644 index 00000000..5411f57f --- /dev/null +++ b/src/Imagekit/Models/Files/FileUpdateResponseProperties/IntersectionMember1Properties/ExtensionStatusProperties/AIAutoDescription.cs @@ -0,0 +1,50 @@ +using System; +using System.Text.Json; +using System.Text.Json.Serialization; + +namespace Imagekit.Models.Files.FileUpdateResponseProperties.IntersectionMember1Properties.ExtensionStatusProperties; + +[JsonConverter(typeof(AIAutoDescriptionConverter))] +public enum AIAutoDescription +{ + Success, + Pending, + Failed, +} + +sealed class AIAutoDescriptionConverter : JsonConverter +{ + public override AIAutoDescription Read( + ref Utf8JsonReader reader, + Type typeToConvert, + JsonSerializerOptions options + ) + { + return JsonSerializer.Deserialize(ref reader, options) switch + { + "success" => AIAutoDescription.Success, + "pending" => AIAutoDescription.Pending, + "failed" => AIAutoDescription.Failed, + _ => (AIAutoDescription)(-1), + }; + } + + public override void Write( + Utf8JsonWriter writer, + AIAutoDescription value, + JsonSerializerOptions options + ) + { + JsonSerializer.Serialize( + writer, + value switch + { + AIAutoDescription.Success => "success", + AIAutoDescription.Pending => "pending", + AIAutoDescription.Failed => "failed", + _ => throw new ArgumentOutOfRangeException(nameof(value)), + }, + options + ); + } +} diff --git a/src/Imagekit/Models/Files/FileUpdateResponseProperties/IntersectionMember1Properties/ExtensionStatusProperties/AwsAutoTagging.cs b/src/Imagekit/Models/Files/FileUpdateResponseProperties/IntersectionMember1Properties/ExtensionStatusProperties/AwsAutoTagging.cs new file mode 100644 index 00000000..4e795b7b --- /dev/null +++ b/src/Imagekit/Models/Files/FileUpdateResponseProperties/IntersectionMember1Properties/ExtensionStatusProperties/AwsAutoTagging.cs @@ -0,0 +1,50 @@ +using System; +using System.Text.Json; +using System.Text.Json.Serialization; + +namespace Imagekit.Models.Files.FileUpdateResponseProperties.IntersectionMember1Properties.ExtensionStatusProperties; + +[JsonConverter(typeof(AwsAutoTaggingConverter))] +public enum AwsAutoTagging +{ + Success, + Pending, + Failed, +} + +sealed class AwsAutoTaggingConverter : JsonConverter +{ + public override AwsAutoTagging Read( + ref Utf8JsonReader reader, + Type typeToConvert, + JsonSerializerOptions options + ) + { + return JsonSerializer.Deserialize(ref reader, options) switch + { + "success" => AwsAutoTagging.Success, + "pending" => AwsAutoTagging.Pending, + "failed" => AwsAutoTagging.Failed, + _ => (AwsAutoTagging)(-1), + }; + } + + public override void Write( + Utf8JsonWriter writer, + AwsAutoTagging value, + JsonSerializerOptions options + ) + { + JsonSerializer.Serialize( + writer, + value switch + { + AwsAutoTagging.Success => "success", + AwsAutoTagging.Pending => "pending", + AwsAutoTagging.Failed => "failed", + _ => throw new ArgumentOutOfRangeException(nameof(value)), + }, + options + ); + } +} diff --git a/src/Imagekit/Models/Files/FileUpdateResponseProperties/IntersectionMember1Properties/ExtensionStatusProperties/GoogleAutoTagging.cs b/src/Imagekit/Models/Files/FileUpdateResponseProperties/IntersectionMember1Properties/ExtensionStatusProperties/GoogleAutoTagging.cs new file mode 100644 index 00000000..98e402cc --- /dev/null +++ b/src/Imagekit/Models/Files/FileUpdateResponseProperties/IntersectionMember1Properties/ExtensionStatusProperties/GoogleAutoTagging.cs @@ -0,0 +1,50 @@ +using System; +using System.Text.Json; +using System.Text.Json.Serialization; + +namespace Imagekit.Models.Files.FileUpdateResponseProperties.IntersectionMember1Properties.ExtensionStatusProperties; + +[JsonConverter(typeof(GoogleAutoTaggingConverter))] +public enum GoogleAutoTagging +{ + Success, + Pending, + Failed, +} + +sealed class GoogleAutoTaggingConverter : JsonConverter +{ + public override GoogleAutoTagging Read( + ref Utf8JsonReader reader, + Type typeToConvert, + JsonSerializerOptions options + ) + { + return JsonSerializer.Deserialize(ref reader, options) switch + { + "success" => GoogleAutoTagging.Success, + "pending" => GoogleAutoTagging.Pending, + "failed" => GoogleAutoTagging.Failed, + _ => (GoogleAutoTagging)(-1), + }; + } + + public override void Write( + Utf8JsonWriter writer, + GoogleAutoTagging value, + JsonSerializerOptions options + ) + { + JsonSerializer.Serialize( + writer, + value switch + { + GoogleAutoTagging.Success => "success", + GoogleAutoTagging.Pending => "pending", + GoogleAutoTagging.Failed => "failed", + _ => throw new ArgumentOutOfRangeException(nameof(value)), + }, + options + ); + } +} diff --git a/src/Imagekit/Models/Files/FileUpdateResponseProperties/IntersectionMember1Properties/ExtensionStatusProperties/RemoveBg.cs b/src/Imagekit/Models/Files/FileUpdateResponseProperties/IntersectionMember1Properties/ExtensionStatusProperties/RemoveBg.cs new file mode 100644 index 00000000..6f293e15 --- /dev/null +++ b/src/Imagekit/Models/Files/FileUpdateResponseProperties/IntersectionMember1Properties/ExtensionStatusProperties/RemoveBg.cs @@ -0,0 +1,46 @@ +using System; +using System.Text.Json; +using System.Text.Json.Serialization; + +namespace Imagekit.Models.Files.FileUpdateResponseProperties.IntersectionMember1Properties.ExtensionStatusProperties; + +[JsonConverter(typeof(RemoveBgConverter))] +public enum RemoveBg +{ + Success, + Pending, + Failed, +} + +sealed class RemoveBgConverter : JsonConverter +{ + public override RemoveBg Read( + ref Utf8JsonReader reader, + Type typeToConvert, + JsonSerializerOptions options + ) + { + return JsonSerializer.Deserialize(ref reader, options) switch + { + "success" => RemoveBg.Success, + "pending" => RemoveBg.Pending, + "failed" => RemoveBg.Failed, + _ => (RemoveBg)(-1), + }; + } + + public override void Write(Utf8JsonWriter writer, RemoveBg value, JsonSerializerOptions options) + { + JsonSerializer.Serialize( + writer, + value switch + { + RemoveBg.Success => "success", + RemoveBg.Pending => "pending", + RemoveBg.Failed => "failed", + _ => throw new ArgumentOutOfRangeException(nameof(value)), + }, + options + ); + } +} diff --git a/src/Imagekit/Models/Files/FileUploadParams.cs b/src/Imagekit/Models/Files/FileUploadParams.cs new file mode 100644 index 00000000..6d1d3bd2 --- /dev/null +++ b/src/Imagekit/Models/Files/FileUploadParams.cs @@ -0,0 +1,638 @@ +using System; +using System.Collections.Generic; +using System.Net.Http; +using System.Text; +using System.Text.Json; +using FileUploadParamsProperties = Imagekit.Models.Files.FileUploadParamsProperties; + +namespace Imagekit.Models.Files; + +/// +/// ImageKit.io allows you to upload files directly from both the server and client +/// sides. For server-side uploads, private API key authentication is used. For client-side +/// uploads, generate a one-time `token`, `signature`, and `expire` from your secure +/// backend using private API. [Learn more](/docs/api-reference/upload-file/upload-file#how-to-implement-client-side-file-upload) +/// about how to implement client-side file upload. +/// +/// The [V2 API](/docs/api-reference/upload-file/upload-file-v2) enhances security +/// by verifying the entire payload using JWT. +/// +/// **File size limit** \ On the free plan, the maximum upload file sizes are 20MB +/// for images, audio, and raw files and 100MB for videos. On the paid plan, these +/// limits increase to 40MB for images, audio, and raw files and 2GB for videos. These +/// limits can be further increased with higher-tier plans. +/// +/// **Version limit** \ A file can have a maximum of 100 versions. +/// +/// **Demo applications** +/// +/// - A full-fledged [upload widget using Uppy](https://github.com/imagekit-samples/uppy-uploader), +/// supporting file selections from local storage, URL, Dropbox, Google Drive, Instagram, +/// and more. - [Quick start guides](/docs/quick-start-guides) for various frameworks +/// and technologies. +/// +public sealed record class FileUploadParams : ParamsBase +{ + public Dictionary BodyProperties { get; set; } = []; + + /// + /// The API accepts any of the following: + /// + /// - **Binary data** – send the raw bytes as `multipart/form-data`. - **HTTP + /// / HTTPS URL** – a publicly reachable URL that ImageKit’s servers can fetch. + /// - **Base64 string** – the file encoded as a Base64 data URI or plain Base64. + /// + /// When supplying a URL, the server must receive the response headers within + /// 8 seconds; otherwise the request fails with 400 Bad Request. + /// + public required string File + { + get + { + if (!this.BodyProperties.TryGetValue("file", out JsonElement element)) + throw new ArgumentOutOfRangeException("file", "Missing required argument"); + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions) + ?? throw new ArgumentNullException("file"); + } + set + { + this.BodyProperties["file"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + /// + /// The name with which the file has to be uploaded. The file name can contain: + /// + /// - Alphanumeric Characters: `a-z`, `A-Z`, `0-9`. - Special Characters: + /// `.`, `-` + /// + /// Any other character including space will be replaced by `_` + /// + public required string FileName + { + get + { + if (!this.BodyProperties.TryGetValue("fileName", out JsonElement element)) + throw new ArgumentOutOfRangeException("fileName", "Missing required argument"); + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions) + ?? throw new ArgumentNullException("fileName"); + } + set + { + this.BodyProperties["fileName"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + /// + /// A unique value that the ImageKit.io server will use to recognize and prevent + /// subsequent retries for the same request. We suggest using V4 UUIDs, or another + /// random string with enough entropy to avoid collisions. This field is only + /// required for authentication when uploading a file from the client side. + /// + /// **Note**: Sending a value that has been used in the past will result in a + /// validation error. Even if your previous request resulted in an error, you + /// should always send a new value for this field. + /// + public string? Token + { + get + { + if (!this.BodyProperties.TryGetValue("token", out JsonElement element)) + return null; + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions); + } + set + { + this.BodyProperties["token"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + /// + /// Server-side checks to run on the asset. Read more about [Upload API checks](/docs/api-reference/upload-file/upload-file#upload-api-checks). + /// + public string? Checks + { + get + { + if (!this.BodyProperties.TryGetValue("checks", out JsonElement element)) + return null; + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions); + } + set + { + this.BodyProperties["checks"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + /// + /// Define an important area in the image. This is only relevant for image type files. + /// + /// - To be passed as a string with the x and y coordinates of the top-left + /// corner, and width and height of the area of interest in the format `x,y,width,height`. + /// For example - `10,10,100,100` - Can be used with fo-customtransformation. + /// - If this field is not specified and the file is overwritten, then customCoordinates + /// will be removed. + /// + public string? CustomCoordinates + { + get + { + if (!this.BodyProperties.TryGetValue("customCoordinates", out JsonElement element)) + return null; + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions); + } + set + { + this.BodyProperties["customCoordinates"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + /// + /// JSON key-value pairs to associate with the asset. Create the custom metadata + /// fields before setting these values. + /// + public Dictionary? CustomMetadata + { + get + { + if (!this.BodyProperties.TryGetValue("customMetadata", out JsonElement element)) + return null; + + return JsonSerializer.Deserialize?>( + element, + ModelBase.SerializerOptions + ); + } + set + { + this.BodyProperties["customMetadata"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + /// + /// Optional text to describe the contents of the file. + /// + public string? Description + { + get + { + if (!this.BodyProperties.TryGetValue("description", out JsonElement element)) + return null; + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions); + } + set + { + this.BodyProperties["description"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + /// + /// The time until your signature is valid. It must be a [Unix time](https://en.wikipedia.org/wiki/Unix_time) + /// in less than 1 hour into the future. It should be in seconds. This field is + /// only required for authentication when uploading a file from the client side. + /// + public long? Expire + { + get + { + if (!this.BodyProperties.TryGetValue("expire", out JsonElement element)) + return null; + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions); + } + set + { + this.BodyProperties["expire"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + /// + /// Array of extensions to be applied to the image. Each extension can be configured + /// with specific parameters based on the extension type. + /// + public List? Extensions + { + get + { + if (!this.BodyProperties.TryGetValue("extensions", out JsonElement element)) + return null; + + return JsonSerializer.Deserialize?>( + element, + ModelBase.SerializerOptions + ); + } + set + { + this.BodyProperties["extensions"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + /// + /// The folder path in which the image has to be uploaded. If the folder(s) didn't + /// exist before, a new folder(s) is created. + /// + /// The folder name can contain: + /// + /// - Alphanumeric Characters: `a-z` , `A-Z` , `0-9` - Special Characters: + /// `/` , `_` , `-` + /// + /// Using multiple `/` creates a nested folder. + /// + public string? Folder + { + get + { + if (!this.BodyProperties.TryGetValue("folder", out JsonElement element)) + return null; + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions); + } + set + { + this.BodyProperties["folder"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + /// + /// Whether to mark the file as private or not. + /// + /// If `true`, the file is marked as private and is accessible only using named + /// transformation or signed URL. + /// + public bool? IsPrivateFile + { + get + { + if (!this.BodyProperties.TryGetValue("isPrivateFile", out JsonElement element)) + return null; + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions); + } + set + { + this.BodyProperties["isPrivateFile"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + /// + /// Whether to upload file as published or not. + /// + /// If `false`, the file is marked as unpublished, which restricts access to the + /// file only via the media library. Files in draft or unpublished state can only + /// be publicly accessed after being published. + /// + /// The option to upload in draft state is only available in custom enterprise + /// pricing plans. + /// + public bool? IsPublished + { + get + { + if (!this.BodyProperties.TryGetValue("isPublished", out JsonElement element)) + return null; + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions); + } + set + { + this.BodyProperties["isPublished"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + /// + /// If set to `true` and a file already exists at the exact location, its AITags + /// will be removed. Set `overwriteAITags` to `false` to preserve AITags. + /// + public bool? OverwriteAITags + { + get + { + if (!this.BodyProperties.TryGetValue("overwriteAITags", out JsonElement element)) + return null; + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions); + } + set + { + this.BodyProperties["overwriteAITags"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + /// + /// If the request does not have `customMetadata`, and a file already exists at + /// the exact location, existing customMetadata will be removed. + /// + public bool? OverwriteCustomMetadata + { + get + { + if ( + !this.BodyProperties.TryGetValue("overwriteCustomMetadata", out JsonElement element) + ) + return null; + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions); + } + set + { + this.BodyProperties["overwriteCustomMetadata"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + /// + /// If `false` and `useUniqueFileName` is also `false`, and a file already exists + /// at the exact location, upload API will return an error immediately. + /// + public bool? OverwriteFile + { + get + { + if (!this.BodyProperties.TryGetValue("overwriteFile", out JsonElement element)) + return null; + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions); + } + set + { + this.BodyProperties["overwriteFile"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + /// + /// If the request does not have `tags`, and a file already exists at the exact + /// location, existing tags will be removed. + /// + public bool? OverwriteTags + { + get + { + if (!this.BodyProperties.TryGetValue("overwriteTags", out JsonElement element)) + return null; + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions); + } + set + { + this.BodyProperties["overwriteTags"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + /// + /// Your ImageKit.io public key. This field is only required for authentication + /// when uploading a file from the client side. + /// + public string? PublicKey + { + get + { + if (!this.BodyProperties.TryGetValue("publicKey", out JsonElement element)) + return null; + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions); + } + set + { + this.BodyProperties["publicKey"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + /// + /// Array of response field keys to include in the API response body. + /// + public List>? ResponseFields + { + get + { + if (!this.BodyProperties.TryGetValue("responseFields", out JsonElement element)) + return null; + + return JsonSerializer.Deserialize + >?>(element, ModelBase.SerializerOptions); + } + set + { + this.BodyProperties["responseFields"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + /// + /// HMAC-SHA1 digest of the token+expire using your ImageKit.io private API key + /// as a key. Learn how to create a signature on the page below. This should be + /// in lowercase. + /// + /// Signature must be calculated on the server-side. This field is only required + /// for authentication when uploading a file from the client side. + /// + public string? Signature + { + get + { + if (!this.BodyProperties.TryGetValue("signature", out JsonElement element)) + return null; + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions); + } + set + { + this.BodyProperties["signature"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + /// + /// Set the tags while uploading the file. Provide an array of tag strings (e.g. + /// `["tag1", "tag2", "tag3"]`). The combined length of all tag characters must + /// not exceed 500, and the `%` character is not allowed. If this field is not + /// specified and the file is overwritten, the existing tags will be removed. + /// + public List? Tags + { + get + { + if (!this.BodyProperties.TryGetValue("tags", out JsonElement element)) + return null; + + return JsonSerializer.Deserialize?>(element, ModelBase.SerializerOptions); + } + set + { + this.BodyProperties["tags"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + /// + /// Configure pre-processing (`pre`) and post-processing (`post`) transformations. + /// + /// - `pre` — applied before the file is uploaded to the Media Library. Useful + /// for reducing file size or applying basic optimizations upfront (e.g., resize, compress). + /// + /// - `post` — applied immediately after upload. Ideal for generating transformed + /// versions (like video encodes or thumbnails) in advance, so they're ready for + /// delivery without delay. + /// + /// You can mix and match any combination of post-processing types. + /// + public FileUploadParamsProperties::Transformation? Transformation + { + get + { + if (!this.BodyProperties.TryGetValue("transformation", out JsonElement element)) + return null; + + return JsonSerializer.Deserialize( + element, + ModelBase.SerializerOptions + ); + } + set + { + this.BodyProperties["transformation"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + /// + /// Whether to use a unique filename for this file or not. + /// + /// If `true`, ImageKit.io will add a unique suffix to the filename parameter + /// to get a unique filename. + /// + /// If `false`, then the image is uploaded with the provided filename parameter, + /// and any existing file with the same name is replaced. + /// + public bool? UseUniqueFileName + { + get + { + if (!this.BodyProperties.TryGetValue("useUniqueFileName", out JsonElement element)) + return null; + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions); + } + set + { + this.BodyProperties["useUniqueFileName"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + /// + /// The final status of extensions after they have completed execution will be + /// delivered to this endpoint as a POST request. [Learn more](/docs/api-reference/digital-asset-management-dam/managing-assets/update-file-details#webhook-payload-structure) + /// about the webhook payload structure. + /// + public string? WebhookURL + { + get + { + if (!this.BodyProperties.TryGetValue("webhookUrl", out JsonElement element)) + return null; + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions); + } + set + { + this.BodyProperties["webhookUrl"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + public override Uri Url(IImageKitClient client) + { + return new UriBuilder(client.BaseUrl.ToString().TrimEnd('/') + "/api/v1/files/upload") + { + Query = this.QueryString(client), + }.Uri; + } + + public StringContent BodyContent() + { + return new( + JsonSerializer.Serialize(this.BodyProperties), + Encoding.UTF8, + "application/json" + ); + } + + public void AddHeadersToRequest(HttpRequestMessage request, IImageKitClient client) + { + ParamsBase.AddDefaultHeaders(request, client); + foreach (var item in this.HeaderProperties) + { + ParamsBase.AddHeaderElementToRequest(request, item.Key, item.Value); + } + } +} diff --git a/src/Imagekit/Models/Files/FileUploadParamsProperties/Extension.cs b/src/Imagekit/Models/Files/FileUploadParamsProperties/Extension.cs new file mode 100644 index 00000000..aca5f9b4 --- /dev/null +++ b/src/Imagekit/Models/Files/FileUploadParamsProperties/Extension.cs @@ -0,0 +1,177 @@ +using System; +using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; +using System.Text.Json; +using System.Text.Json.Serialization; +using Imagekit.Models.Files.FileUploadParamsProperties.ExtensionProperties; +using ExtensionVariants = Imagekit.Models.Files.FileUploadParamsProperties.ExtensionVariants; + +namespace Imagekit.Models.Files.FileUploadParamsProperties; + +[JsonConverter(typeof(ExtensionConverter))] +public abstract record class Extension +{ + internal Extension() { } + + public static implicit operator Extension(RemoveBg value) => + new ExtensionVariants::RemoveBg(value); + + public static implicit operator Extension(AutoTaggingExtension value) => + new ExtensionVariants::AutoTaggingExtension(value); + + public bool TryPickRemoveBg([NotNullWhen(true)] out RemoveBg? value) + { + value = (this as ExtensionVariants::RemoveBg)?.Value; + return value != null; + } + + public bool TryPickAutoTagging([NotNullWhen(true)] out AutoTaggingExtension? value) + { + value = (this as ExtensionVariants::AutoTaggingExtension)?.Value; + return value != null; + } + + public bool TryPickAIAutoDescription([NotNullWhen(true)] out JsonElement? value) + { + value = (this as ExtensionVariants::AIAutoDescription)?.Value; + return value != null; + } + + public void Switch( + Action removeBg, + Action autoTagging, + Action aiAutoDescription + ) + { + switch (this) + { + case ExtensionVariants::RemoveBg inner: + removeBg(inner); + break; + case ExtensionVariants::AutoTaggingExtension inner: + autoTagging(inner); + break; + case ExtensionVariants::AIAutoDescription inner: + aiAutoDescription(inner); + break; + default: + throw new InvalidOperationException(); + } + } + + public T Match( + Func removeBg, + Func autoTagging, + Func aiAutoDescription + ) + { + return this switch + { + ExtensionVariants::RemoveBg inner => removeBg(inner), + ExtensionVariants::AutoTaggingExtension inner => autoTagging(inner), + ExtensionVariants::AIAutoDescription inner => aiAutoDescription(inner), + _ => throw new InvalidOperationException(), + }; + } + + public abstract void Validate(); +} + +sealed class ExtensionConverter : JsonConverter +{ + public override Extension? Read( + ref Utf8JsonReader reader, + Type typeToConvert, + JsonSerializerOptions options + ) + { + var json = JsonSerializer.Deserialize(ref reader, options); + string? name; + try + { + name = json.GetProperty("name").GetString(); + } + catch + { + name = null; + } + + switch (name) + { + case "remove-bg": + { + List exceptions = []; + + try + { + var deserialized = JsonSerializer.Deserialize(json, options); + if (deserialized != null) + { + return new ExtensionVariants::RemoveBg(deserialized); + } + } + catch (JsonException e) + { + exceptions.Add(e); + } + + throw new AggregateException(exceptions); + } + case "ai-auto-description": + { + List exceptions = []; + + try + { + return new ExtensionVariants::AIAutoDescription( + JsonSerializer.Deserialize(json, options) + ); + } + catch (JsonException e) + { + exceptions.Add(e); + } + + throw new AggregateException(exceptions); + } + default: + { + List exceptions = []; + + try + { + var deserialized = JsonSerializer.Deserialize( + json, + options + ); + if (deserialized != null) + { + return new ExtensionVariants::AutoTaggingExtension(deserialized); + } + } + catch (JsonException e) + { + exceptions.Add(e); + } + + throw new AggregateException(exceptions); + } + } + } + + public override void Write( + Utf8JsonWriter writer, + Extension value, + JsonSerializerOptions options + ) + { + object variant = value switch + { + ExtensionVariants::RemoveBg(var removeBg) => removeBg, + ExtensionVariants::AutoTaggingExtension(var autoTagging) => autoTagging, + ExtensionVariants::AIAutoDescription(var aiAutoDescription) => aiAutoDescription, + _ => throw new ArgumentOutOfRangeException(nameof(value)), + }; + JsonSerializer.Serialize(writer, variant, options); + } +} diff --git a/src/Imagekit/Models/Files/FileUploadParamsProperties/ExtensionProperties/AutoTaggingExtension.cs b/src/Imagekit/Models/Files/FileUploadParamsProperties/ExtensionProperties/AutoTaggingExtension.cs new file mode 100644 index 00000000..11eab9ca --- /dev/null +++ b/src/Imagekit/Models/Files/FileUploadParamsProperties/ExtensionProperties/AutoTaggingExtension.cs @@ -0,0 +1,100 @@ +using System; +using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; +using System.Text.Json; +using System.Text.Json.Serialization; +using Imagekit.Models.Files.FileUploadParamsProperties.ExtensionProperties.AutoTaggingExtensionProperties; + +namespace Imagekit.Models.Files.FileUploadParamsProperties.ExtensionProperties; + +[JsonConverter(typeof(ModelConverter))] +public sealed record class AutoTaggingExtension : ModelBase, IFromRaw +{ + /// + /// Maximum number of tags to attach to the asset. + /// + public required long MaxTags + { + get + { + if (!this.Properties.TryGetValue("maxTags", out JsonElement element)) + throw new ArgumentOutOfRangeException("maxTags", "Missing required argument"); + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions); + } + set + { + this.Properties["maxTags"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + /// + /// Minimum confidence level for tags to be considered valid. + /// + public required long MinConfidence + { + get + { + if (!this.Properties.TryGetValue("minConfidence", out JsonElement element)) + throw new ArgumentOutOfRangeException("minConfidence", "Missing required argument"); + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions); + } + set + { + this.Properties["minConfidence"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + /// + /// Specifies the auto-tagging extension used. + /// + public required ApiEnum Name + { + get + { + if (!this.Properties.TryGetValue("name", out JsonElement element)) + throw new ArgumentOutOfRangeException("name", "Missing required argument"); + + return JsonSerializer.Deserialize>( + element, + ModelBase.SerializerOptions + ); + } + set + { + this.Properties["name"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + public override void Validate() + { + _ = this.MaxTags; + _ = this.MinConfidence; + this.Name.Validate(); + } + + public AutoTaggingExtension() { } + +#pragma warning disable CS8618 + [SetsRequiredMembers] + AutoTaggingExtension(Dictionary properties) + { + Properties = properties; + } +#pragma warning restore CS8618 + + public static AutoTaggingExtension FromRawUnchecked(Dictionary properties) + { + return new(properties); + } +} diff --git a/src/Imagekit/Models/Files/FileUploadParamsProperties/ExtensionProperties/AutoTaggingExtensionProperties/Name.cs b/src/Imagekit/Models/Files/FileUploadParamsProperties/ExtensionProperties/AutoTaggingExtensionProperties/Name.cs new file mode 100644 index 00000000..55796f3b --- /dev/null +++ b/src/Imagekit/Models/Files/FileUploadParamsProperties/ExtensionProperties/AutoTaggingExtensionProperties/Name.cs @@ -0,0 +1,46 @@ +using System; +using System.Text.Json; +using System.Text.Json.Serialization; + +namespace Imagekit.Models.Files.FileUploadParamsProperties.ExtensionProperties.AutoTaggingExtensionProperties; + +/// +/// Specifies the auto-tagging extension used. +/// +[JsonConverter(typeof(NameConverter))] +public enum Name +{ + GoogleAutoTagging, + AwsAutoTagging, +} + +sealed class NameConverter : JsonConverter +{ + public override Name Read( + ref Utf8JsonReader reader, + Type typeToConvert, + JsonSerializerOptions options + ) + { + return JsonSerializer.Deserialize(ref reader, options) switch + { + "google-auto-tagging" => Name.GoogleAutoTagging, + "aws-auto-tagging" => Name.AwsAutoTagging, + _ => (Name)(-1), + }; + } + + public override void Write(Utf8JsonWriter writer, Name value, JsonSerializerOptions options) + { + JsonSerializer.Serialize( + writer, + value switch + { + Name.GoogleAutoTagging => "google-auto-tagging", + Name.AwsAutoTagging => "aws-auto-tagging", + _ => throw new ArgumentOutOfRangeException(nameof(value)), + }, + options + ); + } +} diff --git a/src/Imagekit/Models/Files/FileUploadParamsProperties/ExtensionProperties/RemoveBg.cs b/src/Imagekit/Models/Files/FileUploadParamsProperties/ExtensionProperties/RemoveBg.cs new file mode 100644 index 00000000..68223612 --- /dev/null +++ b/src/Imagekit/Models/Files/FileUploadParamsProperties/ExtensionProperties/RemoveBg.cs @@ -0,0 +1,74 @@ +using System; +using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; +using System.Text.Json; +using System.Text.Json.Serialization; +using Imagekit.Models.Files.FileUploadParamsProperties.ExtensionProperties.RemoveBgProperties; + +namespace Imagekit.Models.Files.FileUploadParamsProperties.ExtensionProperties; + +[JsonConverter(typeof(ModelConverter))] +public sealed record class RemoveBg : ModelBase, IFromRaw +{ + /// + /// Specifies the background removal extension. + /// + public JsonElement Name + { + get + { + if (!this.Properties.TryGetValue("name", out JsonElement element)) + throw new ArgumentOutOfRangeException("name", "Missing required argument"); + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions); + } + set + { + this.Properties["name"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + public Options? Options + { + get + { + if (!this.Properties.TryGetValue("options", out JsonElement element)) + return null; + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions); + } + set + { + this.Properties["options"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + public override void Validate() + { + this.Options?.Validate(); + } + + public RemoveBg() + { + this.Name = JsonSerializer.Deserialize("\"remove-bg\""); + } + +#pragma warning disable CS8618 + [SetsRequiredMembers] + RemoveBg(Dictionary properties) + { + Properties = properties; + } +#pragma warning restore CS8618 + + public static RemoveBg FromRawUnchecked(Dictionary properties) + { + return new(properties); + } +} diff --git a/src/Imagekit/Models/Files/FileUploadParamsProperties/ExtensionProperties/RemoveBgProperties/Options.cs b/src/Imagekit/Models/Files/FileUploadParamsProperties/ExtensionProperties/RemoveBgProperties/Options.cs new file mode 100644 index 00000000..7f5799e6 --- /dev/null +++ b/src/Imagekit/Models/Files/FileUploadParamsProperties/ExtensionProperties/RemoveBgProperties/Options.cs @@ -0,0 +1,122 @@ +using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; +using System.Text.Json; +using System.Text.Json.Serialization; + +namespace Imagekit.Models.Files.FileUploadParamsProperties.ExtensionProperties.RemoveBgProperties; + +[JsonConverter(typeof(ModelConverter))] +public sealed record class Options : ModelBase, IFromRaw +{ + /// + /// Whether to add an artificial shadow to the result. Default is false. Note: + /// Adding shadows is currently only supported for car photos. + /// + public bool? AddShadow + { + get + { + if (!this.Properties.TryGetValue("add_shadow", out JsonElement element)) + return null; + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions); + } + set + { + this.Properties["add_shadow"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + /// + /// Specifies a solid color background using hex code (e.g., "81d4fa", "fff") + /// or color name (e.g., "green"). If this parameter is set, `bg_image_url` must + /// be empty. + /// + public string? BgColor + { + get + { + if (!this.Properties.TryGetValue("bg_color", out JsonElement element)) + return null; + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions); + } + set + { + this.Properties["bg_color"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + /// + /// Sets a background image from a URL. If this parameter is set, `bg_color` + /// must be empty. + /// + public string? BgImageURL + { + get + { + if (!this.Properties.TryGetValue("bg_image_url", out JsonElement element)) + return null; + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions); + } + set + { + this.Properties["bg_image_url"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + /// + /// Allows semi-transparent regions in the result. Default is true. Note: Semitransparency + /// is currently only supported for car windows. + /// + public bool? Semitransparency + { + get + { + if (!this.Properties.TryGetValue("semitransparency", out JsonElement element)) + return null; + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions); + } + set + { + this.Properties["semitransparency"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + public override void Validate() + { + _ = this.AddShadow; + _ = this.BgColor; + _ = this.BgImageURL; + _ = this.Semitransparency; + } + + public Options() { } + +#pragma warning disable CS8618 + [SetsRequiredMembers] + Options(Dictionary properties) + { + Properties = properties; + } +#pragma warning restore CS8618 + + public static Options FromRawUnchecked(Dictionary properties) + { + return new(properties); + } +} diff --git a/src/Imagekit/Models/Files/FileUploadParamsProperties/ExtensionVariants/All.cs b/src/Imagekit/Models/Files/FileUploadParamsProperties/ExtensionVariants/All.cs new file mode 100644 index 00000000..b312f63e --- /dev/null +++ b/src/Imagekit/Models/Files/FileUploadParamsProperties/ExtensionVariants/All.cs @@ -0,0 +1,46 @@ +using System.Text.Json; +using ExtensionProperties = Imagekit.Models.Files.FileUploadParamsProperties.ExtensionProperties; + +namespace Imagekit.Models.Files.FileUploadParamsProperties.ExtensionVariants; + +public sealed record class RemoveBg(ExtensionProperties::RemoveBg Value) + : Extension, + IVariant +{ + public static RemoveBg From(ExtensionProperties::RemoveBg value) + { + return new(value); + } + + public override void Validate() + { + this.Value.Validate(); + } +} + +public sealed record class AutoTaggingExtension(ExtensionProperties::AutoTaggingExtension Value) + : Extension, + IVariant +{ + public static AutoTaggingExtension From(ExtensionProperties::AutoTaggingExtension value) + { + return new(value); + } + + public override void Validate() + { + this.Value.Validate(); + } +} + +public sealed record class AIAutoDescription(JsonElement Value) + : Extension, + IVariant +{ + public static AIAutoDescription From(JsonElement value) + { + return new(value); + } + + public override void Validate() { } +} diff --git a/src/Imagekit/Models/Files/FileUploadParamsProperties/ResponseField.cs b/src/Imagekit/Models/Files/FileUploadParamsProperties/ResponseField.cs new file mode 100644 index 00000000..c5b5b8f7 --- /dev/null +++ b/src/Imagekit/Models/Files/FileUploadParamsProperties/ResponseField.cs @@ -0,0 +1,62 @@ +using System; +using System.Text.Json; +using System.Text.Json.Serialization; + +namespace Imagekit.Models.Files.FileUploadParamsProperties; + +[JsonConverter(typeof(ResponseFieldConverter))] +public enum ResponseField +{ + Tags, + CustomCoordinates, + IsPrivateFile, + EmbeddedMetadata, + IsPublished, + CustomMetadata, + Metadata, +} + +sealed class ResponseFieldConverter : JsonConverter +{ + public override ResponseField Read( + ref Utf8JsonReader reader, + Type typeToConvert, + JsonSerializerOptions options + ) + { + return JsonSerializer.Deserialize(ref reader, options) switch + { + "tags" => ResponseField.Tags, + "customCoordinates" => ResponseField.CustomCoordinates, + "isPrivateFile" => ResponseField.IsPrivateFile, + "embeddedMetadata" => ResponseField.EmbeddedMetadata, + "isPublished" => ResponseField.IsPublished, + "customMetadata" => ResponseField.CustomMetadata, + "metadata" => ResponseField.Metadata, + _ => (ResponseField)(-1), + }; + } + + public override void Write( + Utf8JsonWriter writer, + ResponseField value, + JsonSerializerOptions options + ) + { + JsonSerializer.Serialize( + writer, + value switch + { + ResponseField.Tags => "tags", + ResponseField.CustomCoordinates => "customCoordinates", + ResponseField.IsPrivateFile => "isPrivateFile", + ResponseField.EmbeddedMetadata => "embeddedMetadata", + ResponseField.IsPublished => "isPublished", + ResponseField.CustomMetadata => "customMetadata", + ResponseField.Metadata => "metadata", + _ => throw new ArgumentOutOfRangeException(nameof(value)), + }, + options + ); + } +} diff --git a/src/Imagekit/Models/Files/FileUploadParamsProperties/Transformation.cs b/src/Imagekit/Models/Files/FileUploadParamsProperties/Transformation.cs new file mode 100644 index 00000000..e8cdd4c6 --- /dev/null +++ b/src/Imagekit/Models/Files/FileUploadParamsProperties/Transformation.cs @@ -0,0 +1,92 @@ +using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; +using System.Text.Json; +using System.Text.Json.Serialization; +using Imagekit.Models.Files.FileUploadParamsProperties.TransformationProperties; + +namespace Imagekit.Models.Files.FileUploadParamsProperties; + +/// +/// Configure pre-processing (`pre`) and post-processing (`post`) transformations. +/// +/// - `pre` — applied before the file is uploaded to the Media Library. Useful +/// for reducing file size or applying basic optimizations upfront (e.g., resize, compress). +/// +/// - `post` — applied immediately after upload. Ideal for generating transformed +/// versions (like video encodes or thumbnails) in advance, so they're ready for +/// delivery without delay. +/// +/// You can mix and match any combination of post-processing types. +/// +[JsonConverter(typeof(ModelConverter))] +public sealed record class Transformation : ModelBase, IFromRaw +{ + /// + /// List of transformations to apply *after* the file is uploaded. Each item + /// must match one of the following types: `transformation`, `gif-to-video`, + /// `thumbnail`, `abs`. + /// + public List? Post + { + get + { + if (!this.Properties.TryGetValue("post", out JsonElement element)) + return null; + + return JsonSerializer.Deserialize?>(element, ModelBase.SerializerOptions); + } + set + { + this.Properties["post"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + /// + /// Transformation string to apply before uploading the file to the Media Library. + /// Useful for optimizing files at ingestion. + /// + public string? Pre + { + get + { + if (!this.Properties.TryGetValue("pre", out JsonElement element)) + return null; + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions); + } + set + { + this.Properties["pre"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + public override void Validate() + { + foreach (var item in this.Post ?? []) + { + item.Validate(); + } + _ = this.Pre; + } + + public Transformation() { } + +#pragma warning disable CS8618 + [SetsRequiredMembers] + Transformation(Dictionary properties) + { + Properties = properties; + } +#pragma warning restore CS8618 + + public static Transformation FromRawUnchecked(Dictionary properties) + { + return new(properties); + } +} diff --git a/src/Imagekit/Models/Files/FileUploadParamsProperties/TransformationProperties/Post.cs b/src/Imagekit/Models/Files/FileUploadParamsProperties/TransformationProperties/Post.cs new file mode 100644 index 00000000..9f7a1ec3 --- /dev/null +++ b/src/Imagekit/Models/Files/FileUploadParamsProperties/TransformationProperties/Post.cs @@ -0,0 +1,225 @@ +using System; +using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; +using System.Text.Json; +using System.Text.Json.Serialization; +using PostProperties = Imagekit.Models.Files.FileUploadParamsProperties.TransformationProperties.PostProperties; +using PostVariants = Imagekit.Models.Files.FileUploadParamsProperties.TransformationProperties.PostVariants; + +namespace Imagekit.Models.Files.FileUploadParamsProperties.TransformationProperties; + +[JsonConverter(typeof(PostConverter))] +public abstract record class Post +{ + internal Post() { } + + public static implicit operator Post(PostProperties::Transformation value) => + new PostVariants::Transformation(value); + + public static implicit operator Post(PostProperties::GifToVideo value) => + new PostVariants::GifToVideo(value); + + public static implicit operator Post(PostProperties::Thumbnail value) => + new PostVariants::Thumbnail(value); + + public static implicit operator Post(PostProperties::Abs value) => new PostVariants::Abs(value); + + public bool TryPickTransformation([NotNullWhen(true)] out PostProperties::Transformation? value) + { + value = (this as PostVariants::Transformation)?.Value; + return value != null; + } + + public bool TryPickGifToVideo([NotNullWhen(true)] out PostProperties::GifToVideo? value) + { + value = (this as PostVariants::GifToVideo)?.Value; + return value != null; + } + + public bool TryPickThumbnail([NotNullWhen(true)] out PostProperties::Thumbnail? value) + { + value = (this as PostVariants::Thumbnail)?.Value; + return value != null; + } + + public bool TryPickAbs([NotNullWhen(true)] out PostProperties::Abs? value) + { + value = (this as PostVariants::Abs)?.Value; + return value != null; + } + + public void Switch( + Action transformation, + Action gifToVideo, + Action thumbnail, + Action abs + ) + { + switch (this) + { + case PostVariants::Transformation inner: + transformation(inner); + break; + case PostVariants::GifToVideo inner: + gifToVideo(inner); + break; + case PostVariants::Thumbnail inner: + thumbnail(inner); + break; + case PostVariants::Abs inner: + abs(inner); + break; + default: + throw new InvalidOperationException(); + } + } + + public T Match( + Func transformation, + Func gifToVideo, + Func thumbnail, + Func abs + ) + { + return this switch + { + PostVariants::Transformation inner => transformation(inner), + PostVariants::GifToVideo inner => gifToVideo(inner), + PostVariants::Thumbnail inner => thumbnail(inner), + PostVariants::Abs inner => abs(inner), + _ => throw new InvalidOperationException(), + }; + } + + public abstract void Validate(); +} + +sealed class PostConverter : JsonConverter +{ + public override Post? Read( + ref Utf8JsonReader reader, + Type typeToConvert, + JsonSerializerOptions options + ) + { + var json = JsonSerializer.Deserialize(ref reader, options); + string? type; + try + { + type = json.GetProperty("type").GetString(); + } + catch + { + type = null; + } + + switch (type) + { + case "transformation": + { + List exceptions = []; + + try + { + var deserialized = JsonSerializer.Deserialize( + json, + options + ); + if (deserialized != null) + { + return new PostVariants::Transformation(deserialized); + } + } + catch (JsonException e) + { + exceptions.Add(e); + } + + throw new AggregateException(exceptions); + } + case "gif-to-video": + { + List exceptions = []; + + try + { + var deserialized = JsonSerializer.Deserialize( + json, + options + ); + if (deserialized != null) + { + return new PostVariants::GifToVideo(deserialized); + } + } + catch (JsonException e) + { + exceptions.Add(e); + } + + throw new AggregateException(exceptions); + } + case "thumbnail": + { + List exceptions = []; + + try + { + var deserialized = JsonSerializer.Deserialize( + json, + options + ); + if (deserialized != null) + { + return new PostVariants::Thumbnail(deserialized); + } + } + catch (JsonException e) + { + exceptions.Add(e); + } + + throw new AggregateException(exceptions); + } + case "abs": + { + List exceptions = []; + + try + { + var deserialized = JsonSerializer.Deserialize( + json, + options + ); + if (deserialized != null) + { + return new PostVariants::Abs(deserialized); + } + } + catch (JsonException e) + { + exceptions.Add(e); + } + + throw new AggregateException(exceptions); + } + default: + { + throw new Exception(); + } + } + } + + public override void Write(Utf8JsonWriter writer, Post value, JsonSerializerOptions options) + { + object variant = value switch + { + PostVariants::Transformation(var transformation) => transformation, + PostVariants::GifToVideo(var gifToVideo) => gifToVideo, + PostVariants::Thumbnail(var thumbnail) => thumbnail, + PostVariants::Abs(var abs) => abs, + _ => throw new ArgumentOutOfRangeException(nameof(value)), + }; + JsonSerializer.Serialize(writer, variant, options); + } +} diff --git a/src/Imagekit/Models/Files/FileUploadParamsProperties/TransformationProperties/PostProperties/Abs.cs b/src/Imagekit/Models/Files/FileUploadParamsProperties/TransformationProperties/PostProperties/Abs.cs new file mode 100644 index 00000000..10c95b3c --- /dev/null +++ b/src/Imagekit/Models/Files/FileUploadParamsProperties/TransformationProperties/PostProperties/Abs.cs @@ -0,0 +1,103 @@ +using System; +using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; +using System.Text.Json; +using System.Text.Json.Serialization; +using Imagekit.Models.Files.FileUploadParamsProperties.TransformationProperties.PostProperties.AbsProperties; + +namespace Imagekit.Models.Files.FileUploadParamsProperties.TransformationProperties.PostProperties; + +[JsonConverter(typeof(ModelConverter))] +public sealed record class Abs : ModelBase, IFromRaw +{ + /// + /// Streaming protocol to use (`hls` or `dash`). + /// + public required ApiEnum Protocol + { + get + { + if (!this.Properties.TryGetValue("protocol", out JsonElement element)) + throw new ArgumentOutOfRangeException("protocol", "Missing required argument"); + + return JsonSerializer.Deserialize>( + element, + ModelBase.SerializerOptions + ); + } + set + { + this.Properties["protocol"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + /// + /// Adaptive Bitrate Streaming (ABS) setup. + /// + public JsonElement Type + { + get + { + if (!this.Properties.TryGetValue("type", out JsonElement element)) + throw new ArgumentOutOfRangeException("type", "Missing required argument"); + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions); + } + set + { + this.Properties["type"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + /// + /// List of different representations you want to create separated by an underscore. + /// + public required string Value + { + get + { + if (!this.Properties.TryGetValue("value", out JsonElement element)) + throw new ArgumentOutOfRangeException("value", "Missing required argument"); + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions) + ?? throw new ArgumentNullException("value"); + } + set + { + this.Properties["value"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + public override void Validate() + { + this.Protocol.Validate(); + _ = this.Value; + } + + public Abs() + { + this.Type = JsonSerializer.Deserialize("\"abs\""); + } + +#pragma warning disable CS8618 + [SetsRequiredMembers] + Abs(Dictionary properties) + { + Properties = properties; + } +#pragma warning restore CS8618 + + public static Abs FromRawUnchecked(Dictionary properties) + { + return new(properties); + } +} diff --git a/src/Imagekit/Models/Files/FileUploadParamsProperties/TransformationProperties/PostProperties/AbsProperties/Protocol.cs b/src/Imagekit/Models/Files/FileUploadParamsProperties/TransformationProperties/PostProperties/AbsProperties/Protocol.cs new file mode 100644 index 00000000..56d80f9f --- /dev/null +++ b/src/Imagekit/Models/Files/FileUploadParamsProperties/TransformationProperties/PostProperties/AbsProperties/Protocol.cs @@ -0,0 +1,46 @@ +using System; +using System.Text.Json; +using System.Text.Json.Serialization; + +namespace Imagekit.Models.Files.FileUploadParamsProperties.TransformationProperties.PostProperties.AbsProperties; + +/// +/// Streaming protocol to use (`hls` or `dash`). +/// +[JsonConverter(typeof(ProtocolConverter))] +public enum Protocol +{ + Hls, + Dash, +} + +sealed class ProtocolConverter : JsonConverter +{ + public override Protocol Read( + ref Utf8JsonReader reader, + Type typeToConvert, + JsonSerializerOptions options + ) + { + return JsonSerializer.Deserialize(ref reader, options) switch + { + "hls" => Protocol.Hls, + "dash" => Protocol.Dash, + _ => (Protocol)(-1), + }; + } + + public override void Write(Utf8JsonWriter writer, Protocol value, JsonSerializerOptions options) + { + JsonSerializer.Serialize( + writer, + value switch + { + Protocol.Hls => "hls", + Protocol.Dash => "dash", + _ => throw new ArgumentOutOfRangeException(nameof(value)), + }, + options + ); + } +} diff --git a/src/Imagekit/Models/Files/FileUploadParamsProperties/TransformationProperties/PostProperties/GifToVideo.cs b/src/Imagekit/Models/Files/FileUploadParamsProperties/TransformationProperties/PostProperties/GifToVideo.cs new file mode 100644 index 00000000..44e57f2a --- /dev/null +++ b/src/Imagekit/Models/Files/FileUploadParamsProperties/TransformationProperties/PostProperties/GifToVideo.cs @@ -0,0 +1,77 @@ +using System; +using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; +using System.Text.Json; +using System.Text.Json.Serialization; + +namespace Imagekit.Models.Files.FileUploadParamsProperties.TransformationProperties.PostProperties; + +[JsonConverter(typeof(ModelConverter))] +public sealed record class GifToVideo : ModelBase, IFromRaw +{ + /// + /// Converts an animated GIF into an MP4. + /// + public JsonElement Type + { + get + { + if (!this.Properties.TryGetValue("type", out JsonElement element)) + throw new ArgumentOutOfRangeException("type", "Missing required argument"); + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions); + } + set + { + this.Properties["type"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + /// + /// Optional transformation string to apply to the output video. **Example**: + /// `q-80` + /// + public string? Value + { + get + { + if (!this.Properties.TryGetValue("value", out JsonElement element)) + return null; + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions); + } + set + { + this.Properties["value"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + public override void Validate() + { + _ = this.Value; + } + + public GifToVideo() + { + this.Type = JsonSerializer.Deserialize("\"gif-to-video\""); + } + +#pragma warning disable CS8618 + [SetsRequiredMembers] + GifToVideo(Dictionary properties) + { + Properties = properties; + } +#pragma warning restore CS8618 + + public static GifToVideo FromRawUnchecked(Dictionary properties) + { + return new(properties); + } +} diff --git a/src/Imagekit/Models/Files/FileUploadParamsProperties/TransformationProperties/PostProperties/Thumbnail.cs b/src/Imagekit/Models/Files/FileUploadParamsProperties/TransformationProperties/PostProperties/Thumbnail.cs new file mode 100644 index 00000000..879f27c1 --- /dev/null +++ b/src/Imagekit/Models/Files/FileUploadParamsProperties/TransformationProperties/PostProperties/Thumbnail.cs @@ -0,0 +1,76 @@ +using System; +using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; +using System.Text.Json; +using System.Text.Json.Serialization; + +namespace Imagekit.Models.Files.FileUploadParamsProperties.TransformationProperties.PostProperties; + +[JsonConverter(typeof(ModelConverter))] +public sealed record class Thumbnail : ModelBase, IFromRaw +{ + /// + /// Generates a thumbnail image. + /// + public JsonElement Type + { + get + { + if (!this.Properties.TryGetValue("type", out JsonElement element)) + throw new ArgumentOutOfRangeException("type", "Missing required argument"); + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions); + } + set + { + this.Properties["type"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + /// + /// Optional transformation string. **Example**: `w-150,h-150` + /// + public string? Value + { + get + { + if (!this.Properties.TryGetValue("value", out JsonElement element)) + return null; + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions); + } + set + { + this.Properties["value"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + public override void Validate() + { + _ = this.Value; + } + + public Thumbnail() + { + this.Type = JsonSerializer.Deserialize("\"thumbnail\""); + } + +#pragma warning disable CS8618 + [SetsRequiredMembers] + Thumbnail(Dictionary properties) + { + Properties = properties; + } +#pragma warning restore CS8618 + + public static Thumbnail FromRawUnchecked(Dictionary properties) + { + return new(properties); + } +} diff --git a/src/Imagekit/Models/Files/FileUploadParamsProperties/TransformationProperties/PostProperties/Transformation.cs b/src/Imagekit/Models/Files/FileUploadParamsProperties/TransformationProperties/PostProperties/Transformation.cs new file mode 100644 index 00000000..b68c748b --- /dev/null +++ b/src/Imagekit/Models/Files/FileUploadParamsProperties/TransformationProperties/PostProperties/Transformation.cs @@ -0,0 +1,85 @@ +using System; +using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; +using System.Text.Json; +using System.Text.Json.Serialization; + +namespace Imagekit.Models.Files.FileUploadParamsProperties.TransformationProperties.PostProperties; + +[JsonConverter(typeof(ModelConverter))] +public sealed record class Transformation : ModelBase, IFromRaw +{ + /// + /// Transformation type. + /// + public JsonElement Type + { + get + { + if (!this.Properties.TryGetValue("type", out JsonElement element)) + throw new ArgumentOutOfRangeException("type", "Missing required argument"); + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions); + } + set + { + this.Properties["type"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + /// + /// Transformation string (e.g. `w-200,h-200`). Same syntax as ImageKit URL-based + /// transformations. + /// + public required string Value + { + get + { + if (!this.Properties.TryGetValue("value", out JsonElement element)) + throw new ArgumentOutOfRangeException("value", "Missing required argument"); + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions) + ?? throw new ArgumentNullException("value"); + } + set + { + this.Properties["value"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + public override void Validate() + { + _ = this.Value; + } + + public Transformation() + { + this.Type = JsonSerializer.Deserialize("\"transformation\""); + } + +#pragma warning disable CS8618 + [SetsRequiredMembers] + Transformation(Dictionary properties) + { + Properties = properties; + } +#pragma warning restore CS8618 + + public static Transformation FromRawUnchecked(Dictionary properties) + { + return new(properties); + } + + [SetsRequiredMembers] + public Transformation(string value) + : this() + { + this.Value = value; + } +} diff --git a/src/Imagekit/Models/Files/FileUploadParamsProperties/TransformationProperties/PostVariants/All.cs b/src/Imagekit/Models/Files/FileUploadParamsProperties/TransformationProperties/PostVariants/All.cs new file mode 100644 index 00000000..ae864596 --- /dev/null +++ b/src/Imagekit/Models/Files/FileUploadParamsProperties/TransformationProperties/PostVariants/All.cs @@ -0,0 +1,61 @@ +using PostProperties = Imagekit.Models.Files.FileUploadParamsProperties.TransformationProperties.PostProperties; + +namespace Imagekit.Models.Files.FileUploadParamsProperties.TransformationProperties.PostVariants; + +public sealed record class Transformation(PostProperties::Transformation Value) + : Post, + IVariant +{ + public static Transformation From(PostProperties::Transformation value) + { + return new(value); + } + + public override void Validate() + { + this.Value.Validate(); + } +} + +public sealed record class GifToVideo(PostProperties::GifToVideo Value) + : Post, + IVariant +{ + public static GifToVideo From(PostProperties::GifToVideo value) + { + return new(value); + } + + public override void Validate() + { + this.Value.Validate(); + } +} + +public sealed record class Thumbnail(PostProperties::Thumbnail Value) + : Post, + IVariant +{ + public static Thumbnail From(PostProperties::Thumbnail value) + { + return new(value); + } + + public override void Validate() + { + this.Value.Validate(); + } +} + +public sealed record class Abs(PostProperties::Abs Value) : Post, IVariant +{ + public static Abs From(PostProperties::Abs value) + { + return new(value); + } + + public override void Validate() + { + this.Value.Validate(); + } +} diff --git a/src/Imagekit/Models/Files/FileUploadResponse.cs b/src/Imagekit/Models/Files/FileUploadResponse.cs new file mode 100644 index 00000000..1321dab1 --- /dev/null +++ b/src/Imagekit/Models/Files/FileUploadResponse.cs @@ -0,0 +1,612 @@ +using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; +using System.Text.Json; +using System.Text.Json.Serialization; +using Imagekit.Models.Files.FileUploadResponseProperties; + +namespace Imagekit.Models.Files; + +/// +/// Object containing details of a successful upload. +/// +[JsonConverter(typeof(ModelConverter))] +public sealed record class FileUploadResponse : ModelBase, IFromRaw +{ + /// + /// An array of tags assigned to the uploaded file by auto tagging. + /// + public List? AITags + { + get + { + if (!this.Properties.TryGetValue("AITags", out JsonElement element)) + return null; + + return JsonSerializer.Deserialize?>(element, ModelBase.SerializerOptions); + } + set + { + this.Properties["AITags"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + /// + /// The audio codec used in the video (only for video). + /// + public string? AudioCodec + { + get + { + if (!this.Properties.TryGetValue("audioCodec", out JsonElement element)) + return null; + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions); + } + set + { + this.Properties["audioCodec"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + /// + /// The bit rate of the video in kbps (only for video). + /// + public long? BitRate + { + get + { + if (!this.Properties.TryGetValue("bitRate", out JsonElement element)) + return null; + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions); + } + set + { + this.Properties["bitRate"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + /// + /// Value of custom coordinates associated with the image in the format `x,y,width,height`. + /// If `customCoordinates` are not defined, then it is `null`. Send `customCoordinates` + /// in `responseFields` in API request to get the value of this field. + /// + public string? CustomCoordinates + { + get + { + if (!this.Properties.TryGetValue("customCoordinates", out JsonElement element)) + return null; + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions); + } + set + { + this.Properties["customCoordinates"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + /// + /// A key-value data associated with the asset. Use `responseField` in API request + /// to get `customMetadata` in the upload API response. Before setting any custom + /// metadata on an asset, you have to create the field using custom metadata + /// fields API. Send `customMetadata` in `responseFields` in API request to get + /// the value of this field. + /// + public Dictionary? CustomMetadata + { + get + { + if (!this.Properties.TryGetValue("customMetadata", out JsonElement element)) + return null; + + return JsonSerializer.Deserialize?>( + element, + ModelBase.SerializerOptions + ); + } + set + { + this.Properties["customMetadata"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + /// + /// Optional text to describe the contents of the file. Can be set by the user + /// or the ai-auto-description extension. + /// + public string? Description + { + get + { + if (!this.Properties.TryGetValue("description", out JsonElement element)) + return null; + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions); + } + set + { + this.Properties["description"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + /// + /// The duration of the video in seconds (only for video). + /// + public long? Duration + { + get + { + if (!this.Properties.TryGetValue("duration", out JsonElement element)) + return null; + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions); + } + set + { + this.Properties["duration"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + /// + /// Consolidated embedded metadata associated with the file. It includes exif, + /// iptc, and xmp data. Send `embeddedMetadata` in `responseFields` in API request + /// to get embeddedMetadata in the upload API response. + /// + public Dictionary? EmbeddedMetadata + { + get + { + if (!this.Properties.TryGetValue("embeddedMetadata", out JsonElement element)) + return null; + + return JsonSerializer.Deserialize?>( + element, + ModelBase.SerializerOptions + ); + } + set + { + this.Properties["embeddedMetadata"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + /// + /// Extension names with their processing status at the time of completion of + /// the request. It could have one of the following status values: + /// + /// `success`: The extension has been successfully applied. `failed`: The extension + /// has failed and will not be retried. `pending`: The extension will finish processing + /// in some time. On completion, the final status (success / failed) will be sent + /// to the `webhookUrl` provided. + /// + /// If no extension was requested, then this parameter is not returned. + /// + public ExtensionStatus? ExtensionStatus + { + get + { + if (!this.Properties.TryGetValue("extensionStatus", out JsonElement element)) + return null; + + return JsonSerializer.Deserialize( + element, + ModelBase.SerializerOptions + ); + } + set + { + this.Properties["extensionStatus"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + /// + /// Unique fileId. Store this fileld in your database, as this will be used to + /// perform update action on this file. + /// + public string? FileID + { + get + { + if (!this.Properties.TryGetValue("fileId", out JsonElement element)) + return null; + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions); + } + set + { + this.Properties["fileId"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + /// + /// The relative path of the file in the media library e.g. `/marketing-assets/new-banner.jpg`. + /// + public string? FilePath + { + get + { + if (!this.Properties.TryGetValue("filePath", out JsonElement element)) + return null; + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions); + } + set + { + this.Properties["filePath"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + /// + /// Type of the uploaded file. Possible values are `image`, `non-image`. + /// + public string? FileType + { + get + { + if (!this.Properties.TryGetValue("fileType", out JsonElement element)) + return null; + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions); + } + set + { + this.Properties["fileType"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + /// + /// Height of the image in pixels (Only for images) + /// + public double? Height + { + get + { + if (!this.Properties.TryGetValue("height", out JsonElement element)) + return null; + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions); + } + set + { + this.Properties["height"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + /// + /// Is the file marked as private. It can be either `true` or `false`. Send `isPrivateFile` + /// in `responseFields` in API request to get the value of this field. + /// + public bool? IsPrivateFile + { + get + { + if (!this.Properties.TryGetValue("isPrivateFile", out JsonElement element)) + return null; + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions); + } + set + { + this.Properties["isPrivateFile"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + /// + /// Is the file published or in draft state. It can be either `true` or `false`. + /// Send `isPublished` in `responseFields` in API request to get the value of + /// this field. + /// + public bool? IsPublished + { + get + { + if (!this.Properties.TryGetValue("isPublished", out JsonElement element)) + return null; + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions); + } + set + { + this.Properties["isPublished"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + /// + /// Legacy metadata. Send `metadata` in `responseFields` in API request to get + /// metadata in the upload API response. + /// + public Metadata? Metadata + { + get + { + if (!this.Properties.TryGetValue("metadata", out JsonElement element)) + return null; + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions); + } + set + { + this.Properties["metadata"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + /// + /// Name of the asset. + /// + public string? Name + { + get + { + if (!this.Properties.TryGetValue("name", out JsonElement element)) + return null; + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions); + } + set + { + this.Properties["name"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + /// + /// Size of the image file in Bytes. + /// + public double? Size + { + get + { + if (!this.Properties.TryGetValue("size", out JsonElement element)) + return null; + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions); + } + set + { + this.Properties["size"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + /// + /// The array of tags associated with the asset. If no tags are set, it will + /// be `null`. Send `tags` in `responseFields` in API request to get the value + /// of this field. + /// + public List? Tags + { + get + { + if (!this.Properties.TryGetValue("tags", out JsonElement element)) + return null; + + return JsonSerializer.Deserialize?>(element, ModelBase.SerializerOptions); + } + set + { + this.Properties["tags"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + /// + /// In the case of an image, a small thumbnail URL. + /// + public string? ThumbnailURL + { + get + { + if (!this.Properties.TryGetValue("thumbnailUrl", out JsonElement element)) + return null; + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions); + } + set + { + this.Properties["thumbnailUrl"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + /// + /// A publicly accessible URL of the file. + /// + public string? URL + { + get + { + if (!this.Properties.TryGetValue("url", out JsonElement element)) + return null; + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions); + } + set + { + this.Properties["url"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + /// + /// An object containing the file or file version's `id` (versionId) and `name`. + /// + public VersionInfo? VersionInfo + { + get + { + if (!this.Properties.TryGetValue("versionInfo", out JsonElement element)) + return null; + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions); + } + set + { + this.Properties["versionInfo"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + /// + /// The video codec used in the video (only for video). + /// + public string? VideoCodec + { + get + { + if (!this.Properties.TryGetValue("videoCodec", out JsonElement element)) + return null; + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions); + } + set + { + this.Properties["videoCodec"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + /// + /// Width of the image in pixels (Only for Images) + /// + public double? Width + { + get + { + if (!this.Properties.TryGetValue("width", out JsonElement element)) + return null; + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions); + } + set + { + this.Properties["width"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + public override void Validate() + { + foreach (var item in this.AITags ?? []) + { + item.Validate(); + } + _ = this.AudioCodec; + _ = this.BitRate; + _ = this.CustomCoordinates; + if (this.CustomMetadata != null) + { + foreach (var item in this.CustomMetadata.Values) + { + _ = item; + } + } + _ = this.Description; + _ = this.Duration; + if (this.EmbeddedMetadata != null) + { + foreach (var item in this.EmbeddedMetadata.Values) + { + _ = item; + } + } + this.ExtensionStatus?.Validate(); + _ = this.FileID; + _ = this.FilePath; + _ = this.FileType; + _ = this.Height; + _ = this.IsPrivateFile; + _ = this.IsPublished; + this.Metadata?.Validate(); + _ = this.Name; + _ = this.Size; + foreach (var item in this.Tags ?? []) + { + _ = item; + } + _ = this.ThumbnailURL; + _ = this.URL; + this.VersionInfo?.Validate(); + _ = this.VideoCodec; + _ = this.Width; + } + + public FileUploadResponse() { } + +#pragma warning disable CS8618 + [SetsRequiredMembers] + FileUploadResponse(Dictionary properties) + { + Properties = properties; + } +#pragma warning restore CS8618 + + public static FileUploadResponse FromRawUnchecked(Dictionary properties) + { + return new(properties); + } +} diff --git a/src/Imagekit/Models/Files/FileUploadResponseProperties/AITag.cs b/src/Imagekit/Models/Files/FileUploadResponseProperties/AITag.cs new file mode 100644 index 00000000..bbe9e966 --- /dev/null +++ b/src/Imagekit/Models/Files/FileUploadResponseProperties/AITag.cs @@ -0,0 +1,96 @@ +using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; +using System.Text.Json; +using System.Text.Json.Serialization; + +namespace Imagekit.Models.Files.FileUploadResponseProperties; + +[JsonConverter(typeof(ModelConverter))] +public sealed record class AITag : ModelBase, IFromRaw +{ + /// + /// Confidence score of the tag. + /// + public double? Confidence + { + get + { + if (!this.Properties.TryGetValue("confidence", out JsonElement element)) + return null; + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions); + } + set + { + this.Properties["confidence"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + /// + /// Name of the tag. + /// + public string? Name + { + get + { + if (!this.Properties.TryGetValue("name", out JsonElement element)) + return null; + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions); + } + set + { + this.Properties["name"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + /// + /// Array of `AITags` associated with the image. If no `AITags` are set, it will + /// be null. These tags can be added using the `google-auto-tagging` or `aws-auto-tagging` extensions. + /// + public string? Source + { + get + { + if (!this.Properties.TryGetValue("source", out JsonElement element)) + return null; + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions); + } + set + { + this.Properties["source"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + public override void Validate() + { + _ = this.Confidence; + _ = this.Name; + _ = this.Source; + } + + public AITag() { } + +#pragma warning disable CS8618 + [SetsRequiredMembers] + AITag(Dictionary properties) + { + Properties = properties; + } +#pragma warning restore CS8618 + + public static AITag FromRawUnchecked(Dictionary properties) + { + return new(properties); + } +} diff --git a/src/Imagekit/Models/Files/FileUploadResponseProperties/ExtensionStatus.cs b/src/Imagekit/Models/Files/FileUploadResponseProperties/ExtensionStatus.cs new file mode 100644 index 00000000..a742a8b7 --- /dev/null +++ b/src/Imagekit/Models/Files/FileUploadResponseProperties/ExtensionStatus.cs @@ -0,0 +1,129 @@ +using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; +using System.Text.Json; +using System.Text.Json.Serialization; +using Imagekit.Models.Files.FileUploadResponseProperties.ExtensionStatusProperties; + +namespace Imagekit.Models.Files.FileUploadResponseProperties; + +/// +/// Extension names with their processing status at the time of completion of the +/// request. It could have one of the following status values: +/// +/// `success`: The extension has been successfully applied. `failed`: The extension +/// has failed and will not be retried. `pending`: The extension will finish processing +/// in some time. On completion, the final status (success / failed) will be sent +/// to the `webhookUrl` provided. +/// +/// If no extension was requested, then this parameter is not returned. +/// +[JsonConverter(typeof(ModelConverter))] +public sealed record class ExtensionStatus : ModelBase, IFromRaw +{ + public ApiEnum? AIAutoDescription + { + get + { + if (!this.Properties.TryGetValue("ai-auto-description", out JsonElement element)) + return null; + + return JsonSerializer.Deserialize?>( + element, + ModelBase.SerializerOptions + ); + } + set + { + this.Properties["ai-auto-description"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + public ApiEnum? AwsAutoTagging + { + get + { + if (!this.Properties.TryGetValue("aws-auto-tagging", out JsonElement element)) + return null; + + return JsonSerializer.Deserialize?>( + element, + ModelBase.SerializerOptions + ); + } + set + { + this.Properties["aws-auto-tagging"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + public ApiEnum? GoogleAutoTagging + { + get + { + if (!this.Properties.TryGetValue("google-auto-tagging", out JsonElement element)) + return null; + + return JsonSerializer.Deserialize?>( + element, + ModelBase.SerializerOptions + ); + } + set + { + this.Properties["google-auto-tagging"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + public ApiEnum? RemoveBg + { + get + { + if (!this.Properties.TryGetValue("remove-bg", out JsonElement element)) + return null; + + return JsonSerializer.Deserialize?>( + element, + ModelBase.SerializerOptions + ); + } + set + { + this.Properties["remove-bg"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + public override void Validate() + { + this.AIAutoDescription?.Validate(); + this.AwsAutoTagging?.Validate(); + this.GoogleAutoTagging?.Validate(); + this.RemoveBg?.Validate(); + } + + public ExtensionStatus() { } + +#pragma warning disable CS8618 + [SetsRequiredMembers] + ExtensionStatus(Dictionary properties) + { + Properties = properties; + } +#pragma warning restore CS8618 + + public static ExtensionStatus FromRawUnchecked(Dictionary properties) + { + return new(properties); + } +} diff --git a/src/Imagekit/Models/Files/FileUploadResponseProperties/ExtensionStatusProperties/AIAutoDescription.cs b/src/Imagekit/Models/Files/FileUploadResponseProperties/ExtensionStatusProperties/AIAutoDescription.cs new file mode 100644 index 00000000..6a9e6728 --- /dev/null +++ b/src/Imagekit/Models/Files/FileUploadResponseProperties/ExtensionStatusProperties/AIAutoDescription.cs @@ -0,0 +1,50 @@ +using System; +using System.Text.Json; +using System.Text.Json.Serialization; + +namespace Imagekit.Models.Files.FileUploadResponseProperties.ExtensionStatusProperties; + +[JsonConverter(typeof(AIAutoDescriptionConverter))] +public enum AIAutoDescription +{ + Success, + Pending, + Failed, +} + +sealed class AIAutoDescriptionConverter : JsonConverter +{ + public override AIAutoDescription Read( + ref Utf8JsonReader reader, + Type typeToConvert, + JsonSerializerOptions options + ) + { + return JsonSerializer.Deserialize(ref reader, options) switch + { + "success" => AIAutoDescription.Success, + "pending" => AIAutoDescription.Pending, + "failed" => AIAutoDescription.Failed, + _ => (AIAutoDescription)(-1), + }; + } + + public override void Write( + Utf8JsonWriter writer, + AIAutoDescription value, + JsonSerializerOptions options + ) + { + JsonSerializer.Serialize( + writer, + value switch + { + AIAutoDescription.Success => "success", + AIAutoDescription.Pending => "pending", + AIAutoDescription.Failed => "failed", + _ => throw new ArgumentOutOfRangeException(nameof(value)), + }, + options + ); + } +} diff --git a/src/Imagekit/Models/Files/FileUploadResponseProperties/ExtensionStatusProperties/AwsAutoTagging.cs b/src/Imagekit/Models/Files/FileUploadResponseProperties/ExtensionStatusProperties/AwsAutoTagging.cs new file mode 100644 index 00000000..b1faf17d --- /dev/null +++ b/src/Imagekit/Models/Files/FileUploadResponseProperties/ExtensionStatusProperties/AwsAutoTagging.cs @@ -0,0 +1,50 @@ +using System; +using System.Text.Json; +using System.Text.Json.Serialization; + +namespace Imagekit.Models.Files.FileUploadResponseProperties.ExtensionStatusProperties; + +[JsonConverter(typeof(AwsAutoTaggingConverter))] +public enum AwsAutoTagging +{ + Success, + Pending, + Failed, +} + +sealed class AwsAutoTaggingConverter : JsonConverter +{ + public override AwsAutoTagging Read( + ref Utf8JsonReader reader, + Type typeToConvert, + JsonSerializerOptions options + ) + { + return JsonSerializer.Deserialize(ref reader, options) switch + { + "success" => AwsAutoTagging.Success, + "pending" => AwsAutoTagging.Pending, + "failed" => AwsAutoTagging.Failed, + _ => (AwsAutoTagging)(-1), + }; + } + + public override void Write( + Utf8JsonWriter writer, + AwsAutoTagging value, + JsonSerializerOptions options + ) + { + JsonSerializer.Serialize( + writer, + value switch + { + AwsAutoTagging.Success => "success", + AwsAutoTagging.Pending => "pending", + AwsAutoTagging.Failed => "failed", + _ => throw new ArgumentOutOfRangeException(nameof(value)), + }, + options + ); + } +} diff --git a/src/Imagekit/Models/Files/FileUploadResponseProperties/ExtensionStatusProperties/GoogleAutoTagging.cs b/src/Imagekit/Models/Files/FileUploadResponseProperties/ExtensionStatusProperties/GoogleAutoTagging.cs new file mode 100644 index 00000000..3de49b9f --- /dev/null +++ b/src/Imagekit/Models/Files/FileUploadResponseProperties/ExtensionStatusProperties/GoogleAutoTagging.cs @@ -0,0 +1,50 @@ +using System; +using System.Text.Json; +using System.Text.Json.Serialization; + +namespace Imagekit.Models.Files.FileUploadResponseProperties.ExtensionStatusProperties; + +[JsonConverter(typeof(GoogleAutoTaggingConverter))] +public enum GoogleAutoTagging +{ + Success, + Pending, + Failed, +} + +sealed class GoogleAutoTaggingConverter : JsonConverter +{ + public override GoogleAutoTagging Read( + ref Utf8JsonReader reader, + Type typeToConvert, + JsonSerializerOptions options + ) + { + return JsonSerializer.Deserialize(ref reader, options) switch + { + "success" => GoogleAutoTagging.Success, + "pending" => GoogleAutoTagging.Pending, + "failed" => GoogleAutoTagging.Failed, + _ => (GoogleAutoTagging)(-1), + }; + } + + public override void Write( + Utf8JsonWriter writer, + GoogleAutoTagging value, + JsonSerializerOptions options + ) + { + JsonSerializer.Serialize( + writer, + value switch + { + GoogleAutoTagging.Success => "success", + GoogleAutoTagging.Pending => "pending", + GoogleAutoTagging.Failed => "failed", + _ => throw new ArgumentOutOfRangeException(nameof(value)), + }, + options + ); + } +} diff --git a/src/Imagekit/Models/Files/FileUploadResponseProperties/ExtensionStatusProperties/RemoveBg.cs b/src/Imagekit/Models/Files/FileUploadResponseProperties/ExtensionStatusProperties/RemoveBg.cs new file mode 100644 index 00000000..08d97e52 --- /dev/null +++ b/src/Imagekit/Models/Files/FileUploadResponseProperties/ExtensionStatusProperties/RemoveBg.cs @@ -0,0 +1,46 @@ +using System; +using System.Text.Json; +using System.Text.Json.Serialization; + +namespace Imagekit.Models.Files.FileUploadResponseProperties.ExtensionStatusProperties; + +[JsonConverter(typeof(RemoveBgConverter))] +public enum RemoveBg +{ + Success, + Pending, + Failed, +} + +sealed class RemoveBgConverter : JsonConverter +{ + public override RemoveBg Read( + ref Utf8JsonReader reader, + Type typeToConvert, + JsonSerializerOptions options + ) + { + return JsonSerializer.Deserialize(ref reader, options) switch + { + "success" => RemoveBg.Success, + "pending" => RemoveBg.Pending, + "failed" => RemoveBg.Failed, + _ => (RemoveBg)(-1), + }; + } + + public override void Write(Utf8JsonWriter writer, RemoveBg value, JsonSerializerOptions options) + { + JsonSerializer.Serialize( + writer, + value switch + { + RemoveBg.Success => "success", + RemoveBg.Pending => "pending", + RemoveBg.Failed => "failed", + _ => throw new ArgumentOutOfRangeException(nameof(value)), + }, + options + ); + } +} diff --git a/src/Imagekit/Models/Files/FileUploadResponseProperties/VersionInfo.cs b/src/Imagekit/Models/Files/FileUploadResponseProperties/VersionInfo.cs new file mode 100644 index 00000000..a54f4050 --- /dev/null +++ b/src/Imagekit/Models/Files/FileUploadResponseProperties/VersionInfo.cs @@ -0,0 +1,76 @@ +using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; +using System.Text.Json; +using System.Text.Json.Serialization; + +namespace Imagekit.Models.Files.FileUploadResponseProperties; + +/// +/// An object containing the file or file version's `id` (versionId) and `name`. +/// +[JsonConverter(typeof(ModelConverter))] +public sealed record class VersionInfo : ModelBase, IFromRaw +{ + /// + /// Unique identifier of the file version. + /// + public string? ID + { + get + { + if (!this.Properties.TryGetValue("id", out JsonElement element)) + return null; + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions); + } + set + { + this.Properties["id"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + /// + /// Name of the file version. + /// + public string? Name + { + get + { + if (!this.Properties.TryGetValue("name", out JsonElement element)) + return null; + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions); + } + set + { + this.Properties["name"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + public override void Validate() + { + _ = this.ID; + _ = this.Name; + } + + public VersionInfo() { } + +#pragma warning disable CS8618 + [SetsRequiredMembers] + VersionInfo(Dictionary properties) + { + Properties = properties; + } +#pragma warning restore CS8618 + + public static VersionInfo FromRawUnchecked(Dictionary properties) + { + return new(properties); + } +} diff --git a/src/Imagekit/Models/Files/Folder.cs b/src/Imagekit/Models/Files/Folder.cs new file mode 100644 index 00000000..5a3d957c --- /dev/null +++ b/src/Imagekit/Models/Files/Folder.cs @@ -0,0 +1,171 @@ +using System; +using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; +using System.Text.Json; +using System.Text.Json.Serialization; +using FolderProperties = Imagekit.Models.Files.FolderProperties; + +namespace Imagekit.Models.Files; + +[JsonConverter(typeof(ModelConverter))] +public sealed record class Folder : ModelBase, IFromRaw +{ + /// + /// Date and time when the folder was created. The date and time is in ISO8601 + /// format. + /// + public DateTime? CreatedAt + { + get + { + if (!this.Properties.TryGetValue("createdAt", out JsonElement element)) + return null; + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions); + } + set + { + this.Properties["createdAt"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + /// + /// Unique identifier of the asset. + /// + public string? FolderID + { + get + { + if (!this.Properties.TryGetValue("folderId", out JsonElement element)) + return null; + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions); + } + set + { + this.Properties["folderId"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + /// + /// Path of the folder. This is the path you would use in the URL to access the + /// folder. For example, if the folder is at the root of the media library, the + /// path will be /folder. If the folder is inside another folder named images, + /// the path will be /images/folder. + /// + public string? FolderPath + { + get + { + if (!this.Properties.TryGetValue("folderPath", out JsonElement element)) + return null; + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions); + } + set + { + this.Properties["folderPath"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + /// + /// Name of the asset. + /// + public string? Name + { + get + { + if (!this.Properties.TryGetValue("name", out JsonElement element)) + return null; + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions); + } + set + { + this.Properties["name"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + /// + /// Type of the asset. + /// + public ApiEnum? Type + { + get + { + if (!this.Properties.TryGetValue("type", out JsonElement element)) + return null; + + return JsonSerializer.Deserialize?>( + element, + ModelBase.SerializerOptions + ); + } + set + { + this.Properties["type"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + /// + /// Date and time when the folder was last updated. The date and time is in ISO8601 + /// format. + /// + public DateTime? UpdatedAt + { + get + { + if (!this.Properties.TryGetValue("updatedAt", out JsonElement element)) + return null; + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions); + } + set + { + this.Properties["updatedAt"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + public override void Validate() + { + _ = this.CreatedAt; + _ = this.FolderID; + _ = this.FolderPath; + _ = this.Name; + this.Type?.Validate(); + _ = this.UpdatedAt; + } + + public Folder() { } + +#pragma warning disable CS8618 + [SetsRequiredMembers] + Folder(Dictionary properties) + { + Properties = properties; + } +#pragma warning restore CS8618 + + public static Folder FromRawUnchecked(Dictionary properties) + { + return new(properties); + } +} diff --git a/src/Imagekit/Models/Files/FolderProperties/Type.cs b/src/Imagekit/Models/Files/FolderProperties/Type.cs new file mode 100644 index 00000000..0d97363d --- /dev/null +++ b/src/Imagekit/Models/Files/FolderProperties/Type.cs @@ -0,0 +1,43 @@ +using System.Text.Json; +using System.Text.Json.Serialization; +using System = System; + +namespace Imagekit.Models.Files.FolderProperties; + +/// +/// Type of the asset. +/// +[JsonConverter(typeof(TypeConverter))] +public enum Type +{ + Folder, +} + +sealed class TypeConverter : JsonConverter +{ + public override Type Read( + ref Utf8JsonReader reader, + System::Type typeToConvert, + JsonSerializerOptions options + ) + { + return JsonSerializer.Deserialize(ref reader, options) switch + { + "folder" => FolderProperties.Type.Folder, + _ => (Type)(-1), + }; + } + + public override void Write(Utf8JsonWriter writer, Type value, JsonSerializerOptions options) + { + JsonSerializer.Serialize( + writer, + value switch + { + FolderProperties.Type.Folder => "folder", + _ => throw new System::ArgumentOutOfRangeException(nameof(value)), + }, + options + ); + } +} diff --git a/src/Imagekit/Models/Files/Metadata.cs b/src/Imagekit/Models/Files/Metadata.cs new file mode 100644 index 00000000..8c59db4f --- /dev/null +++ b/src/Imagekit/Models/Files/Metadata.cs @@ -0,0 +1,338 @@ +using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; +using System.Text.Json; +using System.Text.Json.Serialization; +using Imagekit.Models.Files.MetadataProperties; + +namespace Imagekit.Models.Files; + +/// +/// JSON object containing metadata. +/// +[JsonConverter(typeof(ModelConverter))] +public sealed record class Metadata : ModelBase, IFromRaw +{ + /// + /// The audio codec used in the video (only for video). + /// + public string? AudioCodec + { + get + { + if (!this.Properties.TryGetValue("audioCodec", out JsonElement element)) + return null; + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions); + } + set + { + this.Properties["audioCodec"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + /// + /// The bit rate of the video in kbps (only for video). + /// + public long? BitRate + { + get + { + if (!this.Properties.TryGetValue("bitRate", out JsonElement element)) + return null; + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions); + } + set + { + this.Properties["bitRate"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + /// + /// The density of the image in DPI. + /// + public long? Density + { + get + { + if (!this.Properties.TryGetValue("density", out JsonElement element)) + return null; + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions); + } + set + { + this.Properties["density"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + /// + /// The duration of the video in seconds (only for video). + /// + public long? Duration + { + get + { + if (!this.Properties.TryGetValue("duration", out JsonElement element)) + return null; + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions); + } + set + { + this.Properties["duration"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + public Exif? Exif + { + get + { + if (!this.Properties.TryGetValue("exif", out JsonElement element)) + return null; + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions); + } + set + { + this.Properties["exif"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + /// + /// The format of the file (e.g., 'jpg', 'mp4'). + /// + public string? Format + { + get + { + if (!this.Properties.TryGetValue("format", out JsonElement element)) + return null; + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions); + } + set + { + this.Properties["format"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + /// + /// Indicates if the image has a color profile. + /// + public bool? HasColorProfile + { + get + { + if (!this.Properties.TryGetValue("hasColorProfile", out JsonElement element)) + return null; + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions); + } + set + { + this.Properties["hasColorProfile"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + /// + /// Indicates if the image contains transparent areas. + /// + public bool? HasTransparency + { + get + { + if (!this.Properties.TryGetValue("hasTransparency", out JsonElement element)) + return null; + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions); + } + set + { + this.Properties["hasTransparency"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + /// + /// The height of the image or video in pixels. + /// + public long? Height + { + get + { + if (!this.Properties.TryGetValue("height", out JsonElement element)) + return null; + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions); + } + set + { + this.Properties["height"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + /// + /// Perceptual hash of the image. + /// + public string? PHash + { + get + { + if (!this.Properties.TryGetValue("pHash", out JsonElement element)) + return null; + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions); + } + set + { + this.Properties["pHash"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + /// + /// The quality indicator of the image. + /// + public long? Quality + { + get + { + if (!this.Properties.TryGetValue("quality", out JsonElement element)) + return null; + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions); + } + set + { + this.Properties["quality"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + /// + /// The file size in bytes. + /// + public long? Size + { + get + { + if (!this.Properties.TryGetValue("size", out JsonElement element)) + return null; + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions); + } + set + { + this.Properties["size"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + /// + /// The video codec used in the video (only for video). + /// + public string? VideoCodec + { + get + { + if (!this.Properties.TryGetValue("videoCodec", out JsonElement element)) + return null; + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions); + } + set + { + this.Properties["videoCodec"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + /// + /// The width of the image or video in pixels. + /// + public long? Width + { + get + { + if (!this.Properties.TryGetValue("width", out JsonElement element)) + return null; + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions); + } + set + { + this.Properties["width"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + public override void Validate() + { + _ = this.AudioCodec; + _ = this.BitRate; + _ = this.Density; + _ = this.Duration; + this.Exif?.Validate(); + _ = this.Format; + _ = this.HasColorProfile; + _ = this.HasTransparency; + _ = this.Height; + _ = this.PHash; + _ = this.Quality; + _ = this.Size; + _ = this.VideoCodec; + _ = this.Width; + } + + public Metadata() { } + +#pragma warning disable CS8618 + [SetsRequiredMembers] + Metadata(Dictionary properties) + { + Properties = properties; + } +#pragma warning restore CS8618 + + public static Metadata FromRawUnchecked(Dictionary properties) + { + return new(properties); + } +} diff --git a/src/Imagekit/Models/Files/Metadata/MetadataGetFromURLParams.cs b/src/Imagekit/Models/Files/Metadata/MetadataGetFromURLParams.cs new file mode 100644 index 00000000..45993ec0 --- /dev/null +++ b/src/Imagekit/Models/Files/Metadata/MetadataGetFromURLParams.cs @@ -0,0 +1,52 @@ +using System; +using System.Net.Http; +using System.Text.Json; + +namespace Imagekit.Models.Files.Metadata; + +/// +/// Get image EXIF, pHash, and other metadata from ImageKit.io powered remote URL +/// using this API. +/// +public sealed record class MetadataGetFromURLParams : ParamsBase +{ + /// + /// Should be a valid file URL. It should be accessible using your ImageKit.io + /// account. + /// + public required string URL + { + get + { + if (!this.QueryProperties.TryGetValue("url", out JsonElement element)) + throw new ArgumentOutOfRangeException("url", "Missing required argument"); + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions) + ?? throw new ArgumentNullException("url"); + } + set + { + this.QueryProperties["url"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + public override Uri Url(IImageKitClient client) + { + return new UriBuilder(client.BaseUrl.ToString().TrimEnd('/') + "/v1/files/metadata") + { + Query = this.QueryString(client), + }.Uri; + } + + public void AddHeadersToRequest(HttpRequestMessage request, IImageKitClient client) + { + ParamsBase.AddDefaultHeaders(request, client); + foreach (var item in this.HeaderProperties) + { + ParamsBase.AddHeaderElementToRequest(request, item.Key, item.Value); + } + } +} diff --git a/src/Imagekit/Models/Files/Metadata/MetadataGetParams.cs b/src/Imagekit/Models/Files/Metadata/MetadataGetParams.cs new file mode 100644 index 00000000..acd20a10 --- /dev/null +++ b/src/Imagekit/Models/Files/Metadata/MetadataGetParams.cs @@ -0,0 +1,36 @@ +using System; +using System.Net.Http; + +namespace Imagekit.Models.Files.Metadata; + +/// +/// You can programmatically get image EXIF, pHash, and other metadata for uploaded +/// files in the ImageKit.io media library using this API. +/// +/// You can also get the metadata in upload API response by passing `metadata` in +/// `responseFields` parameter. +/// +public sealed record class MetadataGetParams : ParamsBase +{ + public required string FileID; + + public override Uri Url(IImageKitClient client) + { + return new UriBuilder( + client.BaseUrl.ToString().TrimEnd('/') + + string.Format("/v1/files/{0}/metadata", this.FileID) + ) + { + Query = this.QueryString(client), + }.Uri; + } + + public void AddHeadersToRequest(HttpRequestMessage request, IImageKitClient client) + { + ParamsBase.AddDefaultHeaders(request, client); + foreach (var item in this.HeaderProperties) + { + ParamsBase.AddHeaderElementToRequest(request, item.Key, item.Value); + } + } +} diff --git a/src/Imagekit/Models/Files/MetadataProperties/Exif.cs b/src/Imagekit/Models/Files/MetadataProperties/Exif.cs new file mode 100644 index 00000000..db2ed74c --- /dev/null +++ b/src/Imagekit/Models/Files/MetadataProperties/Exif.cs @@ -0,0 +1,183 @@ +using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; +using System.Text.Json; +using System.Text.Json.Serialization; +using ExifProperties = Imagekit.Models.Files.MetadataProperties.ExifProperties; + +namespace Imagekit.Models.Files.MetadataProperties; + +[JsonConverter(typeof(ModelConverter))] +public sealed record class Exif : ModelBase, IFromRaw +{ + /// + /// Object containing Exif details. + /// + public ExifProperties::Exif? Exif1 + { + get + { + if (!this.Properties.TryGetValue("exif", out JsonElement element)) + return null; + + return JsonSerializer.Deserialize( + element, + ModelBase.SerializerOptions + ); + } + set + { + this.Properties["exif"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + /// + /// Object containing GPS information. + /// + public ExifProperties::Gps? Gps + { + get + { + if (!this.Properties.TryGetValue("gps", out JsonElement element)) + return null; + + return JsonSerializer.Deserialize( + element, + ModelBase.SerializerOptions + ); + } + set + { + this.Properties["gps"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + /// + /// Object containing EXIF image information. + /// + public ExifProperties::Image? Image + { + get + { + if (!this.Properties.TryGetValue("image", out JsonElement element)) + return null; + + return JsonSerializer.Deserialize( + element, + ModelBase.SerializerOptions + ); + } + set + { + this.Properties["image"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + /// + /// JSON object. + /// + public ExifProperties::Interoperability? Interoperability + { + get + { + if (!this.Properties.TryGetValue("interoperability", out JsonElement element)) + return null; + + return JsonSerializer.Deserialize( + element, + ModelBase.SerializerOptions + ); + } + set + { + this.Properties["interoperability"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + public Dictionary? Makernote + { + get + { + if (!this.Properties.TryGetValue("makernote", out JsonElement element)) + return null; + + return JsonSerializer.Deserialize?>( + element, + ModelBase.SerializerOptions + ); + } + set + { + this.Properties["makernote"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + /// + /// Object containing Thumbnail information. + /// + public ExifProperties::Thumbnail? Thumbnail + { + get + { + if (!this.Properties.TryGetValue("thumbnail", out JsonElement element)) + return null; + + return JsonSerializer.Deserialize( + element, + ModelBase.SerializerOptions + ); + } + set + { + this.Properties["thumbnail"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + public override void Validate() + { + this.Exif1?.Validate(); + this.Gps?.Validate(); + this.Image?.Validate(); + this.Interoperability?.Validate(); + if (this.Makernote != null) + { + foreach (var item in this.Makernote.Values) + { + _ = item; + } + } + this.Thumbnail?.Validate(); + } + + public Exif() { } + +#pragma warning disable CS8618 + [SetsRequiredMembers] + Exif(Dictionary properties) + { + Properties = properties; + } +#pragma warning restore CS8618 + + public static Exif FromRawUnchecked(Dictionary properties) + { + return new(properties); + } +} diff --git a/src/Imagekit/Models/Files/MetadataProperties/ExifProperties/Exif.cs b/src/Imagekit/Models/Files/MetadataProperties/ExifProperties/Exif.cs new file mode 100644 index 00000000..2f1827b7 --- /dev/null +++ b/src/Imagekit/Models/Files/MetadataProperties/ExifProperties/Exif.cs @@ -0,0 +1,526 @@ +using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; +using System.Text.Json; +using System.Text.Json.Serialization; + +namespace Imagekit.Models.Files.MetadataProperties.ExifProperties; + +/// +/// Object containing Exif details. +/// +[JsonConverter(typeof(ModelConverter))] +public sealed record class Exif : ModelBase, IFromRaw +{ + public double? ApertureValue + { + get + { + if (!this.Properties.TryGetValue("ApertureValue", out JsonElement element)) + return null; + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions); + } + set + { + this.Properties["ApertureValue"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + public long? ColorSpace + { + get + { + if (!this.Properties.TryGetValue("ColorSpace", out JsonElement element)) + return null; + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions); + } + set + { + this.Properties["ColorSpace"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + public string? CreateDate + { + get + { + if (!this.Properties.TryGetValue("CreateDate", out JsonElement element)) + return null; + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions); + } + set + { + this.Properties["CreateDate"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + public long? CustomRendered + { + get + { + if (!this.Properties.TryGetValue("CustomRendered", out JsonElement element)) + return null; + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions); + } + set + { + this.Properties["CustomRendered"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + public string? DateTimeOriginal + { + get + { + if (!this.Properties.TryGetValue("DateTimeOriginal", out JsonElement element)) + return null; + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions); + } + set + { + this.Properties["DateTimeOriginal"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + public long? ExifImageHeight + { + get + { + if (!this.Properties.TryGetValue("ExifImageHeight", out JsonElement element)) + return null; + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions); + } + set + { + this.Properties["ExifImageHeight"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + public long? ExifImageWidth + { + get + { + if (!this.Properties.TryGetValue("ExifImageWidth", out JsonElement element)) + return null; + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions); + } + set + { + this.Properties["ExifImageWidth"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + public string? ExifVersion + { + get + { + if (!this.Properties.TryGetValue("ExifVersion", out JsonElement element)) + return null; + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions); + } + set + { + this.Properties["ExifVersion"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + public double? ExposureCompensation + { + get + { + if (!this.Properties.TryGetValue("ExposureCompensation", out JsonElement element)) + return null; + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions); + } + set + { + this.Properties["ExposureCompensation"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + public long? ExposureMode + { + get + { + if (!this.Properties.TryGetValue("ExposureMode", out JsonElement element)) + return null; + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions); + } + set + { + this.Properties["ExposureMode"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + public long? ExposureProgram + { + get + { + if (!this.Properties.TryGetValue("ExposureProgram", out JsonElement element)) + return null; + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions); + } + set + { + this.Properties["ExposureProgram"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + public double? ExposureTime + { + get + { + if (!this.Properties.TryGetValue("ExposureTime", out JsonElement element)) + return null; + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions); + } + set + { + this.Properties["ExposureTime"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + public long? Flash + { + get + { + if (!this.Properties.TryGetValue("Flash", out JsonElement element)) + return null; + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions); + } + set + { + this.Properties["Flash"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + public string? FlashpixVersion + { + get + { + if (!this.Properties.TryGetValue("FlashpixVersion", out JsonElement element)) + return null; + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions); + } + set + { + this.Properties["FlashpixVersion"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + public double? FNumber + { + get + { + if (!this.Properties.TryGetValue("FNumber", out JsonElement element)) + return null; + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions); + } + set + { + this.Properties["FNumber"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + public long? FocalLength + { + get + { + if (!this.Properties.TryGetValue("FocalLength", out JsonElement element)) + return null; + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions); + } + set + { + this.Properties["FocalLength"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + public long? FocalPlaneResolutionUnit + { + get + { + if (!this.Properties.TryGetValue("FocalPlaneResolutionUnit", out JsonElement element)) + return null; + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions); + } + set + { + this.Properties["FocalPlaneResolutionUnit"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + public double? FocalPlaneXResolution + { + get + { + if (!this.Properties.TryGetValue("FocalPlaneXResolution", out JsonElement element)) + return null; + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions); + } + set + { + this.Properties["FocalPlaneXResolution"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + public double? FocalPlaneYResolution + { + get + { + if (!this.Properties.TryGetValue("FocalPlaneYResolution", out JsonElement element)) + return null; + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions); + } + set + { + this.Properties["FocalPlaneYResolution"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + public long? InteropOffset + { + get + { + if (!this.Properties.TryGetValue("InteropOffset", out JsonElement element)) + return null; + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions); + } + set + { + this.Properties["InteropOffset"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + public long? ISO + { + get + { + if (!this.Properties.TryGetValue("ISO", out JsonElement element)) + return null; + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions); + } + set + { + this.Properties["ISO"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + public long? MeteringMode + { + get + { + if (!this.Properties.TryGetValue("MeteringMode", out JsonElement element)) + return null; + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions); + } + set + { + this.Properties["MeteringMode"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + public long? SceneCaptureType + { + get + { + if (!this.Properties.TryGetValue("SceneCaptureType", out JsonElement element)) + return null; + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions); + } + set + { + this.Properties["SceneCaptureType"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + public double? ShutterSpeedValue + { + get + { + if (!this.Properties.TryGetValue("ShutterSpeedValue", out JsonElement element)) + return null; + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions); + } + set + { + this.Properties["ShutterSpeedValue"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + public string? SubSecTime + { + get + { + if (!this.Properties.TryGetValue("SubSecTime", out JsonElement element)) + return null; + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions); + } + set + { + this.Properties["SubSecTime"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + public long? WhiteBalance + { + get + { + if (!this.Properties.TryGetValue("WhiteBalance", out JsonElement element)) + return null; + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions); + } + set + { + this.Properties["WhiteBalance"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + public override void Validate() + { + _ = this.ApertureValue; + _ = this.ColorSpace; + _ = this.CreateDate; + _ = this.CustomRendered; + _ = this.DateTimeOriginal; + _ = this.ExifImageHeight; + _ = this.ExifImageWidth; + _ = this.ExifVersion; + _ = this.ExposureCompensation; + _ = this.ExposureMode; + _ = this.ExposureProgram; + _ = this.ExposureTime; + _ = this.Flash; + _ = this.FlashpixVersion; + _ = this.FNumber; + _ = this.FocalLength; + _ = this.FocalPlaneResolutionUnit; + _ = this.FocalPlaneXResolution; + _ = this.FocalPlaneYResolution; + _ = this.InteropOffset; + _ = this.ISO; + _ = this.MeteringMode; + _ = this.SceneCaptureType; + _ = this.ShutterSpeedValue; + _ = this.SubSecTime; + _ = this.WhiteBalance; + } + + public Exif() { } + +#pragma warning disable CS8618 + [SetsRequiredMembers] + Exif(Dictionary properties) + { + Properties = properties; + } +#pragma warning restore CS8618 + + public static Exif FromRawUnchecked(Dictionary properties) + { + return new(properties); + } +} diff --git a/src/Imagekit/Models/Files/MetadataProperties/ExifProperties/Gps.cs b/src/Imagekit/Models/Files/MetadataProperties/ExifProperties/Gps.cs new file mode 100644 index 00000000..aa6d03c1 --- /dev/null +++ b/src/Imagekit/Models/Files/MetadataProperties/ExifProperties/Gps.cs @@ -0,0 +1,54 @@ +using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; +using System.Text.Json; +using System.Text.Json.Serialization; + +namespace Imagekit.Models.Files.MetadataProperties.ExifProperties; + +/// +/// Object containing GPS information. +/// +[JsonConverter(typeof(ModelConverter))] +public sealed record class Gps : ModelBase, IFromRaw +{ + public List? GpsVersionID + { + get + { + if (!this.Properties.TryGetValue("GPSVersionID", out JsonElement element)) + return null; + + return JsonSerializer.Deserialize?>(element, ModelBase.SerializerOptions); + } + set + { + this.Properties["GPSVersionID"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + public override void Validate() + { + foreach (var item in this.GpsVersionID ?? []) + { + _ = item; + } + } + + public Gps() { } + +#pragma warning disable CS8618 + [SetsRequiredMembers] + Gps(Dictionary properties) + { + Properties = properties; + } +#pragma warning restore CS8618 + + public static Gps FromRawUnchecked(Dictionary properties) + { + return new(properties); + } +} diff --git a/src/Imagekit/Models/Files/MetadataProperties/ExifProperties/Image.cs b/src/Imagekit/Models/Files/MetadataProperties/ExifProperties/Image.cs new file mode 100644 index 00000000..5c25d6a2 --- /dev/null +++ b/src/Imagekit/Models/Files/MetadataProperties/ExifProperties/Image.cs @@ -0,0 +1,241 @@ +using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; +using System.Text.Json; +using System.Text.Json.Serialization; + +namespace Imagekit.Models.Files.MetadataProperties.ExifProperties; + +/// +/// Object containing EXIF image information. +/// +[JsonConverter(typeof(ModelConverter))] +public sealed record class Image : ModelBase, IFromRaw +{ + public long? ExifOffset + { + get + { + if (!this.Properties.TryGetValue("ExifOffset", out JsonElement element)) + return null; + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions); + } + set + { + this.Properties["ExifOffset"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + public long? GpsInfo + { + get + { + if (!this.Properties.TryGetValue("GPSInfo", out JsonElement element)) + return null; + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions); + } + set + { + this.Properties["GPSInfo"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + public string? Make + { + get + { + if (!this.Properties.TryGetValue("Make", out JsonElement element)) + return null; + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions); + } + set + { + this.Properties["Make"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + public string? Model + { + get + { + if (!this.Properties.TryGetValue("Model", out JsonElement element)) + return null; + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions); + } + set + { + this.Properties["Model"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + public string? ModifyDate + { + get + { + if (!this.Properties.TryGetValue("ModifyDate", out JsonElement element)) + return null; + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions); + } + set + { + this.Properties["ModifyDate"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + public long? Orientation + { + get + { + if (!this.Properties.TryGetValue("Orientation", out JsonElement element)) + return null; + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions); + } + set + { + this.Properties["Orientation"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + public long? ResolutionUnit + { + get + { + if (!this.Properties.TryGetValue("ResolutionUnit", out JsonElement element)) + return null; + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions); + } + set + { + this.Properties["ResolutionUnit"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + public string? Software + { + get + { + if (!this.Properties.TryGetValue("Software", out JsonElement element)) + return null; + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions); + } + set + { + this.Properties["Software"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + public long? XResolution + { + get + { + if (!this.Properties.TryGetValue("XResolution", out JsonElement element)) + return null; + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions); + } + set + { + this.Properties["XResolution"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + public long? YCbCrPositioning + { + get + { + if (!this.Properties.TryGetValue("YCbCrPositioning", out JsonElement element)) + return null; + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions); + } + set + { + this.Properties["YCbCrPositioning"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + public long? YResolution + { + get + { + if (!this.Properties.TryGetValue("YResolution", out JsonElement element)) + return null; + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions); + } + set + { + this.Properties["YResolution"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + public override void Validate() + { + _ = this.ExifOffset; + _ = this.GpsInfo; + _ = this.Make; + _ = this.Model; + _ = this.ModifyDate; + _ = this.Orientation; + _ = this.ResolutionUnit; + _ = this.Software; + _ = this.XResolution; + _ = this.YCbCrPositioning; + _ = this.YResolution; + } + + public Image() { } + +#pragma warning disable CS8618 + [SetsRequiredMembers] + Image(Dictionary properties) + { + Properties = properties; + } +#pragma warning restore CS8618 + + public static Image FromRawUnchecked(Dictionary properties) + { + return new(properties); + } +} diff --git a/src/Imagekit/Models/Files/MetadataProperties/ExifProperties/Interoperability.cs b/src/Imagekit/Models/Files/MetadataProperties/ExifProperties/Interoperability.cs new file mode 100644 index 00000000..36225916 --- /dev/null +++ b/src/Imagekit/Models/Files/MetadataProperties/ExifProperties/Interoperability.cs @@ -0,0 +1,70 @@ +using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; +using System.Text.Json; +using System.Text.Json.Serialization; + +namespace Imagekit.Models.Files.MetadataProperties.ExifProperties; + +/// +/// JSON object. +/// +[JsonConverter(typeof(ModelConverter))] +public sealed record class Interoperability : ModelBase, IFromRaw +{ + public string? InteropIndex + { + get + { + if (!this.Properties.TryGetValue("InteropIndex", out JsonElement element)) + return null; + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions); + } + set + { + this.Properties["InteropIndex"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + public string? InteropVersion + { + get + { + if (!this.Properties.TryGetValue("InteropVersion", out JsonElement element)) + return null; + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions); + } + set + { + this.Properties["InteropVersion"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + public override void Validate() + { + _ = this.InteropIndex; + _ = this.InteropVersion; + } + + public Interoperability() { } + +#pragma warning disable CS8618 + [SetsRequiredMembers] + Interoperability(Dictionary properties) + { + Properties = properties; + } +#pragma warning restore CS8618 + + public static Interoperability FromRawUnchecked(Dictionary properties) + { + return new(properties); + } +} diff --git a/src/Imagekit/Models/Files/MetadataProperties/ExifProperties/Thumbnail.cs b/src/Imagekit/Models/Files/MetadataProperties/ExifProperties/Thumbnail.cs new file mode 100644 index 00000000..9e01cf4c --- /dev/null +++ b/src/Imagekit/Models/Files/MetadataProperties/ExifProperties/Thumbnail.cs @@ -0,0 +1,146 @@ +using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; +using System.Text.Json; +using System.Text.Json.Serialization; + +namespace Imagekit.Models.Files.MetadataProperties.ExifProperties; + +/// +/// Object containing Thumbnail information. +/// +[JsonConverter(typeof(ModelConverter))] +public sealed record class Thumbnail : ModelBase, IFromRaw +{ + public long? Compression + { + get + { + if (!this.Properties.TryGetValue("Compression", out JsonElement element)) + return null; + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions); + } + set + { + this.Properties["Compression"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + public long? ResolutionUnit + { + get + { + if (!this.Properties.TryGetValue("ResolutionUnit", out JsonElement element)) + return null; + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions); + } + set + { + this.Properties["ResolutionUnit"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + public long? ThumbnailLength + { + get + { + if (!this.Properties.TryGetValue("ThumbnailLength", out JsonElement element)) + return null; + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions); + } + set + { + this.Properties["ThumbnailLength"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + public long? ThumbnailOffset + { + get + { + if (!this.Properties.TryGetValue("ThumbnailOffset", out JsonElement element)) + return null; + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions); + } + set + { + this.Properties["ThumbnailOffset"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + public long? XResolution + { + get + { + if (!this.Properties.TryGetValue("XResolution", out JsonElement element)) + return null; + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions); + } + set + { + this.Properties["XResolution"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + public long? YResolution + { + get + { + if (!this.Properties.TryGetValue("YResolution", out JsonElement element)) + return null; + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions); + } + set + { + this.Properties["YResolution"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + public override void Validate() + { + _ = this.Compression; + _ = this.ResolutionUnit; + _ = this.ThumbnailLength; + _ = this.ThumbnailOffset; + _ = this.XResolution; + _ = this.YResolution; + } + + public Thumbnail() { } + +#pragma warning disable CS8618 + [SetsRequiredMembers] + Thumbnail(Dictionary properties) + { + Properties = properties; + } +#pragma warning restore CS8618 + + public static Thumbnail FromRawUnchecked(Dictionary properties) + { + return new(properties); + } +} diff --git a/src/Imagekit/Models/Files/Versions/VersionDeleteParams.cs b/src/Imagekit/Models/Files/Versions/VersionDeleteParams.cs new file mode 100644 index 00000000..7b43acb3 --- /dev/null +++ b/src/Imagekit/Models/Files/Versions/VersionDeleteParams.cs @@ -0,0 +1,36 @@ +using System; +using System.Net.Http; + +namespace Imagekit.Models.Files.Versions; + +/// +/// This API deletes a non-current file version permanently. The API returns an empty response. +/// +/// Note: If you want to delete all versions of a file, use the delete file API. +/// +public sealed record class VersionDeleteParams : ParamsBase +{ + public required string FileID; + + public required string VersionID; + + public override Uri Url(IImageKitClient client) + { + return new UriBuilder( + client.BaseUrl.ToString().TrimEnd('/') + + string.Format("/v1/files/{0}/versions/{1}", this.FileID, this.VersionID) + ) + { + Query = this.QueryString(client), + }.Uri; + } + + public void AddHeadersToRequest(HttpRequestMessage request, IImageKitClient client) + { + ParamsBase.AddDefaultHeaders(request, client); + foreach (var item in this.HeaderProperties) + { + ParamsBase.AddHeaderElementToRequest(request, item.Key, item.Value); + } + } +} diff --git a/src/Imagekit/Models/Files/Versions/VersionDeleteResponse.cs b/src/Imagekit/Models/Files/Versions/VersionDeleteResponse.cs new file mode 100644 index 00000000..b5ca5287 --- /dev/null +++ b/src/Imagekit/Models/Files/Versions/VersionDeleteResponse.cs @@ -0,0 +1,27 @@ +using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; +using System.Text.Json; +using System.Text.Json.Serialization; + +namespace Imagekit.Models.Files.Versions; + +[JsonConverter(typeof(ModelConverter))] +public sealed record class VersionDeleteResponse : ModelBase, IFromRaw +{ + public override void Validate() { } + + public VersionDeleteResponse() { } + +#pragma warning disable CS8618 + [SetsRequiredMembers] + VersionDeleteResponse(Dictionary properties) + { + Properties = properties; + } +#pragma warning restore CS8618 + + public static VersionDeleteResponse FromRawUnchecked(Dictionary properties) + { + return new(properties); + } +} diff --git a/src/Imagekit/Models/Files/Versions/VersionGetParams.cs b/src/Imagekit/Models/Files/Versions/VersionGetParams.cs new file mode 100644 index 00000000..f1850a9a --- /dev/null +++ b/src/Imagekit/Models/Files/Versions/VersionGetParams.cs @@ -0,0 +1,34 @@ +using System; +using System.Net.Http; + +namespace Imagekit.Models.Files.Versions; + +/// +/// This API returns an object with details or attributes of a file version. +/// +public sealed record class VersionGetParams : ParamsBase +{ + public required string FileID; + + public required string VersionID; + + public override Uri Url(IImageKitClient client) + { + return new UriBuilder( + client.BaseUrl.ToString().TrimEnd('/') + + string.Format("/v1/files/{0}/versions/{1}", this.FileID, this.VersionID) + ) + { + Query = this.QueryString(client), + }.Uri; + } + + public void AddHeadersToRequest(HttpRequestMessage request, IImageKitClient client) + { + ParamsBase.AddDefaultHeaders(request, client); + foreach (var item in this.HeaderProperties) + { + ParamsBase.AddHeaderElementToRequest(request, item.Key, item.Value); + } + } +} diff --git a/src/Imagekit/Models/Files/Versions/VersionListParams.cs b/src/Imagekit/Models/Files/Versions/VersionListParams.cs new file mode 100644 index 00000000..359cb066 --- /dev/null +++ b/src/Imagekit/Models/Files/Versions/VersionListParams.cs @@ -0,0 +1,32 @@ +using System; +using System.Net.Http; + +namespace Imagekit.Models.Files.Versions; + +/// +/// This API returns details of all versions of a file. +/// +public sealed record class VersionListParams : ParamsBase +{ + public required string FileID; + + public override Uri Url(IImageKitClient client) + { + return new UriBuilder( + client.BaseUrl.ToString().TrimEnd('/') + + string.Format("/v1/files/{0}/versions", this.FileID) + ) + { + Query = this.QueryString(client), + }.Uri; + } + + public void AddHeadersToRequest(HttpRequestMessage request, IImageKitClient client) + { + ParamsBase.AddDefaultHeaders(request, client); + foreach (var item in this.HeaderProperties) + { + ParamsBase.AddHeaderElementToRequest(request, item.Key, item.Value); + } + } +} diff --git a/src/Imagekit/Models/Files/Versions/VersionRestoreParams.cs b/src/Imagekit/Models/Files/Versions/VersionRestoreParams.cs new file mode 100644 index 00000000..71a8ca90 --- /dev/null +++ b/src/Imagekit/Models/Files/Versions/VersionRestoreParams.cs @@ -0,0 +1,34 @@ +using System; +using System.Net.Http; + +namespace Imagekit.Models.Files.Versions; + +/// +/// This API restores a file version as the current file version. +/// +public sealed record class VersionRestoreParams : ParamsBase +{ + public required string FileID; + + public required string VersionID; + + public override Uri Url(IImageKitClient client) + { + return new UriBuilder( + client.BaseUrl.ToString().TrimEnd('/') + + string.Format("/v1/files/{0}/versions/{1}/restore", this.FileID, this.VersionID) + ) + { + Query = this.QueryString(client), + }.Uri; + } + + public void AddHeadersToRequest(HttpRequestMessage request, IImageKitClient client) + { + ParamsBase.AddDefaultHeaders(request, client); + foreach (var item in this.HeaderProperties) + { + ParamsBase.AddHeaderElementToRequest(request, item.Key, item.Value); + } + } +} diff --git a/src/Imagekit/Models/Folders/FolderCopyParams.cs b/src/Imagekit/Models/Folders/FolderCopyParams.cs new file mode 100644 index 00000000..9f99e796 --- /dev/null +++ b/src/Imagekit/Models/Folders/FolderCopyParams.cs @@ -0,0 +1,120 @@ +using System; +using System.Collections.Generic; +using System.Net.Http; +using System.Text; +using System.Text.Json; + +namespace Imagekit.Models.Folders; + +/// +/// This will copy one folder into another. The selected folder, its nested folders, +/// files, and their versions (in `includeVersions` is set to true) are copied in +/// this operation. Note: If any file at the destination has the same name as the +/// source file, then the source file and its versions will be appended to the destination +/// file version history. +/// +public sealed record class FolderCopyParams : ParamsBase +{ + public Dictionary BodyProperties { get; set; } = []; + + /// + /// Full path to the destination folder where you want to copy the source folder + /// into. + /// + public required string DestinationPath + { + get + { + if (!this.BodyProperties.TryGetValue("destinationPath", out JsonElement element)) + throw new ArgumentOutOfRangeException( + "destinationPath", + "Missing required argument" + ); + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions) + ?? throw new ArgumentNullException("destinationPath"); + } + set + { + this.BodyProperties["destinationPath"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + /// + /// The full path to the source folder you want to copy. + /// + public required string SourceFolderPath + { + get + { + if (!this.BodyProperties.TryGetValue("sourceFolderPath", out JsonElement element)) + throw new ArgumentOutOfRangeException( + "sourceFolderPath", + "Missing required argument" + ); + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions) + ?? throw new ArgumentNullException("sourceFolderPath"); + } + set + { + this.BodyProperties["sourceFolderPath"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + /// + /// Option to copy all versions of files that are nested inside the selected + /// folder. By default, only the current version of each file will be copied. + /// When set to true, all versions of each file will be copied. Default value + /// - `false`. + /// + public bool? IncludeVersions + { + get + { + if (!this.BodyProperties.TryGetValue("includeVersions", out JsonElement element)) + return null; + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions); + } + set + { + this.BodyProperties["includeVersions"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + public override Uri Url(IImageKitClient client) + { + return new UriBuilder(client.BaseUrl.ToString().TrimEnd('/') + "/v1/bulkJobs/copyFolder") + { + Query = this.QueryString(client), + }.Uri; + } + + public StringContent BodyContent() + { + return new( + JsonSerializer.Serialize(this.BodyProperties), + Encoding.UTF8, + "application/json" + ); + } + + public void AddHeadersToRequest(HttpRequestMessage request, IImageKitClient client) + { + ParamsBase.AddDefaultHeaders(request, client); + foreach (var item in this.HeaderProperties) + { + ParamsBase.AddHeaderElementToRequest(request, item.Key, item.Value); + } + } +} diff --git a/src/Imagekit/Models/Folders/FolderCopyResponse.cs b/src/Imagekit/Models/Folders/FolderCopyResponse.cs new file mode 100644 index 00000000..546214a0 --- /dev/null +++ b/src/Imagekit/Models/Folders/FolderCopyResponse.cs @@ -0,0 +1,64 @@ +using System; +using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; +using System.Text.Json; +using System.Text.Json.Serialization; + +namespace Imagekit.Models.Folders; + +/// +/// Job submitted successfully. A `jobId` will be returned. +/// +[JsonConverter(typeof(ModelConverter))] +public sealed record class FolderCopyResponse : ModelBase, IFromRaw +{ + /// + /// Unique identifier of the bulk job. This can be used to check the status of + /// the bulk job. + /// + public required string JobID + { + get + { + if (!this.Properties.TryGetValue("jobId", out JsonElement element)) + throw new ArgumentOutOfRangeException("jobId", "Missing required argument"); + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions) + ?? throw new ArgumentNullException("jobId"); + } + set + { + this.Properties["jobId"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + public override void Validate() + { + _ = this.JobID; + } + + public FolderCopyResponse() { } + +#pragma warning disable CS8618 + [SetsRequiredMembers] + FolderCopyResponse(Dictionary properties) + { + Properties = properties; + } +#pragma warning restore CS8618 + + public static FolderCopyResponse FromRawUnchecked(Dictionary properties) + { + return new(properties); + } + + [SetsRequiredMembers] + public FolderCopyResponse(string jobID) + : this() + { + this.JobID = jobID; + } +} diff --git a/src/Imagekit/Models/Folders/FolderCreateParams.cs b/src/Imagekit/Models/Folders/FolderCreateParams.cs new file mode 100644 index 00000000..834ff0e7 --- /dev/null +++ b/src/Imagekit/Models/Folders/FolderCreateParams.cs @@ -0,0 +1,99 @@ +using System; +using System.Collections.Generic; +using System.Net.Http; +using System.Text; +using System.Text.Json; + +namespace Imagekit.Models.Folders; + +/// +/// This will create a new folder. You can specify the folder name and location of +/// the parent folder where this new folder should be created. +/// +public sealed record class FolderCreateParams : ParamsBase +{ + public Dictionary BodyProperties { get; set; } = []; + + /// + /// The folder will be created with this name. + /// + /// All characters except alphabets and numbers (inclusive of unicode letters, + /// marks, and numerals in other languages) will be replaced by an underscore + /// i.e. `_`. + /// + public required string FolderName + { + get + { + if (!this.BodyProperties.TryGetValue("folderName", out JsonElement element)) + throw new ArgumentOutOfRangeException("folderName", "Missing required argument"); + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions) + ?? throw new ArgumentNullException("folderName"); + } + set + { + this.BodyProperties["folderName"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + /// + /// The folder where the new folder should be created, for root use `/` else the + /// path e.g. `containing/folder/`. + /// + /// Note: If any folder(s) is not present in the parentFolderPath parameter, + /// it will be automatically created. For example, if you pass `/product/images/summer`, + /// then `product`, `images`, and `summer` folders will be created if they don't + /// already exist. + /// + public required string ParentFolderPath + { + get + { + if (!this.BodyProperties.TryGetValue("parentFolderPath", out JsonElement element)) + throw new ArgumentOutOfRangeException( + "parentFolderPath", + "Missing required argument" + ); + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions) + ?? throw new ArgumentNullException("parentFolderPath"); + } + set + { + this.BodyProperties["parentFolderPath"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + public override Uri Url(IImageKitClient client) + { + return new UriBuilder(client.BaseUrl.ToString().TrimEnd('/') + "/v1/folder") + { + Query = this.QueryString(client), + }.Uri; + } + + public StringContent BodyContent() + { + return new( + JsonSerializer.Serialize(this.BodyProperties), + Encoding.UTF8, + "application/json" + ); + } + + public void AddHeadersToRequest(HttpRequestMessage request, IImageKitClient client) + { + ParamsBase.AddDefaultHeaders(request, client); + foreach (var item in this.HeaderProperties) + { + ParamsBase.AddHeaderElementToRequest(request, item.Key, item.Value); + } + } +} diff --git a/src/Imagekit/Models/Folders/FolderCreateResponse.cs b/src/Imagekit/Models/Folders/FolderCreateResponse.cs new file mode 100644 index 00000000..c470a9e0 --- /dev/null +++ b/src/Imagekit/Models/Folders/FolderCreateResponse.cs @@ -0,0 +1,27 @@ +using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; +using System.Text.Json; +using System.Text.Json.Serialization; + +namespace Imagekit.Models.Folders; + +[JsonConverter(typeof(ModelConverter))] +public sealed record class FolderCreateResponse : ModelBase, IFromRaw +{ + public override void Validate() { } + + public FolderCreateResponse() { } + +#pragma warning disable CS8618 + [SetsRequiredMembers] + FolderCreateResponse(Dictionary properties) + { + Properties = properties; + } +#pragma warning restore CS8618 + + public static FolderCreateResponse FromRawUnchecked(Dictionary properties) + { + return new(properties); + } +} diff --git a/src/Imagekit/Models/Folders/FolderDeleteParams.cs b/src/Imagekit/Models/Folders/FolderDeleteParams.cs new file mode 100644 index 00000000..ba1ac4fa --- /dev/null +++ b/src/Imagekit/Models/Folders/FolderDeleteParams.cs @@ -0,0 +1,64 @@ +using System; +using System.Collections.Generic; +using System.Net.Http; +using System.Text; +using System.Text.Json; + +namespace Imagekit.Models.Folders; + +/// +/// This will delete a folder and all its contents permanently. The API returns an +/// empty response. +/// +public sealed record class FolderDeleteParams : ParamsBase +{ + public Dictionary BodyProperties { get; set; } = []; + + /// + /// Full path to the folder you want to delete. For example `/folder/to/delete/`. + /// + public required string FolderPath + { + get + { + if (!this.BodyProperties.TryGetValue("folderPath", out JsonElement element)) + throw new ArgumentOutOfRangeException("folderPath", "Missing required argument"); + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions) + ?? throw new ArgumentNullException("folderPath"); + } + set + { + this.BodyProperties["folderPath"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + public override Uri Url(IImageKitClient client) + { + return new UriBuilder(client.BaseUrl.ToString().TrimEnd('/') + "/v1/folder") + { + Query = this.QueryString(client), + }.Uri; + } + + public StringContent BodyContent() + { + return new( + JsonSerializer.Serialize(this.BodyProperties), + Encoding.UTF8, + "application/json" + ); + } + + public void AddHeadersToRequest(HttpRequestMessage request, IImageKitClient client) + { + ParamsBase.AddDefaultHeaders(request, client); + foreach (var item in this.HeaderProperties) + { + ParamsBase.AddHeaderElementToRequest(request, item.Key, item.Value); + } + } +} diff --git a/src/Imagekit/Models/Folders/FolderDeleteResponse.cs b/src/Imagekit/Models/Folders/FolderDeleteResponse.cs new file mode 100644 index 00000000..3ed1bc21 --- /dev/null +++ b/src/Imagekit/Models/Folders/FolderDeleteResponse.cs @@ -0,0 +1,27 @@ +using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; +using System.Text.Json; +using System.Text.Json.Serialization; + +namespace Imagekit.Models.Folders; + +[JsonConverter(typeof(ModelConverter))] +public sealed record class FolderDeleteResponse : ModelBase, IFromRaw +{ + public override void Validate() { } + + public FolderDeleteResponse() { } + +#pragma warning disable CS8618 + [SetsRequiredMembers] + FolderDeleteResponse(Dictionary properties) + { + Properties = properties; + } +#pragma warning restore CS8618 + + public static FolderDeleteResponse FromRawUnchecked(Dictionary properties) + { + return new(properties); + } +} diff --git a/src/Imagekit/Models/Folders/FolderMoveParams.cs b/src/Imagekit/Models/Folders/FolderMoveParams.cs new file mode 100644 index 00000000..dccbc3b3 --- /dev/null +++ b/src/Imagekit/Models/Folders/FolderMoveParams.cs @@ -0,0 +1,95 @@ +using System; +using System.Collections.Generic; +using System.Net.Http; +using System.Text; +using System.Text.Json; + +namespace Imagekit.Models.Folders; + +/// +/// This will move one folder into another. The selected folder, its nested folders, +/// files, and their versions are moved in this operation. Note: If any file at the +/// destination has the same name as the source file, then the source file and its +/// versions will be appended to the destination file version history. +/// +public sealed record class FolderMoveParams : ParamsBase +{ + public Dictionary BodyProperties { get; set; } = []; + + /// + /// Full path to the destination folder where you want to move the source folder + /// into. + /// + public required string DestinationPath + { + get + { + if (!this.BodyProperties.TryGetValue("destinationPath", out JsonElement element)) + throw new ArgumentOutOfRangeException( + "destinationPath", + "Missing required argument" + ); + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions) + ?? throw new ArgumentNullException("destinationPath"); + } + set + { + this.BodyProperties["destinationPath"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + /// + /// The full path to the source folder you want to move. + /// + public required string SourceFolderPath + { + get + { + if (!this.BodyProperties.TryGetValue("sourceFolderPath", out JsonElement element)) + throw new ArgumentOutOfRangeException( + "sourceFolderPath", + "Missing required argument" + ); + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions) + ?? throw new ArgumentNullException("sourceFolderPath"); + } + set + { + this.BodyProperties["sourceFolderPath"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + public override Uri Url(IImageKitClient client) + { + return new UriBuilder(client.BaseUrl.ToString().TrimEnd('/') + "/v1/bulkJobs/moveFolder") + { + Query = this.QueryString(client), + }.Uri; + } + + public StringContent BodyContent() + { + return new( + JsonSerializer.Serialize(this.BodyProperties), + Encoding.UTF8, + "application/json" + ); + } + + public void AddHeadersToRequest(HttpRequestMessage request, IImageKitClient client) + { + ParamsBase.AddDefaultHeaders(request, client); + foreach (var item in this.HeaderProperties) + { + ParamsBase.AddHeaderElementToRequest(request, item.Key, item.Value); + } + } +} diff --git a/src/Imagekit/Models/Folders/FolderMoveResponse.cs b/src/Imagekit/Models/Folders/FolderMoveResponse.cs new file mode 100644 index 00000000..6435065a --- /dev/null +++ b/src/Imagekit/Models/Folders/FolderMoveResponse.cs @@ -0,0 +1,64 @@ +using System; +using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; +using System.Text.Json; +using System.Text.Json.Serialization; + +namespace Imagekit.Models.Folders; + +/// +/// Job submitted successfully. A `jobId` will be returned. +/// +[JsonConverter(typeof(ModelConverter))] +public sealed record class FolderMoveResponse : ModelBase, IFromRaw +{ + /// + /// Unique identifier of the bulk job. This can be used to check the status of + /// the bulk job. + /// + public required string JobID + { + get + { + if (!this.Properties.TryGetValue("jobId", out JsonElement element)) + throw new ArgumentOutOfRangeException("jobId", "Missing required argument"); + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions) + ?? throw new ArgumentNullException("jobId"); + } + set + { + this.Properties["jobId"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + public override void Validate() + { + _ = this.JobID; + } + + public FolderMoveResponse() { } + +#pragma warning disable CS8618 + [SetsRequiredMembers] + FolderMoveResponse(Dictionary properties) + { + Properties = properties; + } +#pragma warning restore CS8618 + + public static FolderMoveResponse FromRawUnchecked(Dictionary properties) + { + return new(properties); + } + + [SetsRequiredMembers] + public FolderMoveResponse(string jobID) + : this() + { + this.JobID = jobID; + } +} diff --git a/src/Imagekit/Models/Folders/FolderRenameParams.cs b/src/Imagekit/Models/Folders/FolderRenameParams.cs new file mode 100644 index 00000000..b73112ce --- /dev/null +++ b/src/Imagekit/Models/Folders/FolderRenameParams.cs @@ -0,0 +1,126 @@ +using System; +using System.Collections.Generic; +using System.Net.Http; +using System.Text; +using System.Text.Json; + +namespace Imagekit.Models.Folders; + +/// +/// This API allows you to rename an existing folder. The folder and all its nested +/// assets and sub-folders will remain unchanged, but their paths will be updated +/// to reflect the new folder name. +/// +public sealed record class FolderRenameParams : ParamsBase +{ + public Dictionary BodyProperties { get; set; } = []; + + /// + /// The full path to the folder you want to rename. + /// + public required string FolderPath + { + get + { + if (!this.BodyProperties.TryGetValue("folderPath", out JsonElement element)) + throw new ArgumentOutOfRangeException("folderPath", "Missing required argument"); + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions) + ?? throw new ArgumentNullException("folderPath"); + } + set + { + this.BodyProperties["folderPath"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + /// + /// The new name for the folder. + /// + /// All characters except alphabets and numbers (inclusive of unicode letters, + /// marks, and numerals in other languages) and `-` will be replaced by an underscore + /// i.e. `_`. + /// + public required string NewFolderName + { + get + { + if (!this.BodyProperties.TryGetValue("newFolderName", out JsonElement element)) + throw new ArgumentOutOfRangeException("newFolderName", "Missing required argument"); + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions) + ?? throw new ArgumentNullException("newFolderName"); + } + set + { + this.BodyProperties["newFolderName"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + /// + /// Option to purge cache for the old nested files and their versions' URLs. + /// + /// When set to true, it will internally issue a purge cache request on CDN to + /// remove the cached content of the old nested files and their versions. There + /// will only be one purge request for all the nested files, which will be counted + /// against your monthly purge quota. + /// + /// Note: A purge cache request will be issued against `https://ik.imagekit.io/old/folder/path*` + /// (with a wildcard at the end). This will remove all nested files, their versions' + /// URLs, and any transformations made using query parameters on these files + /// or their versions. However, the cache for file transformations made using + /// path parameters will persist. You can purge them using the purge API. For + /// more details, refer to the purge API documentation. + /// + /// Default value - `false` + /// + public bool? PurgeCache + { + get + { + if (!this.BodyProperties.TryGetValue("purgeCache", out JsonElement element)) + return null; + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions); + } + set + { + this.BodyProperties["purgeCache"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + public override Uri Url(IImageKitClient client) + { + return new UriBuilder(client.BaseUrl.ToString().TrimEnd('/') + "/v1/bulkJobs/renameFolder") + { + Query = this.QueryString(client), + }.Uri; + } + + public StringContent BodyContent() + { + return new( + JsonSerializer.Serialize(this.BodyProperties), + Encoding.UTF8, + "application/json" + ); + } + + public void AddHeadersToRequest(HttpRequestMessage request, IImageKitClient client) + { + ParamsBase.AddDefaultHeaders(request, client); + foreach (var item in this.HeaderProperties) + { + ParamsBase.AddHeaderElementToRequest(request, item.Key, item.Value); + } + } +} diff --git a/src/Imagekit/Models/Folders/FolderRenameResponse.cs b/src/Imagekit/Models/Folders/FolderRenameResponse.cs new file mode 100644 index 00000000..8dd77536 --- /dev/null +++ b/src/Imagekit/Models/Folders/FolderRenameResponse.cs @@ -0,0 +1,64 @@ +using System; +using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; +using System.Text.Json; +using System.Text.Json.Serialization; + +namespace Imagekit.Models.Folders; + +/// +/// Job submitted successfully. A `jobId` will be returned. +/// +[JsonConverter(typeof(ModelConverter))] +public sealed record class FolderRenameResponse : ModelBase, IFromRaw +{ + /// + /// Unique identifier of the bulk job. This can be used to check the status of + /// the bulk job. + /// + public required string JobID + { + get + { + if (!this.Properties.TryGetValue("jobId", out JsonElement element)) + throw new ArgumentOutOfRangeException("jobId", "Missing required argument"); + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions) + ?? throw new ArgumentNullException("jobId"); + } + set + { + this.Properties["jobId"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + public override void Validate() + { + _ = this.JobID; + } + + public FolderRenameResponse() { } + +#pragma warning disable CS8618 + [SetsRequiredMembers] + FolderRenameResponse(Dictionary properties) + { + Properties = properties; + } +#pragma warning restore CS8618 + + public static FolderRenameResponse FromRawUnchecked(Dictionary properties) + { + return new(properties); + } + + [SetsRequiredMembers] + public FolderRenameResponse(string jobID) + : this() + { + this.JobID = jobID; + } +} diff --git a/src/Imagekit/Models/Folders/Job/JobGetParams.cs b/src/Imagekit/Models/Folders/Job/JobGetParams.cs new file mode 100644 index 00000000..cacc3f64 --- /dev/null +++ b/src/Imagekit/Models/Folders/Job/JobGetParams.cs @@ -0,0 +1,31 @@ +using System; +using System.Net.Http; + +namespace Imagekit.Models.Folders.Job; + +/// +/// This API returns the status of a bulk job like copy and move folder operations. +/// +public sealed record class JobGetParams : ParamsBase +{ + public required string JobID; + + public override Uri Url(IImageKitClient client) + { + return new UriBuilder( + client.BaseUrl.ToString().TrimEnd('/') + string.Format("/v1/bulkJobs/{0}", this.JobID) + ) + { + Query = this.QueryString(client), + }.Uri; + } + + public void AddHeadersToRequest(HttpRequestMessage request, IImageKitClient client) + { + ParamsBase.AddDefaultHeaders(request, client); + foreach (var item in this.HeaderProperties) + { + ParamsBase.AddHeaderElementToRequest(request, item.Key, item.Value); + } + } +} diff --git a/src/Imagekit/Models/Folders/Job/JobGetResponse.cs b/src/Imagekit/Models/Folders/Job/JobGetResponse.cs new file mode 100644 index 00000000..5e20478b --- /dev/null +++ b/src/Imagekit/Models/Folders/Job/JobGetResponse.cs @@ -0,0 +1,125 @@ +using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; +using System.Text.Json; +using System.Text.Json.Serialization; +using Imagekit.Models.Folders.Job.JobGetResponseProperties; + +namespace Imagekit.Models.Folders.Job; + +[JsonConverter(typeof(ModelConverter))] +public sealed record class JobGetResponse : ModelBase, IFromRaw +{ + /// + /// Unique identifier of the bulk job. + /// + public string? JobID + { + get + { + if (!this.Properties.TryGetValue("jobId", out JsonElement element)) + return null; + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions); + } + set + { + this.Properties["jobId"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + /// + /// Unique identifier of the purge request. This will be present only if `purgeCache` + /// is set to `true` in the rename folder API request. + /// + public string? PurgeRequestID + { + get + { + if (!this.Properties.TryGetValue("purgeRequestId", out JsonElement element)) + return null; + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions); + } + set + { + this.Properties["purgeRequestId"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + /// + /// Status of the bulk job. + /// + public ApiEnum? Status + { + get + { + if (!this.Properties.TryGetValue("status", out JsonElement element)) + return null; + + return JsonSerializer.Deserialize?>( + element, + ModelBase.SerializerOptions + ); + } + set + { + this.Properties["status"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + /// + /// Type of the bulk job. + /// + public ApiEnum? Type + { + get + { + if (!this.Properties.TryGetValue("type", out JsonElement element)) + return null; + + return JsonSerializer.Deserialize?>( + element, + ModelBase.SerializerOptions + ); + } + set + { + this.Properties["type"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + public override void Validate() + { + _ = this.JobID; + _ = this.PurgeRequestID; + this.Status?.Validate(); + this.Type?.Validate(); + } + + public JobGetResponse() { } + +#pragma warning disable CS8618 + [SetsRequiredMembers] + JobGetResponse(Dictionary properties) + { + Properties = properties; + } +#pragma warning restore CS8618 + + public static JobGetResponse FromRawUnchecked(Dictionary properties) + { + return new(properties); + } +} diff --git a/src/Imagekit/Models/Folders/Job/JobGetResponseProperties/Status.cs b/src/Imagekit/Models/Folders/Job/JobGetResponseProperties/Status.cs new file mode 100644 index 00000000..21ceca11 --- /dev/null +++ b/src/Imagekit/Models/Folders/Job/JobGetResponseProperties/Status.cs @@ -0,0 +1,46 @@ +using System.Text.Json; +using System.Text.Json.Serialization; +using System = System; + +namespace Imagekit.Models.Folders.Job.JobGetResponseProperties; + +/// +/// Status of the bulk job. +/// +[JsonConverter(typeof(StatusConverter))] +public enum Status +{ + Pending, + Completed, +} + +sealed class StatusConverter : JsonConverter +{ + public override Status Read( + ref Utf8JsonReader reader, + System::Type typeToConvert, + JsonSerializerOptions options + ) + { + return JsonSerializer.Deserialize(ref reader, options) switch + { + "Pending" => Status.Pending, + "Completed" => Status.Completed, + _ => (Status)(-1), + }; + } + + public override void Write(Utf8JsonWriter writer, Status value, JsonSerializerOptions options) + { + JsonSerializer.Serialize( + writer, + value switch + { + Status.Pending => "Pending", + Status.Completed => "Completed", + _ => throw new System::ArgumentOutOfRangeException(nameof(value)), + }, + options + ); + } +} diff --git a/src/Imagekit/Models/Folders/Job/JobGetResponseProperties/Type.cs b/src/Imagekit/Models/Folders/Job/JobGetResponseProperties/Type.cs new file mode 100644 index 00000000..d9f357b4 --- /dev/null +++ b/src/Imagekit/Models/Folders/Job/JobGetResponseProperties/Type.cs @@ -0,0 +1,49 @@ +using System.Text.Json; +using System.Text.Json.Serialization; +using System = System; + +namespace Imagekit.Models.Folders.Job.JobGetResponseProperties; + +/// +/// Type of the bulk job. +/// +[JsonConverter(typeof(TypeConverter))] +public enum Type +{ + CopyFolder, + MoveFolder, + RenameFolder, +} + +sealed class TypeConverter : JsonConverter +{ + public override Type Read( + ref Utf8JsonReader reader, + System::Type typeToConvert, + JsonSerializerOptions options + ) + { + return JsonSerializer.Deserialize(ref reader, options) switch + { + "COPY_FOLDER" => JobGetResponseProperties.Type.CopyFolder, + "MOVE_FOLDER" => JobGetResponseProperties.Type.MoveFolder, + "RENAME_FOLDER" => JobGetResponseProperties.Type.RenameFolder, + _ => (Type)(-1), + }; + } + + public override void Write(Utf8JsonWriter writer, Type value, JsonSerializerOptions options) + { + JsonSerializer.Serialize( + writer, + value switch + { + JobGetResponseProperties.Type.CopyFolder => "COPY_FOLDER", + JobGetResponseProperties.Type.MoveFolder => "MOVE_FOLDER", + JobGetResponseProperties.Type.RenameFolder => "RENAME_FOLDER", + _ => throw new System::ArgumentOutOfRangeException(nameof(value)), + }, + options + ); + } +} diff --git a/src/Imagekit/Models/ImageOverlay.cs b/src/Imagekit/Models/ImageOverlay.cs new file mode 100644 index 00000000..8a1ebd9f --- /dev/null +++ b/src/Imagekit/Models/ImageOverlay.cs @@ -0,0 +1,184 @@ +using System; +using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; +using System.Text.Json; +using System.Text.Json.Serialization; +using Imagekit.Models.ImageOverlayProperties.IntersectionMember1Properties; + +namespace Imagekit.Models; + +[JsonConverter(typeof(ModelConverter))] +public sealed record class ImageOverlay : ModelBase, IFromRaw +{ + public OverlayPosition? Position + { + get + { + if (!this.Properties.TryGetValue("position", out JsonElement element)) + return null; + + return JsonSerializer.Deserialize( + element, + ModelBase.SerializerOptions + ); + } + set + { + this.Properties["position"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + public OverlayTiming? Timing + { + get + { + if (!this.Properties.TryGetValue("timing", out JsonElement element)) + return null; + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions); + } + set + { + this.Properties["timing"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + /// + /// Specifies the relative path to the image used as an overlay. + /// + public required string Input + { + get + { + if (!this.Properties.TryGetValue("input", out JsonElement element)) + throw new ArgumentOutOfRangeException("input", "Missing required argument"); + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions) + ?? throw new ArgumentNullException("input"); + } + set + { + this.Properties["input"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + public JsonElement Type + { + get + { + if (!this.Properties.TryGetValue("type", out JsonElement element)) + throw new ArgumentOutOfRangeException("type", "Missing required argument"); + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions); + } + set + { + this.Properties["type"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + /// + /// The input path can be included in the layer as either `i-{input}` or `ie-{base64_encoded_input}`. + /// By default, the SDK determines the appropriate format automatically. To + /// always use base64 encoding (`ie-{base64}`), set this parameter to `base64`. + /// To always use plain text (`i-{input}`), set it to `plain`. + /// + public ApiEnum? Encoding + { + get + { + if (!this.Properties.TryGetValue("encoding", out JsonElement element)) + return null; + + return JsonSerializer.Deserialize?>( + element, + ModelBase.SerializerOptions + ); + } + set + { + this.Properties["encoding"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + /// + /// Array of transformations to be applied to the overlay image. Supported transformations + /// depends on the base/parent asset. See overlays on [Images](https://imagekit.io/docs/add-overlays-on-images#list-of-supported-image-transformations-in-image-layers) + /// and [Videos](https://imagekit.io/docs/add-overlays-on-videos#list-of-transformations-supported-on-image-overlay). + /// + public List? Transformation + { + get + { + if (!this.Properties.TryGetValue("transformation", out JsonElement element)) + return null; + + return JsonSerializer.Deserialize?>( + element, + ModelBase.SerializerOptions + ); + } + set + { + this.Properties["transformation"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + public static implicit operator BaseOverlay(ImageOverlay imageOverlay) => + new() { Position = imageOverlay.Position, Timing = imageOverlay.Timing }; + + public override void Validate() + { + this.Position?.Validate(); + this.Timing?.Validate(); + _ = this.Input; + this.Encoding?.Validate(); + foreach (var item in this.Transformation ?? []) + { + item.Validate(); + } + } + + public ImageOverlay() + { + this.Type = JsonSerializer.Deserialize("\"image\""); + } + +#pragma warning disable CS8618 + [SetsRequiredMembers] + ImageOverlay(Dictionary properties) + { + Properties = properties; + } +#pragma warning restore CS8618 + + public static ImageOverlay FromRawUnchecked(Dictionary properties) + { + return new(properties); + } + + [SetsRequiredMembers] + public ImageOverlay(string input) + : this() + { + this.Input = input; + } +} diff --git a/src/Imagekit/Models/ImageOverlayProperties/IntersectionMember1.cs b/src/Imagekit/Models/ImageOverlayProperties/IntersectionMember1.cs new file mode 100644 index 00000000..9c13f738 --- /dev/null +++ b/src/Imagekit/Models/ImageOverlayProperties/IntersectionMember1.cs @@ -0,0 +1,140 @@ +using System; +using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; +using System.Text.Json; +using System.Text.Json.Serialization; +using Imagekit.Models.ImageOverlayProperties.IntersectionMember1Properties; + +namespace Imagekit.Models.ImageOverlayProperties; + +[JsonConverter(typeof(ModelConverter))] +public sealed record class IntersectionMember1 : ModelBase, IFromRaw +{ + /// + /// Specifies the relative path to the image used as an overlay. + /// + public required string Input + { + get + { + if (!this.Properties.TryGetValue("input", out JsonElement element)) + throw new ArgumentOutOfRangeException("input", "Missing required argument"); + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions) + ?? throw new ArgumentNullException("input"); + } + set + { + this.Properties["input"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + public JsonElement Type + { + get + { + if (!this.Properties.TryGetValue("type", out JsonElement element)) + throw new ArgumentOutOfRangeException("type", "Missing required argument"); + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions); + } + set + { + this.Properties["type"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + /// + /// The input path can be included in the layer as either `i-{input}` or `ie-{base64_encoded_input}`. + /// By default, the SDK determines the appropriate format automatically. To + /// always use base64 encoding (`ie-{base64}`), set this parameter to `base64`. + /// To always use plain text (`i-{input}`), set it to `plain`. + /// + public ApiEnum? Encoding + { + get + { + if (!this.Properties.TryGetValue("encoding", out JsonElement element)) + return null; + + return JsonSerializer.Deserialize?>( + element, + ModelBase.SerializerOptions + ); + } + set + { + this.Properties["encoding"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + /// + /// Array of transformations to be applied to the overlay image. Supported transformations + /// depends on the base/parent asset. See overlays on [Images](https://imagekit.io/docs/add-overlays-on-images#list-of-supported-image-transformations-in-image-layers) + /// and [Videos](https://imagekit.io/docs/add-overlays-on-videos#list-of-transformations-supported-on-image-overlay). + /// + public List? Transformation + { + get + { + if (!this.Properties.TryGetValue("transformation", out JsonElement element)) + return null; + + return JsonSerializer.Deserialize?>( + element, + ModelBase.SerializerOptions + ); + } + set + { + this.Properties["transformation"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + public override void Validate() + { + _ = this.Input; + this.Encoding?.Validate(); + foreach (var item in this.Transformation ?? []) + { + item.Validate(); + } + } + + public IntersectionMember1() + { + this.Type = JsonSerializer.Deserialize("\"image\""); + } + +#pragma warning disable CS8618 + [SetsRequiredMembers] + IntersectionMember1(Dictionary properties) + { + Properties = properties; + } +#pragma warning restore CS8618 + + public static IntersectionMember1 FromRawUnchecked(Dictionary properties) + { + return new(properties); + } + + [SetsRequiredMembers] + public IntersectionMember1(string input) + : this() + { + this.Input = input; + } +} diff --git a/src/Imagekit/Models/ImageOverlayProperties/IntersectionMember1Properties/Encoding.cs b/src/Imagekit/Models/ImageOverlayProperties/IntersectionMember1Properties/Encoding.cs new file mode 100644 index 00000000..c7efb752 --- /dev/null +++ b/src/Imagekit/Models/ImageOverlayProperties/IntersectionMember1Properties/Encoding.cs @@ -0,0 +1,52 @@ +using System; +using System.Text.Json; +using System.Text.Json.Serialization; + +namespace Imagekit.Models.ImageOverlayProperties.IntersectionMember1Properties; + +/// +/// The input path can be included in the layer as either `i-{input}` or `ie-{base64_encoded_input}`. +/// By default, the SDK determines the appropriate format automatically. To always +/// use base64 encoding (`ie-{base64}`), set this parameter to `base64`. To always +/// use plain text (`i-{input}`), set it to `plain`. +/// +[JsonConverter(typeof(EncodingConverter))] +public enum Encoding +{ + Auto, + Plain, + Base64, +} + +sealed class EncodingConverter : JsonConverter +{ + public override Encoding Read( + ref Utf8JsonReader reader, + Type typeToConvert, + JsonSerializerOptions options + ) + { + return JsonSerializer.Deserialize(ref reader, options) switch + { + "auto" => Encoding.Auto, + "plain" => Encoding.Plain, + "base64" => Encoding.Base64, + _ => (Encoding)(-1), + }; + } + + public override void Write(Utf8JsonWriter writer, Encoding value, JsonSerializerOptions options) + { + JsonSerializer.Serialize( + writer, + value switch + { + Encoding.Auto => "auto", + Encoding.Plain => "plain", + Encoding.Base64 => "base64", + _ => throw new ArgumentOutOfRangeException(nameof(value)), + }, + options + ); + } +} diff --git a/src/Imagekit/Models/Overlay.cs b/src/Imagekit/Models/Overlay.cs new file mode 100644 index 00000000..abc2be63 --- /dev/null +++ b/src/Imagekit/Models/Overlay.cs @@ -0,0 +1,253 @@ +using System; +using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; +using System.Text.Json; +using System.Text.Json.Serialization; +using OverlayVariants = Imagekit.Models.OverlayVariants; + +namespace Imagekit.Models; + +/// +/// Specifies an overlay to be applied on the parent image or video. ImageKit supports +/// overlays including images, text, videos, subtitles, and solid colors. See [Overlay +/// using layers](https://imagekit.io/docs/transformations#overlay-using-layers). +/// +[JsonConverter(typeof(OverlayConverter))] +public abstract record class Overlay +{ + internal Overlay() { } + + public static implicit operator Overlay(TextOverlay value) => + new OverlayVariants::TextOverlay(value); + + public static implicit operator Overlay(ImageOverlay value) => + new OverlayVariants::ImageOverlay(value); + + public static implicit operator Overlay(VideoOverlay value) => + new OverlayVariants::VideoOverlay(value); + + public static implicit operator Overlay(SubtitleOverlay value) => + new OverlayVariants::SubtitleOverlay(value); + + public static implicit operator Overlay(SolidColorOverlay value) => + new OverlayVariants::SolidColorOverlay(value); + + public bool TryPickText([NotNullWhen(true)] out TextOverlay? value) + { + value = (this as OverlayVariants::TextOverlay)?.Value; + return value != null; + } + + public bool TryPickImage([NotNullWhen(true)] out ImageOverlay? value) + { + value = (this as OverlayVariants::ImageOverlay)?.Value; + return value != null; + } + + public bool TryPickVideo([NotNullWhen(true)] out VideoOverlay? value) + { + value = (this as OverlayVariants::VideoOverlay)?.Value; + return value != null; + } + + public bool TryPickSubtitle([NotNullWhen(true)] out SubtitleOverlay? value) + { + value = (this as OverlayVariants::SubtitleOverlay)?.Value; + return value != null; + } + + public bool TryPickSolidColor([NotNullWhen(true)] out SolidColorOverlay? value) + { + value = (this as OverlayVariants::SolidColorOverlay)?.Value; + return value != null; + } + + public void Switch( + Action text, + Action image, + Action video, + Action subtitle, + Action solidColor + ) + { + switch (this) + { + case OverlayVariants::TextOverlay inner: + text(inner); + break; + case OverlayVariants::ImageOverlay inner: + image(inner); + break; + case OverlayVariants::VideoOverlay inner: + video(inner); + break; + case OverlayVariants::SubtitleOverlay inner: + subtitle(inner); + break; + case OverlayVariants::SolidColorOverlay inner: + solidColor(inner); + break; + default: + throw new InvalidOperationException(); + } + } + + public T Match( + Func text, + Func image, + Func video, + Func subtitle, + Func solidColor + ) + { + return this switch + { + OverlayVariants::TextOverlay inner => text(inner), + OverlayVariants::ImageOverlay inner => image(inner), + OverlayVariants::VideoOverlay inner => video(inner), + OverlayVariants::SubtitleOverlay inner => subtitle(inner), + OverlayVariants::SolidColorOverlay inner => solidColor(inner), + _ => throw new InvalidOperationException(), + }; + } + + public abstract void Validate(); +} + +sealed class OverlayConverter : JsonConverter +{ + public override Overlay? Read( + ref Utf8JsonReader reader, + Type typeToConvert, + JsonSerializerOptions options + ) + { + var json = JsonSerializer.Deserialize(ref reader, options); + string? type; + try + { + type = json.GetProperty("type").GetString(); + } + catch + { + type = null; + } + + switch (type) + { + case "text": + { + List exceptions = []; + + try + { + var deserialized = JsonSerializer.Deserialize(json, options); + if (deserialized != null) + { + return new OverlayVariants::TextOverlay(deserialized); + } + } + catch (JsonException e) + { + exceptions.Add(e); + } + + throw new AggregateException(exceptions); + } + case "image": + { + List exceptions = []; + + try + { + var deserialized = JsonSerializer.Deserialize(json, options); + if (deserialized != null) + { + return new OverlayVariants::ImageOverlay(deserialized); + } + } + catch (JsonException e) + { + exceptions.Add(e); + } + + throw new AggregateException(exceptions); + } + case "video": + { + List exceptions = []; + + try + { + var deserialized = JsonSerializer.Deserialize(json, options); + if (deserialized != null) + { + return new OverlayVariants::VideoOverlay(deserialized); + } + } + catch (JsonException e) + { + exceptions.Add(e); + } + + throw new AggregateException(exceptions); + } + case "subtitle": + { + List exceptions = []; + + try + { + var deserialized = JsonSerializer.Deserialize(json, options); + if (deserialized != null) + { + return new OverlayVariants::SubtitleOverlay(deserialized); + } + } + catch (JsonException e) + { + exceptions.Add(e); + } + + throw new AggregateException(exceptions); + } + case "solidColor": + { + List exceptions = []; + + try + { + var deserialized = JsonSerializer.Deserialize(json, options); + if (deserialized != null) + { + return new OverlayVariants::SolidColorOverlay(deserialized); + } + } + catch (JsonException e) + { + exceptions.Add(e); + } + + throw new AggregateException(exceptions); + } + default: + { + throw new Exception(); + } + } + } + + public override void Write(Utf8JsonWriter writer, Overlay value, JsonSerializerOptions options) + { + object variant = value switch + { + OverlayVariants::TextOverlay(var text) => text, + OverlayVariants::ImageOverlay(var image) => image, + OverlayVariants::VideoOverlay(var video) => video, + OverlayVariants::SubtitleOverlay(var subtitle) => subtitle, + OverlayVariants::SolidColorOverlay(var solidColor) => solidColor, + _ => throw new ArgumentOutOfRangeException(nameof(value)), + }; + JsonSerializer.Serialize(writer, variant, options); + } +} diff --git a/src/Imagekit/Models/OverlayPosition.cs b/src/Imagekit/Models/OverlayPosition.cs new file mode 100644 index 00000000..84ba3398 --- /dev/null +++ b/src/Imagekit/Models/OverlayPosition.cs @@ -0,0 +1,106 @@ +using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; +using System.Text.Json; +using System.Text.Json.Serialization; +using Imagekit.Models.OverlayPositionProperties; + +namespace Imagekit.Models; + +[JsonConverter(typeof(ModelConverter))] +public sealed record class OverlayPosition : ModelBase, IFromRaw +{ + /// + /// Specifies the position of the overlay relative to the parent image or video. + /// Maps to `lfo` in the URL. + /// + public ApiEnum? Focus + { + get + { + if (!this.Properties.TryGetValue("focus", out JsonElement element)) + return null; + + return JsonSerializer.Deserialize?>( + element, + ModelBase.SerializerOptions + ); + } + set + { + this.Properties["focus"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + /// + /// Specifies the x-coordinate of the top-left corner of the base asset where + /// the overlay's top-left corner will be positioned. It also accepts arithmetic + /// expressions such as `bw_mul_0.4` or `bw_sub_cw`. Maps to `lx` in the URL. + /// Learn about [Arithmetic expressions](https://imagekit.io/docs/arithmetic-expressions-in-transformations). + /// + public X? X + { + get + { + if (!this.Properties.TryGetValue("x", out JsonElement element)) + return null; + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions); + } + set + { + this.Properties["x"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + /// + /// Specifies the y-coordinate of the top-left corner of the base asset where + /// the overlay's top-left corner will be positioned. It also accepts arithmetic + /// expressions such as `bh_mul_0.4` or `bh_sub_ch`. Maps to `ly` in the URL. + /// Learn about [Arithmetic expressions](https://imagekit.io/docs/arithmetic-expressions-in-transformations). + /// + public Y? Y + { + get + { + if (!this.Properties.TryGetValue("y", out JsonElement element)) + return null; + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions); + } + set + { + this.Properties["y"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + public override void Validate() + { + this.Focus?.Validate(); + this.X?.Validate(); + this.Y?.Validate(); + } + + public OverlayPosition() { } + +#pragma warning disable CS8618 + [SetsRequiredMembers] + OverlayPosition(Dictionary properties) + { + Properties = properties; + } +#pragma warning restore CS8618 + + public static OverlayPosition FromRawUnchecked(Dictionary properties) + { + return new(properties); + } +} diff --git a/src/Imagekit/Models/OverlayPositionProperties/Focus.cs b/src/Imagekit/Models/OverlayPositionProperties/Focus.cs new file mode 100644 index 00000000..9c9b013e --- /dev/null +++ b/src/Imagekit/Models/OverlayPositionProperties/Focus.cs @@ -0,0 +1,68 @@ +using System; +using System.Text.Json; +using System.Text.Json.Serialization; + +namespace Imagekit.Models.OverlayPositionProperties; + +/// +/// Specifies the position of the overlay relative to the parent image or video. +/// Maps to `lfo` in the URL. +/// +[JsonConverter(typeof(FocusConverter))] +public enum Focus +{ + Center, + Top, + Left, + Bottom, + Right, + TopLeft, + TopRight, + BottomLeft, + BottomRight, +} + +sealed class FocusConverter : JsonConverter +{ + public override Focus Read( + ref Utf8JsonReader reader, + Type typeToConvert, + JsonSerializerOptions options + ) + { + return JsonSerializer.Deserialize(ref reader, options) switch + { + "center" => Focus.Center, + "top" => Focus.Top, + "left" => Focus.Left, + "bottom" => Focus.Bottom, + "right" => Focus.Right, + "top_left" => Focus.TopLeft, + "top_right" => Focus.TopRight, + "bottom_left" => Focus.BottomLeft, + "bottom_right" => Focus.BottomRight, + _ => (Focus)(-1), + }; + } + + public override void Write(Utf8JsonWriter writer, Focus value, JsonSerializerOptions options) + { + JsonSerializer.Serialize( + writer, + value switch + { + Focus.Center => "center", + Focus.Top => "top", + Focus.Left => "left", + Focus.Bottom => "bottom", + Focus.Right => "right", + Focus.TopLeft => "top_left", + Focus.TopRight => "top_right", + Focus.BottomLeft => "bottom_left", + Focus.BottomRight => "bottom_right", + _ => throw new ArgumentOutOfRangeException(nameof(value)), + }, + options + ); + } +} diff --git a/src/Imagekit/Models/OverlayPositionProperties/X.cs b/src/Imagekit/Models/OverlayPositionProperties/X.cs new file mode 100644 index 00000000..72a6341a --- /dev/null +++ b/src/Imagekit/Models/OverlayPositionProperties/X.cs @@ -0,0 +1,110 @@ +using System; +using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; +using System.Text.Json; +using System.Text.Json.Serialization; +using XVariants = Imagekit.Models.OverlayPositionProperties.XVariants; + +namespace Imagekit.Models.OverlayPositionProperties; + +/// +/// Specifies the x-coordinate of the top-left corner of the base asset where the +/// overlay's top-left corner will be positioned. It also accepts arithmetic expressions +/// such as `bw_mul_0.4` or `bw_sub_cw`. Maps to `lx` in the URL. Learn about [Arithmetic +/// expressions](https://imagekit.io/docs/arithmetic-expressions-in-transformations). +/// +[JsonConverter(typeof(XConverter))] +public abstract record class X +{ + internal X() { } + + public static implicit operator X(double value) => new XVariants::Double(value); + + public static implicit operator X(string value) => new XVariants::String(value); + + public bool TryPickDouble([NotNullWhen(true)] out double? value) + { + value = (this as XVariants::Double)?.Value; + return value != null; + } + + public bool TryPickString([NotNullWhen(true)] out string? value) + { + value = (this as XVariants::String)?.Value; + return value != null; + } + + public void Switch(Action @double, Action @string) + { + switch (this) + { + case XVariants::Double inner: + @double(inner); + break; + case XVariants::String inner: + @string(inner); + break; + default: + throw new InvalidOperationException(); + } + } + + public T Match(Func @double, Func @string) + { + return this switch + { + XVariants::Double inner => @double(inner), + XVariants::String inner => @string(inner), + _ => throw new InvalidOperationException(), + }; + } + + public abstract void Validate(); +} + +sealed class XConverter : JsonConverter +{ + public override X? Read( + ref Utf8JsonReader reader, + Type typeToConvert, + JsonSerializerOptions options + ) + { + List exceptions = []; + + try + { + return new XVariants::Double(JsonSerializer.Deserialize(ref reader, options)); + } + catch (JsonException e) + { + exceptions.Add(e); + } + + try + { + var deserialized = JsonSerializer.Deserialize(ref reader, options); + if (deserialized != null) + { + return new XVariants::String(deserialized); + } + } + catch (JsonException e) + { + exceptions.Add(e); + } + + throw new AggregateException(exceptions); + } + + public override void Write(Utf8JsonWriter writer, X value, JsonSerializerOptions options) + { + object variant = value switch + { + XVariants::Double(var @double) => @double, + XVariants::String(var @string) => @string, + _ => throw new ArgumentOutOfRangeException(nameof(value)), + }; + JsonSerializer.Serialize(writer, variant, options); + } +} diff --git a/src/Imagekit/Models/OverlayPositionProperties/XVariants/All.cs b/src/Imagekit/Models/OverlayPositionProperties/XVariants/All.cs new file mode 100644 index 00000000..83d285fc --- /dev/null +++ b/src/Imagekit/Models/OverlayPositionProperties/XVariants/All.cs @@ -0,0 +1,21 @@ +namespace Imagekit.Models.OverlayPositionProperties.XVariants; + +public sealed record class Double(double Value) : X, IVariant +{ + public static Double From(double value) + { + return new(value); + } + + public override void Validate() { } +} + +public sealed record class String(string Value) : X, IVariant +{ + public static String From(string value) + { + return new(value); + } + + public override void Validate() { } +} diff --git a/src/Imagekit/Models/OverlayPositionProperties/Y.cs b/src/Imagekit/Models/OverlayPositionProperties/Y.cs new file mode 100644 index 00000000..bde27831 --- /dev/null +++ b/src/Imagekit/Models/OverlayPositionProperties/Y.cs @@ -0,0 +1,110 @@ +using System; +using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; +using System.Text.Json; +using System.Text.Json.Serialization; +using YVariants = Imagekit.Models.OverlayPositionProperties.YVariants; + +namespace Imagekit.Models.OverlayPositionProperties; + +/// +/// Specifies the y-coordinate of the top-left corner of the base asset where the +/// overlay's top-left corner will be positioned. It also accepts arithmetic expressions +/// such as `bh_mul_0.4` or `bh_sub_ch`. Maps to `ly` in the URL. Learn about [Arithmetic +/// expressions](https://imagekit.io/docs/arithmetic-expressions-in-transformations). +/// +[JsonConverter(typeof(YConverter))] +public abstract record class Y +{ + internal Y() { } + + public static implicit operator Y(double value) => new YVariants::Double(value); + + public static implicit operator Y(string value) => new YVariants::String(value); + + public bool TryPickDouble([NotNullWhen(true)] out double? value) + { + value = (this as YVariants::Double)?.Value; + return value != null; + } + + public bool TryPickString([NotNullWhen(true)] out string? value) + { + value = (this as YVariants::String)?.Value; + return value != null; + } + + public void Switch(Action @double, Action @string) + { + switch (this) + { + case YVariants::Double inner: + @double(inner); + break; + case YVariants::String inner: + @string(inner); + break; + default: + throw new InvalidOperationException(); + } + } + + public T Match(Func @double, Func @string) + { + return this switch + { + YVariants::Double inner => @double(inner), + YVariants::String inner => @string(inner), + _ => throw new InvalidOperationException(), + }; + } + + public abstract void Validate(); +} + +sealed class YConverter : JsonConverter +{ + public override Y? Read( + ref Utf8JsonReader reader, + Type typeToConvert, + JsonSerializerOptions options + ) + { + List exceptions = []; + + try + { + return new YVariants::Double(JsonSerializer.Deserialize(ref reader, options)); + } + catch (JsonException e) + { + exceptions.Add(e); + } + + try + { + var deserialized = JsonSerializer.Deserialize(ref reader, options); + if (deserialized != null) + { + return new YVariants::String(deserialized); + } + } + catch (JsonException e) + { + exceptions.Add(e); + } + + throw new AggregateException(exceptions); + } + + public override void Write(Utf8JsonWriter writer, Y value, JsonSerializerOptions options) + { + object variant = value switch + { + YVariants::Double(var @double) => @double, + YVariants::String(var @string) => @string, + _ => throw new ArgumentOutOfRangeException(nameof(value)), + }; + JsonSerializer.Serialize(writer, variant, options); + } +} diff --git a/src/Imagekit/Models/OverlayPositionProperties/YVariants/All.cs b/src/Imagekit/Models/OverlayPositionProperties/YVariants/All.cs new file mode 100644 index 00000000..b123e666 --- /dev/null +++ b/src/Imagekit/Models/OverlayPositionProperties/YVariants/All.cs @@ -0,0 +1,21 @@ +namespace Imagekit.Models.OverlayPositionProperties.YVariants; + +public sealed record class Double(double Value) : Y, IVariant +{ + public static Double From(double value) + { + return new(value); + } + + public override void Validate() { } +} + +public sealed record class String(string Value) : Y, IVariant +{ + public static String From(string value) + { + return new(value); + } + + public override void Validate() { } +} diff --git a/src/Imagekit/Models/OverlayTiming.cs b/src/Imagekit/Models/OverlayTiming.cs new file mode 100644 index 00000000..c559ab9d --- /dev/null +++ b/src/Imagekit/Models/OverlayTiming.cs @@ -0,0 +1,106 @@ +using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; +using System.Text.Json; +using System.Text.Json.Serialization; +using Imagekit.Models.OverlayTimingProperties; + +namespace Imagekit.Models; + +[JsonConverter(typeof(ModelConverter))] +public sealed record class OverlayTiming : ModelBase, IFromRaw +{ + /// + /// Specifies the duration (in seconds) during which the overlay should appear + /// on the base video. Accepts a positive number up to two decimal places (e.g., + /// `20` or `20.50`) and arithmetic expressions such as `bdu_mul_0.4` or `bdu_sub_idu`. + /// Applies only if the base asset is a video. Maps to `ldu` in the URL. + /// + public Duration? Duration + { + get + { + if (!this.Properties.TryGetValue("duration", out JsonElement element)) + return null; + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions); + } + set + { + this.Properties["duration"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + /// + /// Specifies the end time (in seconds) for when the overlay should disappear + /// from the base video. If both end and duration are provided, duration is ignored. + /// Accepts a positive number up to two decimal places (e.g., `20` or `20.50`) + /// and arithmetic expressions such as `bdu_mul_0.4` or `bdu_sub_idu`. Applies + /// only if the base asset is a video. Maps to `leo` in the URL. + /// + public End? End + { + get + { + if (!this.Properties.TryGetValue("end", out JsonElement element)) + return null; + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions); + } + set + { + this.Properties["end"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + /// + /// Specifies the start time (in seconds) for when the overlay should appear on + /// the base video. Accepts a positive number up to two decimal places (e.g., + /// `20` or `20.50`) and arithmetic expressions such as `bdu_mul_0.4` or `bdu_sub_idu`. + /// Applies only if the base asset is a video. Maps to `lso` in the URL. + /// + public Start? Start + { + get + { + if (!this.Properties.TryGetValue("start", out JsonElement element)) + return null; + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions); + } + set + { + this.Properties["start"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + public override void Validate() + { + this.Duration?.Validate(); + this.End?.Validate(); + this.Start?.Validate(); + } + + public OverlayTiming() { } + +#pragma warning disable CS8618 + [SetsRequiredMembers] + OverlayTiming(Dictionary properties) + { + Properties = properties; + } +#pragma warning restore CS8618 + + public static OverlayTiming FromRawUnchecked(Dictionary properties) + { + return new(properties); + } +} diff --git a/src/Imagekit/Models/OverlayTimingProperties/Duration.cs b/src/Imagekit/Models/OverlayTimingProperties/Duration.cs new file mode 100644 index 00000000..c835f546 --- /dev/null +++ b/src/Imagekit/Models/OverlayTimingProperties/Duration.cs @@ -0,0 +1,118 @@ +using System; +using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; +using System.Text.Json; +using System.Text.Json.Serialization; +using DurationVariants = Imagekit.Models.OverlayTimingProperties.DurationVariants; + +namespace Imagekit.Models.OverlayTimingProperties; + +/// +/// Specifies the duration (in seconds) during which the overlay should appear on +/// the base video. Accepts a positive number up to two decimal places (e.g., `20` +/// or `20.50`) and arithmetic expressions such as `bdu_mul_0.4` or `bdu_sub_idu`. +/// Applies only if the base asset is a video. Maps to `ldu` in the URL. +/// +[JsonConverter(typeof(DurationConverter))] +public abstract record class Duration +{ + internal Duration() { } + + public static implicit operator Duration(double value) => new DurationVariants::Double(value); + + public static implicit operator Duration(string value) => new DurationVariants::String(value); + + public bool TryPickDouble([NotNullWhen(true)] out double? value) + { + value = (this as DurationVariants::Double)?.Value; + return value != null; + } + + public bool TryPickString([NotNullWhen(true)] out string? value) + { + value = (this as DurationVariants::String)?.Value; + return value != null; + } + + public void Switch( + Action @double, + Action @string + ) + { + switch (this) + { + case DurationVariants::Double inner: + @double(inner); + break; + case DurationVariants::String inner: + @string(inner); + break; + default: + throw new InvalidOperationException(); + } + } + + public T Match( + Func @double, + Func @string + ) + { + return this switch + { + DurationVariants::Double inner => @double(inner), + DurationVariants::String inner => @string(inner), + _ => throw new InvalidOperationException(), + }; + } + + public abstract void Validate(); +} + +sealed class DurationConverter : JsonConverter +{ + public override Duration? Read( + ref Utf8JsonReader reader, + Type typeToConvert, + JsonSerializerOptions options + ) + { + List exceptions = []; + + try + { + return new DurationVariants::Double( + JsonSerializer.Deserialize(ref reader, options) + ); + } + catch (JsonException e) + { + exceptions.Add(e); + } + + try + { + var deserialized = JsonSerializer.Deserialize(ref reader, options); + if (deserialized != null) + { + return new DurationVariants::String(deserialized); + } + } + catch (JsonException e) + { + exceptions.Add(e); + } + + throw new AggregateException(exceptions); + } + + public override void Write(Utf8JsonWriter writer, Duration value, JsonSerializerOptions options) + { + object variant = value switch + { + DurationVariants::Double(var @double) => @double, + DurationVariants::String(var @string) => @string, + _ => throw new ArgumentOutOfRangeException(nameof(value)), + }; + JsonSerializer.Serialize(writer, variant, options); + } +} diff --git a/src/Imagekit/Models/OverlayTimingProperties/DurationVariants/All.cs b/src/Imagekit/Models/OverlayTimingProperties/DurationVariants/All.cs new file mode 100644 index 00000000..c4645813 --- /dev/null +++ b/src/Imagekit/Models/OverlayTimingProperties/DurationVariants/All.cs @@ -0,0 +1,21 @@ +namespace Imagekit.Models.OverlayTimingProperties.DurationVariants; + +public sealed record class Double(double Value) : Duration, IVariant +{ + public static Double From(double value) + { + return new(value); + } + + public override void Validate() { } +} + +public sealed record class String(string Value) : Duration, IVariant +{ + public static String From(string value) + { + return new(value); + } + + public override void Validate() { } +} diff --git a/src/Imagekit/Models/OverlayTimingProperties/End.cs b/src/Imagekit/Models/OverlayTimingProperties/End.cs new file mode 100644 index 00000000..00434c3d --- /dev/null +++ b/src/Imagekit/Models/OverlayTimingProperties/End.cs @@ -0,0 +1,111 @@ +using System; +using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; +using System.Text.Json; +using System.Text.Json.Serialization; +using EndVariants = Imagekit.Models.OverlayTimingProperties.EndVariants; + +namespace Imagekit.Models.OverlayTimingProperties; + +/// +/// Specifies the end time (in seconds) for when the overlay should disappear from +/// the base video. If both end and duration are provided, duration is ignored. Accepts +/// a positive number up to two decimal places (e.g., `20` or `20.50`) and arithmetic +/// expressions such as `bdu_mul_0.4` or `bdu_sub_idu`. Applies only if the base asset +/// is a video. Maps to `leo` in the URL. +/// +[JsonConverter(typeof(EndConverter))] +public abstract record class End +{ + internal End() { } + + public static implicit operator End(double value) => new EndVariants::Double(value); + + public static implicit operator End(string value) => new EndVariants::String(value); + + public bool TryPickDouble([NotNullWhen(true)] out double? value) + { + value = (this as EndVariants::Double)?.Value; + return value != null; + } + + public bool TryPickString([NotNullWhen(true)] out string? value) + { + value = (this as EndVariants::String)?.Value; + return value != null; + } + + public void Switch(Action @double, Action @string) + { + switch (this) + { + case EndVariants::Double inner: + @double(inner); + break; + case EndVariants::String inner: + @string(inner); + break; + default: + throw new InvalidOperationException(); + } + } + + public T Match(Func @double, Func @string) + { + return this switch + { + EndVariants::Double inner => @double(inner), + EndVariants::String inner => @string(inner), + _ => throw new InvalidOperationException(), + }; + } + + public abstract void Validate(); +} + +sealed class EndConverter : JsonConverter +{ + public override End? Read( + ref Utf8JsonReader reader, + Type typeToConvert, + JsonSerializerOptions options + ) + { + List exceptions = []; + + try + { + return new EndVariants::Double(JsonSerializer.Deserialize(ref reader, options)); + } + catch (JsonException e) + { + exceptions.Add(e); + } + + try + { + var deserialized = JsonSerializer.Deserialize(ref reader, options); + if (deserialized != null) + { + return new EndVariants::String(deserialized); + } + } + catch (JsonException e) + { + exceptions.Add(e); + } + + throw new AggregateException(exceptions); + } + + public override void Write(Utf8JsonWriter writer, End value, JsonSerializerOptions options) + { + object variant = value switch + { + EndVariants::Double(var @double) => @double, + EndVariants::String(var @string) => @string, + _ => throw new ArgumentOutOfRangeException(nameof(value)), + }; + JsonSerializer.Serialize(writer, variant, options); + } +} diff --git a/src/Imagekit/Models/OverlayTimingProperties/EndVariants/All.cs b/src/Imagekit/Models/OverlayTimingProperties/EndVariants/All.cs new file mode 100644 index 00000000..58912819 --- /dev/null +++ b/src/Imagekit/Models/OverlayTimingProperties/EndVariants/All.cs @@ -0,0 +1,21 @@ +namespace Imagekit.Models.OverlayTimingProperties.EndVariants; + +public sealed record class Double(double Value) : End, IVariant +{ + public static Double From(double value) + { + return new(value); + } + + public override void Validate() { } +} + +public sealed record class String(string Value) : End, IVariant +{ + public static String From(string value) + { + return new(value); + } + + public override void Validate() { } +} diff --git a/src/Imagekit/Models/OverlayTimingProperties/Start.cs b/src/Imagekit/Models/OverlayTimingProperties/Start.cs new file mode 100644 index 00000000..dd7eeacc --- /dev/null +++ b/src/Imagekit/Models/OverlayTimingProperties/Start.cs @@ -0,0 +1,115 @@ +using System; +using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; +using System.Text.Json; +using System.Text.Json.Serialization; +using StartVariants = Imagekit.Models.OverlayTimingProperties.StartVariants; + +namespace Imagekit.Models.OverlayTimingProperties; + +/// +/// Specifies the start time (in seconds) for when the overlay should appear on the +/// base video. Accepts a positive number up to two decimal places (e.g., `20` or +/// `20.50`) and arithmetic expressions such as `bdu_mul_0.4` or `bdu_sub_idu`. Applies +/// only if the base asset is a video. Maps to `lso` in the URL. +/// +[JsonConverter(typeof(StartConverter))] +public abstract record class Start +{ + internal Start() { } + + public static implicit operator Start(double value) => new StartVariants::Double(value); + + public static implicit operator Start(string value) => new StartVariants::String(value); + + public bool TryPickDouble([NotNullWhen(true)] out double? value) + { + value = (this as StartVariants::Double)?.Value; + return value != null; + } + + public bool TryPickString([NotNullWhen(true)] out string? value) + { + value = (this as StartVariants::String)?.Value; + return value != null; + } + + public void Switch(Action @double, Action @string) + { + switch (this) + { + case StartVariants::Double inner: + @double(inner); + break; + case StartVariants::String inner: + @string(inner); + break; + default: + throw new InvalidOperationException(); + } + } + + public T Match( + Func @double, + Func @string + ) + { + return this switch + { + StartVariants::Double inner => @double(inner), + StartVariants::String inner => @string(inner), + _ => throw new InvalidOperationException(), + }; + } + + public abstract void Validate(); +} + +sealed class StartConverter : JsonConverter +{ + public override Start? Read( + ref Utf8JsonReader reader, + Type typeToConvert, + JsonSerializerOptions options + ) + { + List exceptions = []; + + try + { + return new StartVariants::Double( + JsonSerializer.Deserialize(ref reader, options) + ); + } + catch (JsonException e) + { + exceptions.Add(e); + } + + try + { + var deserialized = JsonSerializer.Deserialize(ref reader, options); + if (deserialized != null) + { + return new StartVariants::String(deserialized); + } + } + catch (JsonException e) + { + exceptions.Add(e); + } + + throw new AggregateException(exceptions); + } + + public override void Write(Utf8JsonWriter writer, Start value, JsonSerializerOptions options) + { + object variant = value switch + { + StartVariants::Double(var @double) => @double, + StartVariants::String(var @string) => @string, + _ => throw new ArgumentOutOfRangeException(nameof(value)), + }; + JsonSerializer.Serialize(writer, variant, options); + } +} diff --git a/src/Imagekit/Models/OverlayTimingProperties/StartVariants/All.cs b/src/Imagekit/Models/OverlayTimingProperties/StartVariants/All.cs new file mode 100644 index 00000000..6554819a --- /dev/null +++ b/src/Imagekit/Models/OverlayTimingProperties/StartVariants/All.cs @@ -0,0 +1,21 @@ +namespace Imagekit.Models.OverlayTimingProperties.StartVariants; + +public sealed record class Double(double Value) : Start, IVariant +{ + public static Double From(double value) + { + return new(value); + } + + public override void Validate() { } +} + +public sealed record class String(string Value) : Start, IVariant +{ + public static String From(string value) + { + return new(value); + } + + public override void Validate() { } +} diff --git a/src/Imagekit/Models/OverlayVariants/All.cs b/src/Imagekit/Models/OverlayVariants/All.cs new file mode 100644 index 00000000..3ff187c8 --- /dev/null +++ b/src/Imagekit/Models/OverlayVariants/All.cs @@ -0,0 +1,78 @@ +using Models = Imagekit.Models; + +namespace Imagekit.Models.OverlayVariants; + +public sealed record class TextOverlay(Models::TextOverlay Value) + : Models::Overlay, + IVariant +{ + public static TextOverlay From(Models::TextOverlay value) + { + return new(value); + } + + public override void Validate() + { + this.Value.Validate(); + } +} + +public sealed record class ImageOverlay(Models::ImageOverlay Value) + : Models::Overlay, + IVariant +{ + public static ImageOverlay From(Models::ImageOverlay value) + { + return new(value); + } + + public override void Validate() + { + this.Value.Validate(); + } +} + +public sealed record class VideoOverlay(Models::VideoOverlay Value) + : Models::Overlay, + IVariant +{ + public static VideoOverlay From(Models::VideoOverlay value) + { + return new(value); + } + + public override void Validate() + { + this.Value.Validate(); + } +} + +public sealed record class SubtitleOverlay(Models::SubtitleOverlay Value) + : Models::Overlay, + IVariant +{ + public static SubtitleOverlay From(Models::SubtitleOverlay value) + { + return new(value); + } + + public override void Validate() + { + this.Value.Validate(); + } +} + +public sealed record class SolidColorOverlay(Models::SolidColorOverlay Value) + : Models::Overlay, + IVariant +{ + public static SolidColorOverlay From(Models::SolidColorOverlay value) + { + return new(value); + } + + public override void Validate() + { + this.Value.Validate(); + } +} diff --git a/src/Imagekit/Models/SolidColorOverlay.cs b/src/Imagekit/Models/SolidColorOverlay.cs new file mode 100644 index 00000000..7bd01c08 --- /dev/null +++ b/src/Imagekit/Models/SolidColorOverlay.cs @@ -0,0 +1,158 @@ +using System; +using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; +using System.Text.Json; +using System.Text.Json.Serialization; + +namespace Imagekit.Models; + +[JsonConverter(typeof(ModelConverter))] +public sealed record class SolidColorOverlay : ModelBase, IFromRaw +{ + public OverlayPosition? Position + { + get + { + if (!this.Properties.TryGetValue("position", out JsonElement element)) + return null; + + return JsonSerializer.Deserialize( + element, + ModelBase.SerializerOptions + ); + } + set + { + this.Properties["position"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + public OverlayTiming? Timing + { + get + { + if (!this.Properties.TryGetValue("timing", out JsonElement element)) + return null; + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions); + } + set + { + this.Properties["timing"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + /// + /// Specifies the color of the block using an RGB hex code (e.g., `FF0000`), + /// an RGBA code (e.g., `FFAABB50`), or a color name (e.g., `red`). If an 8-character + /// value is provided, the last two characters represent the opacity level (from + /// `00` for 0.00 to `99` for 0.99). + /// + public required string Color + { + get + { + if (!this.Properties.TryGetValue("color", out JsonElement element)) + throw new ArgumentOutOfRangeException("color", "Missing required argument"); + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions) + ?? throw new ArgumentNullException("color"); + } + set + { + this.Properties["color"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + public JsonElement Type + { + get + { + if (!this.Properties.TryGetValue("type", out JsonElement element)) + throw new ArgumentOutOfRangeException("type", "Missing required argument"); + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions); + } + set + { + this.Properties["type"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + /// + /// Control width and height of the solid color overlay. Supported transformations + /// depend on the base/parent asset. See overlays on [Images](https://imagekit.io/docs/add-overlays-on-images#apply-transformation-on-solid-color-overlay) + /// and [Videos](https://imagekit.io/docs/add-overlays-on-videos#apply-transformations-on-solid-color-block-overlay). + /// + public List? Transformation + { + get + { + if (!this.Properties.TryGetValue("transformation", out JsonElement element)) + return null; + + return JsonSerializer.Deserialize?>( + element, + ModelBase.SerializerOptions + ); + } + set + { + this.Properties["transformation"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + public static implicit operator BaseOverlay(SolidColorOverlay solidColorOverlay) => + new() { Position = solidColorOverlay.Position, Timing = solidColorOverlay.Timing }; + + public override void Validate() + { + this.Position?.Validate(); + this.Timing?.Validate(); + _ = this.Color; + foreach (var item in this.Transformation ?? []) + { + item.Validate(); + } + } + + public SolidColorOverlay() + { + this.Type = JsonSerializer.Deserialize("\"solidColor\""); + } + +#pragma warning disable CS8618 + [SetsRequiredMembers] + SolidColorOverlay(Dictionary properties) + { + Properties = properties; + } +#pragma warning restore CS8618 + + public static SolidColorOverlay FromRawUnchecked(Dictionary properties) + { + return new(properties); + } + + [SetsRequiredMembers] + public SolidColorOverlay(string color) + : this() + { + this.Color = color; + } +} diff --git a/src/Imagekit/Models/SolidColorOverlayProperties/IntersectionMember1.cs b/src/Imagekit/Models/SolidColorOverlayProperties/IntersectionMember1.cs new file mode 100644 index 00000000..57ddef26 --- /dev/null +++ b/src/Imagekit/Models/SolidColorOverlayProperties/IntersectionMember1.cs @@ -0,0 +1,114 @@ +using System; +using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; +using System.Text.Json; +using System.Text.Json.Serialization; + +namespace Imagekit.Models.SolidColorOverlayProperties; + +[JsonConverter(typeof(ModelConverter))] +public sealed record class IntersectionMember1 : ModelBase, IFromRaw +{ + /// + /// Specifies the color of the block using an RGB hex code (e.g., `FF0000`), + /// an RGBA code (e.g., `FFAABB50`), or a color name (e.g., `red`). If an 8-character + /// value is provided, the last two characters represent the opacity level (from + /// `00` for 0.00 to `99` for 0.99). + /// + public required string Color + { + get + { + if (!this.Properties.TryGetValue("color", out JsonElement element)) + throw new ArgumentOutOfRangeException("color", "Missing required argument"); + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions) + ?? throw new ArgumentNullException("color"); + } + set + { + this.Properties["color"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + public JsonElement Type + { + get + { + if (!this.Properties.TryGetValue("type", out JsonElement element)) + throw new ArgumentOutOfRangeException("type", "Missing required argument"); + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions); + } + set + { + this.Properties["type"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + /// + /// Control width and height of the solid color overlay. Supported transformations + /// depend on the base/parent asset. See overlays on [Images](https://imagekit.io/docs/add-overlays-on-images#apply-transformation-on-solid-color-overlay) + /// and [Videos](https://imagekit.io/docs/add-overlays-on-videos#apply-transformations-on-solid-color-block-overlay). + /// + public List? Transformation + { + get + { + if (!this.Properties.TryGetValue("transformation", out JsonElement element)) + return null; + + return JsonSerializer.Deserialize?>( + element, + ModelBase.SerializerOptions + ); + } + set + { + this.Properties["transformation"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + public override void Validate() + { + _ = this.Color; + foreach (var item in this.Transformation ?? []) + { + item.Validate(); + } + } + + public IntersectionMember1() + { + this.Type = JsonSerializer.Deserialize("\"solidColor\""); + } + +#pragma warning disable CS8618 + [SetsRequiredMembers] + IntersectionMember1(Dictionary properties) + { + Properties = properties; + } +#pragma warning restore CS8618 + + public static IntersectionMember1 FromRawUnchecked(Dictionary properties) + { + return new(properties); + } + + [SetsRequiredMembers] + public IntersectionMember1(string color) + : this() + { + this.Color = color; + } +} diff --git a/src/Imagekit/Models/SolidColorOverlayTransformation.cs b/src/Imagekit/Models/SolidColorOverlayTransformation.cs new file mode 100644 index 00000000..68937764 --- /dev/null +++ b/src/Imagekit/Models/SolidColorOverlayTransformation.cs @@ -0,0 +1,174 @@ +using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; +using System.Text.Json; +using System.Text.Json.Serialization; +using Imagekit.Models.SolidColorOverlayTransformationProperties; + +namespace Imagekit.Models; + +[JsonConverter(typeof(ModelConverter))] +public sealed record class SolidColorOverlayTransformation + : ModelBase, + IFromRaw +{ + /// + /// Specifies the transparency level of the solid color overlay. Accepts integers + /// from `1` to `9`. + /// + public double? Alpha + { + get + { + if (!this.Properties.TryGetValue("alpha", out JsonElement element)) + return null; + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions); + } + set + { + this.Properties["alpha"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + /// + /// Specifies the background color of the solid color overlay. Accepts an RGB + /// hex code (e.g., `FF0000`), an RGBA code (e.g., `FFAABB50`), or a color name. + /// + public string? Background + { + get + { + if (!this.Properties.TryGetValue("background", out JsonElement element)) + return null; + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions); + } + set + { + this.Properties["background"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + /// + /// Creates a linear gradient with two colors. Pass `true` for a default gradient, + /// or provide a string for a custom gradient. Only works if the base asset is + /// an image. See [gradient](https://imagekit.io/docs/effects-and-enhancements#gradient---e-gradient). + /// + public Gradient? Gradient + { + get + { + if (!this.Properties.TryGetValue("gradient", out JsonElement element)) + return null; + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions); + } + set + { + this.Properties["gradient"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + /// + /// Controls the height of the solid color overlay. Accepts a numeric value or + /// an arithmetic expression. Learn about [arithmetic expressions](https://imagekit.io/docs/arithmetic-expressions-in-transformations). + /// + public Height? Height + { + get + { + if (!this.Properties.TryGetValue("height", out JsonElement element)) + return null; + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions); + } + set + { + this.Properties["height"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + /// + /// Specifies the corner radius of the solid color overlay. Set to `max` for + /// circular or oval shape. See [radius](https://imagekit.io/docs/effects-and-enhancements#radius---r). + /// + public Radius? Radius + { + get + { + if (!this.Properties.TryGetValue("radius", out JsonElement element)) + return null; + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions); + } + set + { + this.Properties["radius"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + /// + /// Controls the width of the solid color overlay. Accepts a numeric value or + /// an arithmetic expression (e.g., `bw_mul_0.2` or `bh_div_2`). Learn about [arithmetic + /// expressions](https://imagekit.io/docs/arithmetic-expressions-in-transformations). + /// + public Width? Width + { + get + { + if (!this.Properties.TryGetValue("width", out JsonElement element)) + return null; + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions); + } + set + { + this.Properties["width"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + public override void Validate() + { + _ = this.Alpha; + _ = this.Background; + this.Gradient?.Validate(); + this.Height?.Validate(); + this.Radius?.Validate(); + this.Width?.Validate(); + } + + public SolidColorOverlayTransformation() { } + +#pragma warning disable CS8618 + [SetsRequiredMembers] + SolidColorOverlayTransformation(Dictionary properties) + { + Properties = properties; + } +#pragma warning restore CS8618 + + public static SolidColorOverlayTransformation FromRawUnchecked( + Dictionary properties + ) + { + return new(properties); + } +} diff --git a/src/Imagekit/Models/SolidColorOverlayTransformationProperties/Gradient.cs b/src/Imagekit/Models/SolidColorOverlayTransformationProperties/Gradient.cs new file mode 100644 index 00000000..d54f5053 --- /dev/null +++ b/src/Imagekit/Models/SolidColorOverlayTransformationProperties/Gradient.cs @@ -0,0 +1,115 @@ +using System; +using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; +using System.Text.Json; +using System.Text.Json.Serialization; +using GradientVariants = Imagekit.Models.SolidColorOverlayTransformationProperties.GradientVariants; + +namespace Imagekit.Models.SolidColorOverlayTransformationProperties; + +/// +/// Creates a linear gradient with two colors. Pass `true` for a default gradient, +/// or provide a string for a custom gradient. Only works if the base asset is an +/// image. See [gradient](https://imagekit.io/docs/effects-and-enhancements#gradient---e-gradient). +/// +[JsonConverter(typeof(GradientConverter))] +public abstract record class Gradient +{ + internal Gradient() { } + + public static implicit operator Gradient(string value) => new GradientVariants::String(value); + + public bool TryPickTrue([NotNullWhen(true)] out JsonElement? value) + { + value = (this as GradientVariants::True)?.Value; + return value != null; + } + + public bool TryPickString([NotNullWhen(true)] out string? value) + { + value = (this as GradientVariants::String)?.Value; + return value != null; + } + + public void Switch( + Action true1, + Action @string + ) + { + switch (this) + { + case GradientVariants::True inner: + true1(inner); + break; + case GradientVariants::String inner: + @string(inner); + break; + default: + throw new InvalidOperationException(); + } + } + + public T Match( + Func true1, + Func @string + ) + { + return this switch + { + GradientVariants::True inner => true1(inner), + GradientVariants::String inner => @string(inner), + _ => throw new InvalidOperationException(), + }; + } + + public abstract void Validate(); +} + +sealed class GradientConverter : JsonConverter +{ + public override Gradient? Read( + ref Utf8JsonReader reader, + Type typeToConvert, + JsonSerializerOptions options + ) + { + List exceptions = []; + + try + { + return new GradientVariants::True( + JsonSerializer.Deserialize(ref reader, options) + ); + } + catch (JsonException e) + { + exceptions.Add(e); + } + + try + { + var deserialized = JsonSerializer.Deserialize(ref reader, options); + if (deserialized != null) + { + return new GradientVariants::String(deserialized); + } + } + catch (JsonException e) + { + exceptions.Add(e); + } + + throw new AggregateException(exceptions); + } + + public override void Write(Utf8JsonWriter writer, Gradient value, JsonSerializerOptions options) + { + object variant = value switch + { + GradientVariants::True(var true1) => true1, + GradientVariants::String(var @string) => @string, + _ => throw new ArgumentOutOfRangeException(nameof(value)), + }; + JsonSerializer.Serialize(writer, variant, options); + } +} diff --git a/src/Imagekit/Models/SolidColorOverlayTransformationProperties/GradientVariants/All.cs b/src/Imagekit/Models/SolidColorOverlayTransformationProperties/GradientVariants/All.cs new file mode 100644 index 00000000..4f3289f0 --- /dev/null +++ b/src/Imagekit/Models/SolidColorOverlayTransformationProperties/GradientVariants/All.cs @@ -0,0 +1,23 @@ +using System.Text.Json; + +namespace Imagekit.Models.SolidColorOverlayTransformationProperties.GradientVariants; + +public sealed record class True(JsonElement Value) : Gradient, IVariant +{ + public static True From(JsonElement value) + { + return new(value); + } + + public override void Validate() { } +} + +public sealed record class String(string Value) : Gradient, IVariant +{ + public static String From(string value) + { + return new(value); + } + + public override void Validate() { } +} diff --git a/src/Imagekit/Models/SolidColorOverlayTransformationProperties/Height.cs b/src/Imagekit/Models/SolidColorOverlayTransformationProperties/Height.cs new file mode 100644 index 00000000..a1edb6a4 --- /dev/null +++ b/src/Imagekit/Models/SolidColorOverlayTransformationProperties/Height.cs @@ -0,0 +1,116 @@ +using System; +using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; +using System.Text.Json; +using System.Text.Json.Serialization; +using HeightVariants = Imagekit.Models.SolidColorOverlayTransformationProperties.HeightVariants; + +namespace Imagekit.Models.SolidColorOverlayTransformationProperties; + +/// +/// Controls the height of the solid color overlay. Accepts a numeric value or an +/// arithmetic expression. Learn about [arithmetic expressions](https://imagekit.io/docs/arithmetic-expressions-in-transformations). +/// +[JsonConverter(typeof(HeightConverter))] +public abstract record class Height +{ + internal Height() { } + + public static implicit operator Height(double value) => new HeightVariants::Double(value); + + public static implicit operator Height(string value) => new HeightVariants::String(value); + + public bool TryPickDouble([NotNullWhen(true)] out double? value) + { + value = (this as HeightVariants::Double)?.Value; + return value != null; + } + + public bool TryPickString([NotNullWhen(true)] out string? value) + { + value = (this as HeightVariants::String)?.Value; + return value != null; + } + + public void Switch( + Action @double, + Action @string + ) + { + switch (this) + { + case HeightVariants::Double inner: + @double(inner); + break; + case HeightVariants::String inner: + @string(inner); + break; + default: + throw new InvalidOperationException(); + } + } + + public T Match( + Func @double, + Func @string + ) + { + return this switch + { + HeightVariants::Double inner => @double(inner), + HeightVariants::String inner => @string(inner), + _ => throw new InvalidOperationException(), + }; + } + + public abstract void Validate(); +} + +sealed class HeightConverter : JsonConverter +{ + public override Height? Read( + ref Utf8JsonReader reader, + Type typeToConvert, + JsonSerializerOptions options + ) + { + List exceptions = []; + + try + { + return new HeightVariants::Double( + JsonSerializer.Deserialize(ref reader, options) + ); + } + catch (JsonException e) + { + exceptions.Add(e); + } + + try + { + var deserialized = JsonSerializer.Deserialize(ref reader, options); + if (deserialized != null) + { + return new HeightVariants::String(deserialized); + } + } + catch (JsonException e) + { + exceptions.Add(e); + } + + throw new AggregateException(exceptions); + } + + public override void Write(Utf8JsonWriter writer, Height value, JsonSerializerOptions options) + { + object variant = value switch + { + HeightVariants::Double(var @double) => @double, + HeightVariants::String(var @string) => @string, + _ => throw new ArgumentOutOfRangeException(nameof(value)), + }; + JsonSerializer.Serialize(writer, variant, options); + } +} diff --git a/src/Imagekit/Models/SolidColorOverlayTransformationProperties/HeightVariants/All.cs b/src/Imagekit/Models/SolidColorOverlayTransformationProperties/HeightVariants/All.cs new file mode 100644 index 00000000..7964bb15 --- /dev/null +++ b/src/Imagekit/Models/SolidColorOverlayTransformationProperties/HeightVariants/All.cs @@ -0,0 +1,21 @@ +namespace Imagekit.Models.SolidColorOverlayTransformationProperties.HeightVariants; + +public sealed record class Double(double Value) : Height, IVariant +{ + public static Double From(double value) + { + return new(value); + } + + public override void Validate() { } +} + +public sealed record class String(string Value) : Height, IVariant +{ + public static String From(string value) + { + return new(value); + } + + public override void Validate() { } +} diff --git a/src/Imagekit/Models/SolidColorOverlayTransformationProperties/Radius.cs b/src/Imagekit/Models/SolidColorOverlayTransformationProperties/Radius.cs new file mode 100644 index 00000000..fd7074ff --- /dev/null +++ b/src/Imagekit/Models/SolidColorOverlayTransformationProperties/Radius.cs @@ -0,0 +1,106 @@ +using System; +using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; +using System.Text.Json; +using System.Text.Json.Serialization; +using RadiusVariants = Imagekit.Models.SolidColorOverlayTransformationProperties.RadiusVariants; + +namespace Imagekit.Models.SolidColorOverlayTransformationProperties; + +/// +/// Specifies the corner radius of the solid color overlay. Set to `max` for circular +/// or oval shape. See [radius](https://imagekit.io/docs/effects-and-enhancements#radius---r). +/// +[JsonConverter(typeof(RadiusConverter))] +public abstract record class Radius +{ + internal Radius() { } + + public static implicit operator Radius(double value) => new RadiusVariants::Double(value); + + public bool TryPickDouble([NotNullWhen(true)] out double? value) + { + value = (this as RadiusVariants::Double)?.Value; + return value != null; + } + + public bool TryPickMax([NotNullWhen(true)] out JsonElement? value) + { + value = (this as RadiusVariants::Max)?.Value; + return value != null; + } + + public void Switch(Action @double, Action max) + { + switch (this) + { + case RadiusVariants::Double inner: + @double(inner); + break; + case RadiusVariants::Max inner: + max(inner); + break; + default: + throw new InvalidOperationException(); + } + } + + public T Match(Func @double, Func max) + { + return this switch + { + RadiusVariants::Double inner => @double(inner), + RadiusVariants::Max inner => max(inner), + _ => throw new InvalidOperationException(), + }; + } + + public abstract void Validate(); +} + +sealed class RadiusConverter : JsonConverter +{ + public override Radius? Read( + ref Utf8JsonReader reader, + Type typeToConvert, + JsonSerializerOptions options + ) + { + List exceptions = []; + + try + { + return new RadiusVariants::Max( + JsonSerializer.Deserialize(ref reader, options) + ); + } + catch (JsonException e) + { + exceptions.Add(e); + } + + try + { + return new RadiusVariants::Double( + JsonSerializer.Deserialize(ref reader, options) + ); + } + catch (JsonException e) + { + exceptions.Add(e); + } + + throw new AggregateException(exceptions); + } + + public override void Write(Utf8JsonWriter writer, Radius value, JsonSerializerOptions options) + { + object variant = value switch + { + RadiusVariants::Double(var @double) => @double, + RadiusVariants::Max(var max) => max, + _ => throw new ArgumentOutOfRangeException(nameof(value)), + }; + JsonSerializer.Serialize(writer, variant, options); + } +} diff --git a/src/Imagekit/Models/SolidColorOverlayTransformationProperties/RadiusVariants/All.cs b/src/Imagekit/Models/SolidColorOverlayTransformationProperties/RadiusVariants/All.cs new file mode 100644 index 00000000..027d6797 --- /dev/null +++ b/src/Imagekit/Models/SolidColorOverlayTransformationProperties/RadiusVariants/All.cs @@ -0,0 +1,23 @@ +using System.Text.Json; + +namespace Imagekit.Models.SolidColorOverlayTransformationProperties.RadiusVariants; + +public sealed record class Double(double Value) : Radius, IVariant +{ + public static Double From(double value) + { + return new(value); + } + + public override void Validate() { } +} + +public sealed record class Max(JsonElement Value) : Radius, IVariant +{ + public static Max From(JsonElement value) + { + return new(value); + } + + public override void Validate() { } +} diff --git a/src/Imagekit/Models/SolidColorOverlayTransformationProperties/Width.cs b/src/Imagekit/Models/SolidColorOverlayTransformationProperties/Width.cs new file mode 100644 index 00000000..689da93c --- /dev/null +++ b/src/Imagekit/Models/SolidColorOverlayTransformationProperties/Width.cs @@ -0,0 +1,113 @@ +using System; +using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; +using System.Text.Json; +using System.Text.Json.Serialization; +using WidthVariants = Imagekit.Models.SolidColorOverlayTransformationProperties.WidthVariants; + +namespace Imagekit.Models.SolidColorOverlayTransformationProperties; + +/// +/// Controls the width of the solid color overlay. Accepts a numeric value or an arithmetic +/// expression (e.g., `bw_mul_0.2` or `bh_div_2`). Learn about [arithmetic expressions](https://imagekit.io/docs/arithmetic-expressions-in-transformations). +/// +[JsonConverter(typeof(WidthConverter))] +public abstract record class Width +{ + internal Width() { } + + public static implicit operator Width(double value) => new WidthVariants::Double(value); + + public static implicit operator Width(string value) => new WidthVariants::String(value); + + public bool TryPickDouble([NotNullWhen(true)] out double? value) + { + value = (this as WidthVariants::Double)?.Value; + return value != null; + } + + public bool TryPickString([NotNullWhen(true)] out string? value) + { + value = (this as WidthVariants::String)?.Value; + return value != null; + } + + public void Switch(Action @double, Action @string) + { + switch (this) + { + case WidthVariants::Double inner: + @double(inner); + break; + case WidthVariants::String inner: + @string(inner); + break; + default: + throw new InvalidOperationException(); + } + } + + public T Match( + Func @double, + Func @string + ) + { + return this switch + { + WidthVariants::Double inner => @double(inner), + WidthVariants::String inner => @string(inner), + _ => throw new InvalidOperationException(), + }; + } + + public abstract void Validate(); +} + +sealed class WidthConverter : JsonConverter +{ + public override Width? Read( + ref Utf8JsonReader reader, + Type typeToConvert, + JsonSerializerOptions options + ) + { + List exceptions = []; + + try + { + return new WidthVariants::Double( + JsonSerializer.Deserialize(ref reader, options) + ); + } + catch (JsonException e) + { + exceptions.Add(e); + } + + try + { + var deserialized = JsonSerializer.Deserialize(ref reader, options); + if (deserialized != null) + { + return new WidthVariants::String(deserialized); + } + } + catch (JsonException e) + { + exceptions.Add(e); + } + + throw new AggregateException(exceptions); + } + + public override void Write(Utf8JsonWriter writer, Width value, JsonSerializerOptions options) + { + object variant = value switch + { + WidthVariants::Double(var @double) => @double, + WidthVariants::String(var @string) => @string, + _ => throw new ArgumentOutOfRangeException(nameof(value)), + }; + JsonSerializer.Serialize(writer, variant, options); + } +} diff --git a/src/Imagekit/Models/SolidColorOverlayTransformationProperties/WidthVariants/All.cs b/src/Imagekit/Models/SolidColorOverlayTransformationProperties/WidthVariants/All.cs new file mode 100644 index 00000000..6c5afda6 --- /dev/null +++ b/src/Imagekit/Models/SolidColorOverlayTransformationProperties/WidthVariants/All.cs @@ -0,0 +1,21 @@ +namespace Imagekit.Models.SolidColorOverlayTransformationProperties.WidthVariants; + +public sealed record class Double(double Value) : Width, IVariant +{ + public static Double From(double value) + { + return new(value); + } + + public override void Validate() { } +} + +public sealed record class String(string Value) : Width, IVariant +{ + public static String From(string value) + { + return new(value); + } + + public override void Validate() { } +} diff --git a/src/Imagekit/Models/SrcOptions.cs b/src/Imagekit/Models/SrcOptions.cs new file mode 100644 index 00000000..d524abc3 --- /dev/null +++ b/src/Imagekit/Models/SrcOptions.cs @@ -0,0 +1,230 @@ +using System; +using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; +using System.Text.Json; +using System.Text.Json.Serialization; + +namespace Imagekit.Models; + +/// +/// Options for generating ImageKit URLs with transformations. See the [Transformations guide](https://imagekit.io/docs/transformations). +/// +[JsonConverter(typeof(ModelConverter))] +public sealed record class SrcOptions : ModelBase, IFromRaw +{ + /// + /// Accepts a relative or absolute path of the resource. If a relative path is + /// provided, it is appended to the `urlEndpoint`. If an absolute path is provided, + /// `urlEndpoint` is ignored. + /// + public required string Src + { + get + { + if (!this.Properties.TryGetValue("src", out JsonElement element)) + throw new ArgumentOutOfRangeException("src", "Missing required argument"); + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions) + ?? throw new ArgumentNullException("src"); + } + set + { + this.Properties["src"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + /// + /// Get your urlEndpoint from the [ImageKit dashboard](https://imagekit.io/dashboard/url-endpoints). + /// + public required string URLEndpoint + { + get + { + if (!this.Properties.TryGetValue("urlEndpoint", out JsonElement element)) + throw new ArgumentOutOfRangeException("urlEndpoint", "Missing required argument"); + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions) + ?? throw new ArgumentNullException("urlEndpoint"); + } + set + { + this.Properties["urlEndpoint"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + /// + /// When you want the signed URL to expire, specified in seconds. If `expiresIn` + /// is anything above 0, the URL will always be signed even if `signed` is set + /// to false. If not specified and `signed` is `true`, the signed URL will not + /// expire (valid indefinitely). + /// + /// Example: Setting `expiresIn: 3600` will make the URL expire 1 hour from generation + /// time. After the expiry time, the signed URL will no longer be valid and ImageKit + /// will return a 401 Unauthorized status code. + /// + /// [Learn more](https://imagekit.io/docs/media-delivery-basic-security#how-to-generate-signed-urls). + /// + public double? ExpiresIn + { + get + { + if (!this.Properties.TryGetValue("expiresIn", out JsonElement element)) + return null; + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions); + } + set + { + this.Properties["expiresIn"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + /// + /// These are additional query parameters that you want to add to the final URL. + /// They can be any query parameters and not necessarily related to ImageKit. + /// This is especially useful if you want to add a versioning parameter to your + /// URLs. + /// + public Dictionary? QueryParameters + { + get + { + if (!this.Properties.TryGetValue("queryParameters", out JsonElement element)) + return null; + + return JsonSerializer.Deserialize?>( + element, + ModelBase.SerializerOptions + ); + } + set + { + this.Properties["queryParameters"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + /// + /// Whether to sign the URL or not. Set this to `true` if you want to generate + /// a signed URL. If `signed` is `true` and `expiresIn` is not specified, the + /// signed URL will not expire (valid indefinitely). Note: If `expiresIn` is set + /// to any value above 0, the URL will always be signed regardless of this setting. + /// [Learn more](https://imagekit.io/docs/media-delivery-basic-security#how-to-generate-signed-urls). + /// + public bool? Signed + { + get + { + if (!this.Properties.TryGetValue("signed", out JsonElement element)) + return null; + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions); + } + set + { + this.Properties["signed"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + /// + /// An array of objects specifying the transformations to be applied in the URL. + /// If more than one transformation is specified, they are applied in the order + /// they are specified as chained transformations. See [Chained transformations](https://imagekit.io/docs/transformations#chained-transformations). + /// + public List? Transformation + { + get + { + if (!this.Properties.TryGetValue("transformation", out JsonElement element)) + return null; + + return JsonSerializer.Deserialize?>( + element, + ModelBase.SerializerOptions + ); + } + set + { + this.Properties["transformation"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + /// + /// By default, the transformation string is added as a query parameter in the + /// URL, e.g., `?tr=w-100,h-100`. If you want to add the transformation string + /// in the path of the URL, set this to `path`. Learn more in the [Transformations + /// guide](https://imagekit.io/docs/transformations). + /// + public ApiEnum? TransformationPosition + { + get + { + if (!this.Properties.TryGetValue("transformationPosition", out JsonElement element)) + return null; + + return JsonSerializer.Deserialize?>( + element, + ModelBase.SerializerOptions + ); + } + set + { + this.Properties["transformationPosition"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + public override void Validate() + { + _ = this.Src; + _ = this.URLEndpoint; + _ = this.ExpiresIn; + if (this.QueryParameters != null) + { + foreach (var item in this.QueryParameters.Values) + { + _ = item; + } + } + _ = this.Signed; + foreach (var item in this.Transformation ?? []) + { + item.Validate(); + } + this.TransformationPosition?.Validate(); + } + + public SrcOptions() { } + +#pragma warning disable CS8618 + [SetsRequiredMembers] + SrcOptions(Dictionary properties) + { + Properties = properties; + } +#pragma warning restore CS8618 + + public static SrcOptions FromRawUnchecked(Dictionary properties) + { + return new(properties); + } +} diff --git a/src/Imagekit/Models/StreamingResolution.cs b/src/Imagekit/Models/StreamingResolution.cs new file mode 100644 index 00000000..b6978e9e --- /dev/null +++ b/src/Imagekit/Models/StreamingResolution.cs @@ -0,0 +1,65 @@ +using System; +using System.Text.Json; +using System.Text.Json.Serialization; + +namespace Imagekit.Models; + +/// +/// Available streaming resolutions for [adaptive bitrate streaming](https://imagekit.io/docs/adaptive-bitrate-streaming) +/// +[JsonConverter(typeof(StreamingResolutionConverter))] +public enum StreamingResolution +{ + v240, + v360, + v480, + v720, + v1080, + v1440, + v2160, +} + +sealed class StreamingResolutionConverter : JsonConverter +{ + public override StreamingResolution Read( + ref Utf8JsonReader reader, + Type typeToConvert, + JsonSerializerOptions options + ) + { + return JsonSerializer.Deserialize(ref reader, options) switch + { + "240" => StreamingResolution.v240, + "360" => StreamingResolution.v360, + "480" => StreamingResolution.v480, + "720" => StreamingResolution.v720, + "1080" => StreamingResolution.v1080, + "1440" => StreamingResolution.v1440, + "2160" => StreamingResolution.v2160, + _ => (StreamingResolution)(-1), + }; + } + + public override void Write( + Utf8JsonWriter writer, + StreamingResolution value, + JsonSerializerOptions options + ) + { + JsonSerializer.Serialize( + writer, + value switch + { + StreamingResolution.v240 => "240", + StreamingResolution.v360 => "360", + StreamingResolution.v480 => "480", + StreamingResolution.v720 => "720", + StreamingResolution.v1080 => "1080", + StreamingResolution.v1440 => "1440", + StreamingResolution.v2160 => "2160", + _ => throw new ArgumentOutOfRangeException(nameof(value)), + }, + options + ); + } +} diff --git a/src/Imagekit/Models/SubtitleOverlay.cs b/src/Imagekit/Models/SubtitleOverlay.cs new file mode 100644 index 00000000..eee00a3c --- /dev/null +++ b/src/Imagekit/Models/SubtitleOverlay.cs @@ -0,0 +1,182 @@ +using System; +using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; +using System.Text.Json; +using System.Text.Json.Serialization; +using Imagekit.Models.SubtitleOverlayProperties.IntersectionMember1Properties; + +namespace Imagekit.Models; + +[JsonConverter(typeof(ModelConverter))] +public sealed record class SubtitleOverlay : ModelBase, IFromRaw +{ + public OverlayPosition? Position + { + get + { + if (!this.Properties.TryGetValue("position", out JsonElement element)) + return null; + + return JsonSerializer.Deserialize( + element, + ModelBase.SerializerOptions + ); + } + set + { + this.Properties["position"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + public OverlayTiming? Timing + { + get + { + if (!this.Properties.TryGetValue("timing", out JsonElement element)) + return null; + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions); + } + set + { + this.Properties["timing"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + /// + /// Specifies the relative path to the subtitle file used as an overlay. + /// + public required string Input + { + get + { + if (!this.Properties.TryGetValue("input", out JsonElement element)) + throw new ArgumentOutOfRangeException("input", "Missing required argument"); + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions) + ?? throw new ArgumentNullException("input"); + } + set + { + this.Properties["input"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + public JsonElement Type + { + get + { + if (!this.Properties.TryGetValue("type", out JsonElement element)) + throw new ArgumentOutOfRangeException("type", "Missing required argument"); + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions); + } + set + { + this.Properties["type"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + /// + /// The input path can be included in the layer as either `i-{input}` or `ie-{base64_encoded_input}`. + /// By default, the SDK determines the appropriate format automatically. To + /// always use base64 encoding (`ie-{base64}`), set this parameter to `base64`. + /// To always use plain text (`i-{input}`), set it to `plain`. + /// + public ApiEnum? Encoding + { + get + { + if (!this.Properties.TryGetValue("encoding", out JsonElement element)) + return null; + + return JsonSerializer.Deserialize?>( + element, + ModelBase.SerializerOptions + ); + } + set + { + this.Properties["encoding"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + /// + /// Control styling of the subtitle. See [Styling subtitles](https://imagekit.io/docs/add-overlays-on-videos#styling-controls-for-subtitles-layer). + /// + public List? Transformation + { + get + { + if (!this.Properties.TryGetValue("transformation", out JsonElement element)) + return null; + + return JsonSerializer.Deserialize?>( + element, + ModelBase.SerializerOptions + ); + } + set + { + this.Properties["transformation"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + public static implicit operator BaseOverlay(SubtitleOverlay subtitleOverlay) => + new() { Position = subtitleOverlay.Position, Timing = subtitleOverlay.Timing }; + + public override void Validate() + { + this.Position?.Validate(); + this.Timing?.Validate(); + _ = this.Input; + this.Encoding?.Validate(); + foreach (var item in this.Transformation ?? []) + { + item.Validate(); + } + } + + public SubtitleOverlay() + { + this.Type = JsonSerializer.Deserialize("\"subtitle\""); + } + +#pragma warning disable CS8618 + [SetsRequiredMembers] + SubtitleOverlay(Dictionary properties) + { + Properties = properties; + } +#pragma warning restore CS8618 + + public static SubtitleOverlay FromRawUnchecked(Dictionary properties) + { + return new(properties); + } + + [SetsRequiredMembers] + public SubtitleOverlay(string input) + : this() + { + this.Input = input; + } +} diff --git a/src/Imagekit/Models/SubtitleOverlayProperties/IntersectionMember1.cs b/src/Imagekit/Models/SubtitleOverlayProperties/IntersectionMember1.cs new file mode 100644 index 00000000..87bc57c5 --- /dev/null +++ b/src/Imagekit/Models/SubtitleOverlayProperties/IntersectionMember1.cs @@ -0,0 +1,138 @@ +using System; +using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; +using System.Text.Json; +using System.Text.Json.Serialization; +using Imagekit.Models.SubtitleOverlayProperties.IntersectionMember1Properties; + +namespace Imagekit.Models.SubtitleOverlayProperties; + +[JsonConverter(typeof(ModelConverter))] +public sealed record class IntersectionMember1 : ModelBase, IFromRaw +{ + /// + /// Specifies the relative path to the subtitle file used as an overlay. + /// + public required string Input + { + get + { + if (!this.Properties.TryGetValue("input", out JsonElement element)) + throw new ArgumentOutOfRangeException("input", "Missing required argument"); + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions) + ?? throw new ArgumentNullException("input"); + } + set + { + this.Properties["input"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + public JsonElement Type + { + get + { + if (!this.Properties.TryGetValue("type", out JsonElement element)) + throw new ArgumentOutOfRangeException("type", "Missing required argument"); + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions); + } + set + { + this.Properties["type"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + /// + /// The input path can be included in the layer as either `i-{input}` or `ie-{base64_encoded_input}`. + /// By default, the SDK determines the appropriate format automatically. To + /// always use base64 encoding (`ie-{base64}`), set this parameter to `base64`. + /// To always use plain text (`i-{input}`), set it to `plain`. + /// + public ApiEnum? Encoding + { + get + { + if (!this.Properties.TryGetValue("encoding", out JsonElement element)) + return null; + + return JsonSerializer.Deserialize?>( + element, + ModelBase.SerializerOptions + ); + } + set + { + this.Properties["encoding"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + /// + /// Control styling of the subtitle. See [Styling subtitles](https://imagekit.io/docs/add-overlays-on-videos#styling-controls-for-subtitles-layer). + /// + public List? Transformation + { + get + { + if (!this.Properties.TryGetValue("transformation", out JsonElement element)) + return null; + + return JsonSerializer.Deserialize?>( + element, + ModelBase.SerializerOptions + ); + } + set + { + this.Properties["transformation"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + public override void Validate() + { + _ = this.Input; + this.Encoding?.Validate(); + foreach (var item in this.Transformation ?? []) + { + item.Validate(); + } + } + + public IntersectionMember1() + { + this.Type = JsonSerializer.Deserialize("\"subtitle\""); + } + +#pragma warning disable CS8618 + [SetsRequiredMembers] + IntersectionMember1(Dictionary properties) + { + Properties = properties; + } +#pragma warning restore CS8618 + + public static IntersectionMember1 FromRawUnchecked(Dictionary properties) + { + return new(properties); + } + + [SetsRequiredMembers] + public IntersectionMember1(string input) + : this() + { + this.Input = input; + } +} diff --git a/src/Imagekit/Models/SubtitleOverlayProperties/IntersectionMember1Properties/Encoding.cs b/src/Imagekit/Models/SubtitleOverlayProperties/IntersectionMember1Properties/Encoding.cs new file mode 100644 index 00000000..e1dda803 --- /dev/null +++ b/src/Imagekit/Models/SubtitleOverlayProperties/IntersectionMember1Properties/Encoding.cs @@ -0,0 +1,52 @@ +using System; +using System.Text.Json; +using System.Text.Json.Serialization; + +namespace Imagekit.Models.SubtitleOverlayProperties.IntersectionMember1Properties; + +/// +/// The input path can be included in the layer as either `i-{input}` or `ie-{base64_encoded_input}`. +/// By default, the SDK determines the appropriate format automatically. To always +/// use base64 encoding (`ie-{base64}`), set this parameter to `base64`. To always +/// use plain text (`i-{input}`), set it to `plain`. +/// +[JsonConverter(typeof(EncodingConverter))] +public enum Encoding +{ + Auto, + Plain, + Base64, +} + +sealed class EncodingConverter : JsonConverter +{ + public override Encoding Read( + ref Utf8JsonReader reader, + Type typeToConvert, + JsonSerializerOptions options + ) + { + return JsonSerializer.Deserialize(ref reader, options) switch + { + "auto" => Encoding.Auto, + "plain" => Encoding.Plain, + "base64" => Encoding.Base64, + _ => (Encoding)(-1), + }; + } + + public override void Write(Utf8JsonWriter writer, Encoding value, JsonSerializerOptions options) + { + JsonSerializer.Serialize( + writer, + value switch + { + Encoding.Auto => "auto", + Encoding.Plain => "plain", + Encoding.Base64 => "base64", + _ => throw new ArgumentOutOfRangeException(nameof(value)), + }, + options + ); + } +} diff --git a/src/Imagekit/Models/SubtitleOverlayTransformation.cs b/src/Imagekit/Models/SubtitleOverlayTransformation.cs new file mode 100644 index 00000000..912ded35 --- /dev/null +++ b/src/Imagekit/Models/SubtitleOverlayTransformation.cs @@ -0,0 +1,220 @@ +using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; +using System.Text.Json; +using System.Text.Json.Serialization; +using Imagekit.Models.SubtitleOverlayTransformationProperties; + +namespace Imagekit.Models; + +/// +/// Subtitle styling options. [Learn more](https://imagekit.io/docs/add-overlays-on-videos#styling-controls-for-subtitles-layer) +/// from the docs. +/// +[JsonConverter(typeof(ModelConverter))] +public sealed record class SubtitleOverlayTransformation + : ModelBase, + IFromRaw +{ + /// + /// Specifies the subtitle background color using a standard color name, an RGB + /// color code (e.g., FF0000), or an RGBA color code (e.g., FFAABB50). + /// + /// [Subtitle styling options](https://imagekit.io/docs/add-overlays-on-videos#styling-controls-for-subtitles-layer) + /// + public string? Background + { + get + { + if (!this.Properties.TryGetValue("background", out JsonElement element)) + return null; + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions); + } + set + { + this.Properties["background"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + /// + /// Sets the font color of the subtitle text using a standard color name, an RGB + /// color code (e.g., FF0000), or an RGBA color code (e.g., FFAABB50). + /// + /// [Subtitle styling options](https://imagekit.io/docs/add-overlays-on-videos#styling-controls-for-subtitles-layer) + /// + public string? Color + { + get + { + if (!this.Properties.TryGetValue("color", out JsonElement element)) + return null; + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions); + } + set + { + this.Properties["color"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + /// + /// Font family for subtitles. Refer to the [supported fonts](https://imagekit.io/docs/add-overlays-on-images#supported-text-font-list). + /// + public string? FontFamily + { + get + { + if (!this.Properties.TryGetValue("fontFamily", out JsonElement element)) + return null; + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions); + } + set + { + this.Properties["fontFamily"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + /// + /// Sets the font outline of the subtitle text. Requires the outline width (an + /// integer) and the outline color (as an RGB color code, RGBA color code, or + /// standard web color name) separated by an underscore. Example: `fol-2_blue` + /// (outline width of 2px and outline color blue), `fol-2_A1CCDD` (outline width + /// of 2px and outline color `#A1CCDD`) and `fol-2_A1CCDD50` (outline width of + /// 2px and outline color `#A1CCDD` at 50% opacity). + /// + /// [Subtitle styling options](https://imagekit.io/docs/add-overlays-on-videos#styling-controls-for-subtitles-layer) + /// + public string? FontOutline + { + get + { + if (!this.Properties.TryGetValue("fontOutline", out JsonElement element)) + return null; + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions); + } + set + { + this.Properties["fontOutline"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + /// + /// Sets the font shadow for the subtitle text. Requires the shadow color (as + /// an RGB color code, RGBA color code, or standard web color name) and shadow + /// indent (an integer) separated by an underscore. Example: `fsh-blue_2` (shadow + /// color blue, indent of 2px), `fsh-A1CCDD_3` (shadow color `#A1CCDD`, indent + /// of 3px), `fsh-A1CCDD50_3` (shadow color `#A1CCDD` at 50% opacity, indent + /// of 3px). + /// + /// [Subtitle styling options](https://imagekit.io/docs/add-overlays-on-videos#styling-controls-for-subtitles-layer) + /// + public string? FontShadow + { + get + { + if (!this.Properties.TryGetValue("fontShadow", out JsonElement element)) + return null; + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions); + } + set + { + this.Properties["fontShadow"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + /// + /// Sets the font size of subtitle text. + /// + /// [Subtitle styling options](https://imagekit.io/docs/add-overlays-on-videos#styling-controls-for-subtitles-layer) + /// + public double? FontSize + { + get + { + if (!this.Properties.TryGetValue("fontSize", out JsonElement element)) + return null; + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions); + } + set + { + this.Properties["fontSize"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + /// + /// Sets the typography style of the subtitle text. Supports values are `b` for + /// bold, `i` for italics, and `b_i` for bold with italics. + /// + /// [Subtitle styling options](https://imagekit.io/docs/add-overlays-on-videos#styling-controls-for-subtitles-layer) + /// + public ApiEnum? Typography + { + get + { + if (!this.Properties.TryGetValue("typography", out JsonElement element)) + return null; + + return JsonSerializer.Deserialize?>( + element, + ModelBase.SerializerOptions + ); + } + set + { + this.Properties["typography"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + public override void Validate() + { + _ = this.Background; + _ = this.Color; + _ = this.FontFamily; + _ = this.FontOutline; + _ = this.FontShadow; + _ = this.FontSize; + this.Typography?.Validate(); + } + + public SubtitleOverlayTransformation() { } + +#pragma warning disable CS8618 + [SetsRequiredMembers] + SubtitleOverlayTransformation(Dictionary properties) + { + Properties = properties; + } +#pragma warning restore CS8618 + + public static SubtitleOverlayTransformation FromRawUnchecked( + Dictionary properties + ) + { + return new(properties); + } +} diff --git a/src/Imagekit/Models/SubtitleOverlayTransformationProperties/Typography.cs b/src/Imagekit/Models/SubtitleOverlayTransformationProperties/Typography.cs new file mode 100644 index 00000000..4cef3c66 --- /dev/null +++ b/src/Imagekit/Models/SubtitleOverlayTransformationProperties/Typography.cs @@ -0,0 +1,56 @@ +using System; +using System.Text.Json; +using System.Text.Json.Serialization; + +namespace Imagekit.Models.SubtitleOverlayTransformationProperties; + +/// +/// Sets the typography style of the subtitle text. Supports values are `b` for bold, +/// `i` for italics, and `b_i` for bold with italics. +/// +/// [Subtitle styling options](https://imagekit.io/docs/add-overlays-on-videos#styling-controls-for-subtitles-layer) +/// +[JsonConverter(typeof(TypographyConverter))] +public enum Typography +{ + B, + I, + BI, +} + +sealed class TypographyConverter : JsonConverter +{ + public override Typography Read( + ref Utf8JsonReader reader, + Type typeToConvert, + JsonSerializerOptions options + ) + { + return JsonSerializer.Deserialize(ref reader, options) switch + { + "b" => Typography.B, + "i" => Typography.I, + "b_i" => Typography.BI, + _ => (Typography)(-1), + }; + } + + public override void Write( + Utf8JsonWriter writer, + Typography value, + JsonSerializerOptions options + ) + { + JsonSerializer.Serialize( + writer, + value switch + { + Typography.B => "b", + Typography.I => "i", + Typography.BI => "b_i", + _ => throw new ArgumentOutOfRangeException(nameof(value)), + }, + options + ); + } +} diff --git a/src/Imagekit/Models/TextOverlay.cs b/src/Imagekit/Models/TextOverlay.cs new file mode 100644 index 00000000..60fe68c8 --- /dev/null +++ b/src/Imagekit/Models/TextOverlay.cs @@ -0,0 +1,183 @@ +using System; +using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; +using System.Text.Json; +using System.Text.Json.Serialization; +using Imagekit.Models.TextOverlayProperties.IntersectionMember1Properties; + +namespace Imagekit.Models; + +[JsonConverter(typeof(ModelConverter))] +public sealed record class TextOverlay : ModelBase, IFromRaw +{ + public OverlayPosition? Position + { + get + { + if (!this.Properties.TryGetValue("position", out JsonElement element)) + return null; + + return JsonSerializer.Deserialize( + element, + ModelBase.SerializerOptions + ); + } + set + { + this.Properties["position"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + public OverlayTiming? Timing + { + get + { + if (!this.Properties.TryGetValue("timing", out JsonElement element)) + return null; + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions); + } + set + { + this.Properties["timing"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + /// + /// Specifies the text to be displayed in the overlay. The SDK automatically handles + /// special characters and encoding. + /// + public required string Text + { + get + { + if (!this.Properties.TryGetValue("text", out JsonElement element)) + throw new ArgumentOutOfRangeException("text", "Missing required argument"); + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions) + ?? throw new ArgumentNullException("text"); + } + set + { + this.Properties["text"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + public JsonElement Type + { + get + { + if (!this.Properties.TryGetValue("type", out JsonElement element)) + throw new ArgumentOutOfRangeException("type", "Missing required argument"); + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions); + } + set + { + this.Properties["type"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + /// + /// Text can be included in the layer as either `i-{input}` (plain text) or `ie-{base64_encoded_input}` + /// (base64). By default, the SDK selects the appropriate format based on the + /// input text. To always use base64 (`ie-{base64}`), set this parameter to + /// `base64`. To always use plain text (`i-{input}`), set it to `plain`. + /// + public ApiEnum? Encoding + { + get + { + if (!this.Properties.TryGetValue("encoding", out JsonElement element)) + return null; + + return JsonSerializer.Deserialize?>( + element, + ModelBase.SerializerOptions + ); + } + set + { + this.Properties["encoding"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + /// + /// Control styling of the text overlay. See [Text overlays](https://imagekit.io/docs/add-overlays-on-images#text-overlay). + /// + public List? Transformation + { + get + { + if (!this.Properties.TryGetValue("transformation", out JsonElement element)) + return null; + + return JsonSerializer.Deserialize?>( + element, + ModelBase.SerializerOptions + ); + } + set + { + this.Properties["transformation"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + public static implicit operator BaseOverlay(TextOverlay textOverlay) => + new() { Position = textOverlay.Position, Timing = textOverlay.Timing }; + + public override void Validate() + { + this.Position?.Validate(); + this.Timing?.Validate(); + _ = this.Text; + this.Encoding?.Validate(); + foreach (var item in this.Transformation ?? []) + { + item.Validate(); + } + } + + public TextOverlay() + { + this.Type = JsonSerializer.Deserialize("\"text\""); + } + +#pragma warning disable CS8618 + [SetsRequiredMembers] + TextOverlay(Dictionary properties) + { + Properties = properties; + } +#pragma warning restore CS8618 + + public static TextOverlay FromRawUnchecked(Dictionary properties) + { + return new(properties); + } + + [SetsRequiredMembers] + public TextOverlay(string text) + : this() + { + this.Text = text; + } +} diff --git a/src/Imagekit/Models/TextOverlayProperties/IntersectionMember1.cs b/src/Imagekit/Models/TextOverlayProperties/IntersectionMember1.cs new file mode 100644 index 00000000..9af23151 --- /dev/null +++ b/src/Imagekit/Models/TextOverlayProperties/IntersectionMember1.cs @@ -0,0 +1,139 @@ +using System; +using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; +using System.Text.Json; +using System.Text.Json.Serialization; +using Imagekit.Models.TextOverlayProperties.IntersectionMember1Properties; + +namespace Imagekit.Models.TextOverlayProperties; + +[JsonConverter(typeof(ModelConverter))] +public sealed record class IntersectionMember1 : ModelBase, IFromRaw +{ + /// + /// Specifies the text to be displayed in the overlay. The SDK automatically handles + /// special characters and encoding. + /// + public required string Text + { + get + { + if (!this.Properties.TryGetValue("text", out JsonElement element)) + throw new ArgumentOutOfRangeException("text", "Missing required argument"); + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions) + ?? throw new ArgumentNullException("text"); + } + set + { + this.Properties["text"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + public JsonElement Type + { + get + { + if (!this.Properties.TryGetValue("type", out JsonElement element)) + throw new ArgumentOutOfRangeException("type", "Missing required argument"); + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions); + } + set + { + this.Properties["type"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + /// + /// Text can be included in the layer as either `i-{input}` (plain text) or `ie-{base64_encoded_input}` + /// (base64). By default, the SDK selects the appropriate format based on the + /// input text. To always use base64 (`ie-{base64}`), set this parameter to + /// `base64`. To always use plain text (`i-{input}`), set it to `plain`. + /// + public ApiEnum? Encoding + { + get + { + if (!this.Properties.TryGetValue("encoding", out JsonElement element)) + return null; + + return JsonSerializer.Deserialize?>( + element, + ModelBase.SerializerOptions + ); + } + set + { + this.Properties["encoding"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + /// + /// Control styling of the text overlay. See [Text overlays](https://imagekit.io/docs/add-overlays-on-images#text-overlay). + /// + public List? Transformation + { + get + { + if (!this.Properties.TryGetValue("transformation", out JsonElement element)) + return null; + + return JsonSerializer.Deserialize?>( + element, + ModelBase.SerializerOptions + ); + } + set + { + this.Properties["transformation"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + public override void Validate() + { + _ = this.Text; + this.Encoding?.Validate(); + foreach (var item in this.Transformation ?? []) + { + item.Validate(); + } + } + + public IntersectionMember1() + { + this.Type = JsonSerializer.Deserialize("\"text\""); + } + +#pragma warning disable CS8618 + [SetsRequiredMembers] + IntersectionMember1(Dictionary properties) + { + Properties = properties; + } +#pragma warning restore CS8618 + + public static IntersectionMember1 FromRawUnchecked(Dictionary properties) + { + return new(properties); + } + + [SetsRequiredMembers] + public IntersectionMember1(string text) + : this() + { + this.Text = text; + } +} diff --git a/src/Imagekit/Models/TextOverlayProperties/IntersectionMember1Properties/Encoding.cs b/src/Imagekit/Models/TextOverlayProperties/IntersectionMember1Properties/Encoding.cs new file mode 100644 index 00000000..74ed2a83 --- /dev/null +++ b/src/Imagekit/Models/TextOverlayProperties/IntersectionMember1Properties/Encoding.cs @@ -0,0 +1,52 @@ +using System; +using System.Text.Json; +using System.Text.Json.Serialization; + +namespace Imagekit.Models.TextOverlayProperties.IntersectionMember1Properties; + +/// +/// Text can be included in the layer as either `i-{input}` (plain text) or `ie-{base64_encoded_input}` +/// (base64). By default, the SDK selects the appropriate format based on the input +/// text. To always use base64 (`ie-{base64}`), set this parameter to `base64`. +/// To always use plain text (`i-{input}`), set it to `plain`. +/// +[JsonConverter(typeof(EncodingConverter))] +public enum Encoding +{ + Auto, + Plain, + Base64, +} + +sealed class EncodingConverter : JsonConverter +{ + public override Encoding Read( + ref Utf8JsonReader reader, + Type typeToConvert, + JsonSerializerOptions options + ) + { + return JsonSerializer.Deserialize(ref reader, options) switch + { + "auto" => Encoding.Auto, + "plain" => Encoding.Plain, + "base64" => Encoding.Base64, + _ => (Encoding)(-1), + }; + } + + public override void Write(Utf8JsonWriter writer, Encoding value, JsonSerializerOptions options) + { + JsonSerializer.Serialize( + writer, + value switch + { + Encoding.Auto => "auto", + Encoding.Plain => "plain", + Encoding.Base64 => "base64", + _ => throw new ArgumentOutOfRangeException(nameof(value)), + }, + options + ); + } +} diff --git a/src/Imagekit/Models/TextOverlayTransformation.cs b/src/Imagekit/Models/TextOverlayTransformation.cs new file mode 100644 index 00000000..0fd70a89 --- /dev/null +++ b/src/Imagekit/Models/TextOverlayTransformation.cs @@ -0,0 +1,345 @@ +using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; +using System.Text.Json; +using System.Text.Json.Serialization; +using Imagekit.Models.TextOverlayTransformationProperties; + +namespace Imagekit.Models; + +[JsonConverter(typeof(ModelConverter))] +public sealed record class TextOverlayTransformation + : ModelBase, + IFromRaw +{ + /// + /// Specifies the transparency level of the text overlay. Accepts integers from + /// `1` to `9`. + /// + public double? Alpha + { + get + { + if (!this.Properties.TryGetValue("alpha", out JsonElement element)) + return null; + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions); + } + set + { + this.Properties["alpha"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + /// + /// Specifies the background color of the text overlay. Accepts an RGB hex code, + /// an RGBA code, or a color name. + /// + public string? Background + { + get + { + if (!this.Properties.TryGetValue("background", out JsonElement element)) + return null; + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions); + } + set + { + this.Properties["background"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + /// + /// Flip the text overlay horizontally, vertically, or both. + /// + public ApiEnum? Flip + { + get + { + if (!this.Properties.TryGetValue("flip", out JsonElement element)) + return null; + + return JsonSerializer.Deserialize?>( + element, + ModelBase.SerializerOptions + ); + } + set + { + this.Properties["flip"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + /// + /// Specifies the font color of the overlaid text. Accepts an RGB hex code (e.g., + /// `FF0000`), an RGBA code (e.g., `FFAABB50`), or a color name. + /// + public string? FontColor + { + get + { + if (!this.Properties.TryGetValue("fontColor", out JsonElement element)) + return null; + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions); + } + set + { + this.Properties["fontColor"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + /// + /// Specifies the font family of the overlaid text. Choose from the supported + /// fonts list or use a custom font. See [Supported fonts](https://imagekit.io/docs/add-overlays-on-images#supported-text-font-list) + /// and [Custom font](https://imagekit.io/docs/add-overlays-on-images#change-font-family-in-text-overlay). + /// + public string? FontFamily + { + get + { + if (!this.Properties.TryGetValue("fontFamily", out JsonElement element)) + return null; + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions); + } + set + { + this.Properties["fontFamily"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + /// + /// Specifies the font size of the overlaid text. Accepts a numeric value or + /// an arithmetic expression. + /// + public FontSize? FontSize + { + get + { + if (!this.Properties.TryGetValue("fontSize", out JsonElement element)) + return null; + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions); + } + set + { + this.Properties["fontSize"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + /// + /// Specifies the inner alignment of the text when width is more than the text + /// length. + /// + public ApiEnum? InnerAlignment + { + get + { + if (!this.Properties.TryGetValue("innerAlignment", out JsonElement element)) + return null; + + return JsonSerializer.Deserialize?>( + element, + ModelBase.SerializerOptions + ); + } + set + { + this.Properties["innerAlignment"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + /// + /// Specifies the line height of the text overlay. Accepts integer values representing + /// line height in points. It can also accept [arithmetic expressions](https://imagekit.io/docs/arithmetic-expressions-in-transformations) + /// such as `bw_mul_0.2`, or `bh_div_20`. + /// + public LineHeight? LineHeight + { + get + { + if (!this.Properties.TryGetValue("lineHeight", out JsonElement element)) + return null; + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions); + } + set + { + this.Properties["lineHeight"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + /// + /// Specifies the padding around the overlaid text. Can be provided as a single + /// positive integer or multiple values separated by underscores (following CSS + /// shorthand order). Arithmetic expressions are also accepted. + /// + public Padding? Padding + { + get + { + if (!this.Properties.TryGetValue("padding", out JsonElement element)) + return null; + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions); + } + set + { + this.Properties["padding"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + /// + /// Specifies the corner radius of the text overlay. Set to `max` to achieve + /// a circular or oval shape. + /// + public Radius? Radius + { + get + { + if (!this.Properties.TryGetValue("radius", out JsonElement element)) + return null; + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions); + } + set + { + this.Properties["radius"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + /// + /// Specifies the rotation angle of the text overlay. Accepts a numeric value + /// for clockwise rotation or a string prefixed with "N" for counter-clockwise + /// rotation. + /// + public Rotation? Rotation + { + get + { + if (!this.Properties.TryGetValue("rotation", out JsonElement element)) + return null; + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions); + } + set + { + this.Properties["rotation"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + /// + /// Specifies the typography style of the text. Supported values: - Single + /// styles: `b` (bold), `i` (italic), `strikethrough`. - Combinations: Any combination + /// separated by underscores, e.g., `b_i`, `b_i_strikethrough`. + /// + public string? Typography + { + get + { + if (!this.Properties.TryGetValue("typography", out JsonElement element)) + return null; + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions); + } + set + { + this.Properties["typography"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + /// + /// Specifies the maximum width (in pixels) of the overlaid text. The text wraps + /// automatically, and arithmetic expressions (e.g., `bw_mul_0.2` or `bh_div_2`) + /// are supported. Useful when used in conjunction with the `background`. Learn + /// about [Arithmetic expressions](https://imagekit.io/docs/arithmetic-expressions-in-transformations). + /// + public Width? Width + { + get + { + if (!this.Properties.TryGetValue("width", out JsonElement element)) + return null; + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions); + } + set + { + this.Properties["width"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + public override void Validate() + { + _ = this.Alpha; + _ = this.Background; + this.Flip?.Validate(); + _ = this.FontColor; + _ = this.FontFamily; + this.FontSize?.Validate(); + this.InnerAlignment?.Validate(); + this.LineHeight?.Validate(); + this.Padding?.Validate(); + this.Radius?.Validate(); + this.Rotation?.Validate(); + _ = this.Typography; + this.Width?.Validate(); + } + + public TextOverlayTransformation() { } + +#pragma warning disable CS8618 + [SetsRequiredMembers] + TextOverlayTransformation(Dictionary properties) + { + Properties = properties; + } +#pragma warning restore CS8618 + + public static TextOverlayTransformation FromRawUnchecked( + Dictionary properties + ) + { + return new(properties); + } +} diff --git a/src/Imagekit/Models/TextOverlayTransformationProperties/Flip.cs b/src/Imagekit/Models/TextOverlayTransformationProperties/Flip.cs new file mode 100644 index 00000000..7eb76e22 --- /dev/null +++ b/src/Imagekit/Models/TextOverlayTransformationProperties/Flip.cs @@ -0,0 +1,52 @@ +using System; +using System.Text.Json; +using System.Text.Json.Serialization; + +namespace Imagekit.Models.TextOverlayTransformationProperties; + +/// +/// Flip the text overlay horizontally, vertically, or both. +/// +[JsonConverter(typeof(FlipConverter))] +public enum Flip +{ + H, + V, + HV, + VH, +} + +sealed class FlipConverter : JsonConverter +{ + public override Flip Read( + ref Utf8JsonReader reader, + Type typeToConvert, + JsonSerializerOptions options + ) + { + return JsonSerializer.Deserialize(ref reader, options) switch + { + "h" => Flip.H, + "v" => Flip.V, + "h_v" => Flip.HV, + "v_h" => Flip.VH, + _ => (Flip)(-1), + }; + } + + public override void Write(Utf8JsonWriter writer, Flip value, JsonSerializerOptions options) + { + JsonSerializer.Serialize( + writer, + value switch + { + Flip.H => "h", + Flip.V => "v", + Flip.HV => "h_v", + Flip.VH => "v_h", + _ => throw new ArgumentOutOfRangeException(nameof(value)), + }, + options + ); + } +} diff --git a/src/Imagekit/Models/TextOverlayTransformationProperties/FontSize.cs b/src/Imagekit/Models/TextOverlayTransformationProperties/FontSize.cs new file mode 100644 index 00000000..47f3d413 --- /dev/null +++ b/src/Imagekit/Models/TextOverlayTransformationProperties/FontSize.cs @@ -0,0 +1,115 @@ +using System; +using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; +using System.Text.Json; +using System.Text.Json.Serialization; +using FontSizeVariants = Imagekit.Models.TextOverlayTransformationProperties.FontSizeVariants; + +namespace Imagekit.Models.TextOverlayTransformationProperties; + +/// +/// Specifies the font size of the overlaid text. Accepts a numeric value or an arithmetic expression. +/// +[JsonConverter(typeof(FontSizeConverter))] +public abstract record class FontSize +{ + internal FontSize() { } + + public static implicit operator FontSize(double value) => new FontSizeVariants::Double(value); + + public static implicit operator FontSize(string value) => new FontSizeVariants::String(value); + + public bool TryPickDouble([NotNullWhen(true)] out double? value) + { + value = (this as FontSizeVariants::Double)?.Value; + return value != null; + } + + public bool TryPickString([NotNullWhen(true)] out string? value) + { + value = (this as FontSizeVariants::String)?.Value; + return value != null; + } + + public void Switch( + Action @double, + Action @string + ) + { + switch (this) + { + case FontSizeVariants::Double inner: + @double(inner); + break; + case FontSizeVariants::String inner: + @string(inner); + break; + default: + throw new InvalidOperationException(); + } + } + + public T Match( + Func @double, + Func @string + ) + { + return this switch + { + FontSizeVariants::Double inner => @double(inner), + FontSizeVariants::String inner => @string(inner), + _ => throw new InvalidOperationException(), + }; + } + + public abstract void Validate(); +} + +sealed class FontSizeConverter : JsonConverter +{ + public override FontSize? Read( + ref Utf8JsonReader reader, + Type typeToConvert, + JsonSerializerOptions options + ) + { + List exceptions = []; + + try + { + return new FontSizeVariants::Double( + JsonSerializer.Deserialize(ref reader, options) + ); + } + catch (JsonException e) + { + exceptions.Add(e); + } + + try + { + var deserialized = JsonSerializer.Deserialize(ref reader, options); + if (deserialized != null) + { + return new FontSizeVariants::String(deserialized); + } + } + catch (JsonException e) + { + exceptions.Add(e); + } + + throw new AggregateException(exceptions); + } + + public override void Write(Utf8JsonWriter writer, FontSize value, JsonSerializerOptions options) + { + object variant = value switch + { + FontSizeVariants::Double(var @double) => @double, + FontSizeVariants::String(var @string) => @string, + _ => throw new ArgumentOutOfRangeException(nameof(value)), + }; + JsonSerializer.Serialize(writer, variant, options); + } +} diff --git a/src/Imagekit/Models/TextOverlayTransformationProperties/FontSizeVariants/All.cs b/src/Imagekit/Models/TextOverlayTransformationProperties/FontSizeVariants/All.cs new file mode 100644 index 00000000..3bf4b3ae --- /dev/null +++ b/src/Imagekit/Models/TextOverlayTransformationProperties/FontSizeVariants/All.cs @@ -0,0 +1,21 @@ +namespace Imagekit.Models.TextOverlayTransformationProperties.FontSizeVariants; + +public sealed record class Double(double Value) : FontSize, IVariant +{ + public static Double From(double value) + { + return new(value); + } + + public override void Validate() { } +} + +public sealed record class String(string Value) : FontSize, IVariant +{ + public static String From(string value) + { + return new(value); + } + + public override void Validate() { } +} diff --git a/src/Imagekit/Models/TextOverlayTransformationProperties/InnerAlignment.cs b/src/Imagekit/Models/TextOverlayTransformationProperties/InnerAlignment.cs new file mode 100644 index 00000000..8dab9ed3 --- /dev/null +++ b/src/Imagekit/Models/TextOverlayTransformationProperties/InnerAlignment.cs @@ -0,0 +1,53 @@ +using System; +using System.Text.Json; +using System.Text.Json.Serialization; + +namespace Imagekit.Models.TextOverlayTransformationProperties; + +/// +/// Specifies the inner alignment of the text when width is more than the text length. +/// +[JsonConverter(typeof(InnerAlignmentConverter))] +public enum InnerAlignment +{ + Left, + Right, + Center, +} + +sealed class InnerAlignmentConverter : JsonConverter +{ + public override InnerAlignment Read( + ref Utf8JsonReader reader, + Type typeToConvert, + JsonSerializerOptions options + ) + { + return JsonSerializer.Deserialize(ref reader, options) switch + { + "left" => InnerAlignment.Left, + "right" => InnerAlignment.Right, + "center" => InnerAlignment.Center, + _ => (InnerAlignment)(-1), + }; + } + + public override void Write( + Utf8JsonWriter writer, + InnerAlignment value, + JsonSerializerOptions options + ) + { + JsonSerializer.Serialize( + writer, + value switch + { + InnerAlignment.Left => "left", + InnerAlignment.Right => "right", + InnerAlignment.Center => "center", + _ => throw new ArgumentOutOfRangeException(nameof(value)), + }, + options + ); + } +} diff --git a/src/Imagekit/Models/TextOverlayTransformationProperties/LineHeight.cs b/src/Imagekit/Models/TextOverlayTransformationProperties/LineHeight.cs new file mode 100644 index 00000000..4038cfb1 --- /dev/null +++ b/src/Imagekit/Models/TextOverlayTransformationProperties/LineHeight.cs @@ -0,0 +1,123 @@ +using System; +using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; +using System.Text.Json; +using System.Text.Json.Serialization; +using LineHeightVariants = Imagekit.Models.TextOverlayTransformationProperties.LineHeightVariants; + +namespace Imagekit.Models.TextOverlayTransformationProperties; + +/// +/// Specifies the line height of the text overlay. Accepts integer values representing +/// line height in points. It can also accept [arithmetic expressions](https://imagekit.io/docs/arithmetic-expressions-in-transformations) +/// such as `bw_mul_0.2`, or `bh_div_20`. +/// +[JsonConverter(typeof(LineHeightConverter))] +public abstract record class LineHeight +{ + internal LineHeight() { } + + public static implicit operator LineHeight(double value) => + new LineHeightVariants::Double(value); + + public static implicit operator LineHeight(string value) => + new LineHeightVariants::String(value); + + public bool TryPickDouble([NotNullWhen(true)] out double? value) + { + value = (this as LineHeightVariants::Double)?.Value; + return value != null; + } + + public bool TryPickString([NotNullWhen(true)] out string? value) + { + value = (this as LineHeightVariants::String)?.Value; + return value != null; + } + + public void Switch( + Action @double, + Action @string + ) + { + switch (this) + { + case LineHeightVariants::Double inner: + @double(inner); + break; + case LineHeightVariants::String inner: + @string(inner); + break; + default: + throw new InvalidOperationException(); + } + } + + public T Match( + Func @double, + Func @string + ) + { + return this switch + { + LineHeightVariants::Double inner => @double(inner), + LineHeightVariants::String inner => @string(inner), + _ => throw new InvalidOperationException(), + }; + } + + public abstract void Validate(); +} + +sealed class LineHeightConverter : JsonConverter +{ + public override LineHeight? Read( + ref Utf8JsonReader reader, + Type typeToConvert, + JsonSerializerOptions options + ) + { + List exceptions = []; + + try + { + return new LineHeightVariants::Double( + JsonSerializer.Deserialize(ref reader, options) + ); + } + catch (JsonException e) + { + exceptions.Add(e); + } + + try + { + var deserialized = JsonSerializer.Deserialize(ref reader, options); + if (deserialized != null) + { + return new LineHeightVariants::String(deserialized); + } + } + catch (JsonException e) + { + exceptions.Add(e); + } + + throw new AggregateException(exceptions); + } + + public override void Write( + Utf8JsonWriter writer, + LineHeight value, + JsonSerializerOptions options + ) + { + object variant = value switch + { + LineHeightVariants::Double(var @double) => @double, + LineHeightVariants::String(var @string) => @string, + _ => throw new ArgumentOutOfRangeException(nameof(value)), + }; + JsonSerializer.Serialize(writer, variant, options); + } +} diff --git a/src/Imagekit/Models/TextOverlayTransformationProperties/LineHeightVariants/All.cs b/src/Imagekit/Models/TextOverlayTransformationProperties/LineHeightVariants/All.cs new file mode 100644 index 00000000..79caf949 --- /dev/null +++ b/src/Imagekit/Models/TextOverlayTransformationProperties/LineHeightVariants/All.cs @@ -0,0 +1,21 @@ +namespace Imagekit.Models.TextOverlayTransformationProperties.LineHeightVariants; + +public sealed record class Double(double Value) : LineHeight, IVariant +{ + public static Double From(double value) + { + return new(value); + } + + public override void Validate() { } +} + +public sealed record class String(string Value) : LineHeight, IVariant +{ + public static String From(string value) + { + return new(value); + } + + public override void Validate() { } +} diff --git a/src/Imagekit/Models/TextOverlayTransformationProperties/Padding.cs b/src/Imagekit/Models/TextOverlayTransformationProperties/Padding.cs new file mode 100644 index 00000000..09bec728 --- /dev/null +++ b/src/Imagekit/Models/TextOverlayTransformationProperties/Padding.cs @@ -0,0 +1,117 @@ +using System; +using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; +using System.Text.Json; +using System.Text.Json.Serialization; +using PaddingVariants = Imagekit.Models.TextOverlayTransformationProperties.PaddingVariants; + +namespace Imagekit.Models.TextOverlayTransformationProperties; + +/// +/// Specifies the padding around the overlaid text. Can be provided as a single positive +/// integer or multiple values separated by underscores (following CSS shorthand order). +/// Arithmetic expressions are also accepted. +/// +[JsonConverter(typeof(PaddingConverter))] +public abstract record class Padding +{ + internal Padding() { } + + public static implicit operator Padding(double value) => new PaddingVariants::Double(value); + + public static implicit operator Padding(string value) => new PaddingVariants::String(value); + + public bool TryPickDouble([NotNullWhen(true)] out double? value) + { + value = (this as PaddingVariants::Double)?.Value; + return value != null; + } + + public bool TryPickString([NotNullWhen(true)] out string? value) + { + value = (this as PaddingVariants::String)?.Value; + return value != null; + } + + public void Switch( + Action @double, + Action @string + ) + { + switch (this) + { + case PaddingVariants::Double inner: + @double(inner); + break; + case PaddingVariants::String inner: + @string(inner); + break; + default: + throw new InvalidOperationException(); + } + } + + public T Match( + Func @double, + Func @string + ) + { + return this switch + { + PaddingVariants::Double inner => @double(inner), + PaddingVariants::String inner => @string(inner), + _ => throw new InvalidOperationException(), + }; + } + + public abstract void Validate(); +} + +sealed class PaddingConverter : JsonConverter +{ + public override Padding? Read( + ref Utf8JsonReader reader, + Type typeToConvert, + JsonSerializerOptions options + ) + { + List exceptions = []; + + try + { + return new PaddingVariants::Double( + JsonSerializer.Deserialize(ref reader, options) + ); + } + catch (JsonException e) + { + exceptions.Add(e); + } + + try + { + var deserialized = JsonSerializer.Deserialize(ref reader, options); + if (deserialized != null) + { + return new PaddingVariants::String(deserialized); + } + } + catch (JsonException e) + { + exceptions.Add(e); + } + + throw new AggregateException(exceptions); + } + + public override void Write(Utf8JsonWriter writer, Padding value, JsonSerializerOptions options) + { + object variant = value switch + { + PaddingVariants::Double(var @double) => @double, + PaddingVariants::String(var @string) => @string, + _ => throw new ArgumentOutOfRangeException(nameof(value)), + }; + JsonSerializer.Serialize(writer, variant, options); + } +} diff --git a/src/Imagekit/Models/TextOverlayTransformationProperties/PaddingVariants/All.cs b/src/Imagekit/Models/TextOverlayTransformationProperties/PaddingVariants/All.cs new file mode 100644 index 00000000..4a679151 --- /dev/null +++ b/src/Imagekit/Models/TextOverlayTransformationProperties/PaddingVariants/All.cs @@ -0,0 +1,21 @@ +namespace Imagekit.Models.TextOverlayTransformationProperties.PaddingVariants; + +public sealed record class Double(double Value) : Padding, IVariant +{ + public static Double From(double value) + { + return new(value); + } + + public override void Validate() { } +} + +public sealed record class String(string Value) : Padding, IVariant +{ + public static String From(string value) + { + return new(value); + } + + public override void Validate() { } +} diff --git a/src/Imagekit/Models/TextOverlayTransformationProperties/Radius.cs b/src/Imagekit/Models/TextOverlayTransformationProperties/Radius.cs new file mode 100644 index 00000000..0c2f728c --- /dev/null +++ b/src/Imagekit/Models/TextOverlayTransformationProperties/Radius.cs @@ -0,0 +1,106 @@ +using System; +using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; +using System.Text.Json; +using System.Text.Json.Serialization; +using RadiusVariants = Imagekit.Models.TextOverlayTransformationProperties.RadiusVariants; + +namespace Imagekit.Models.TextOverlayTransformationProperties; + +/// +/// Specifies the corner radius of the text overlay. Set to `max` to achieve a circular +/// or oval shape. +/// +[JsonConverter(typeof(RadiusConverter))] +public abstract record class Radius +{ + internal Radius() { } + + public static implicit operator Radius(double value) => new RadiusVariants::Double(value); + + public bool TryPickDouble([NotNullWhen(true)] out double? value) + { + value = (this as RadiusVariants::Double)?.Value; + return value != null; + } + + public bool TryPickMax([NotNullWhen(true)] out JsonElement? value) + { + value = (this as RadiusVariants::Max)?.Value; + return value != null; + } + + public void Switch(Action @double, Action max) + { + switch (this) + { + case RadiusVariants::Double inner: + @double(inner); + break; + case RadiusVariants::Max inner: + max(inner); + break; + default: + throw new InvalidOperationException(); + } + } + + public T Match(Func @double, Func max) + { + return this switch + { + RadiusVariants::Double inner => @double(inner), + RadiusVariants::Max inner => max(inner), + _ => throw new InvalidOperationException(), + }; + } + + public abstract void Validate(); +} + +sealed class RadiusConverter : JsonConverter +{ + public override Radius? Read( + ref Utf8JsonReader reader, + Type typeToConvert, + JsonSerializerOptions options + ) + { + List exceptions = []; + + try + { + return new RadiusVariants::Max( + JsonSerializer.Deserialize(ref reader, options) + ); + } + catch (JsonException e) + { + exceptions.Add(e); + } + + try + { + return new RadiusVariants::Double( + JsonSerializer.Deserialize(ref reader, options) + ); + } + catch (JsonException e) + { + exceptions.Add(e); + } + + throw new AggregateException(exceptions); + } + + public override void Write(Utf8JsonWriter writer, Radius value, JsonSerializerOptions options) + { + object variant = value switch + { + RadiusVariants::Double(var @double) => @double, + RadiusVariants::Max(var max) => max, + _ => throw new ArgumentOutOfRangeException(nameof(value)), + }; + JsonSerializer.Serialize(writer, variant, options); + } +} diff --git a/src/Imagekit/Models/TextOverlayTransformationProperties/RadiusVariants/All.cs b/src/Imagekit/Models/TextOverlayTransformationProperties/RadiusVariants/All.cs new file mode 100644 index 00000000..8f858903 --- /dev/null +++ b/src/Imagekit/Models/TextOverlayTransformationProperties/RadiusVariants/All.cs @@ -0,0 +1,23 @@ +using System.Text.Json; + +namespace Imagekit.Models.TextOverlayTransformationProperties.RadiusVariants; + +public sealed record class Double(double Value) : Radius, IVariant +{ + public static Double From(double value) + { + return new(value); + } + + public override void Validate() { } +} + +public sealed record class Max(JsonElement Value) : Radius, IVariant +{ + public static Max From(JsonElement value) + { + return new(value); + } + + public override void Validate() { } +} diff --git a/src/Imagekit/Models/TextOverlayTransformationProperties/Rotation.cs b/src/Imagekit/Models/TextOverlayTransformationProperties/Rotation.cs new file mode 100644 index 00000000..cb4ceeba --- /dev/null +++ b/src/Imagekit/Models/TextOverlayTransformationProperties/Rotation.cs @@ -0,0 +1,116 @@ +using System; +using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; +using System.Text.Json; +using System.Text.Json.Serialization; +using RotationVariants = Imagekit.Models.TextOverlayTransformationProperties.RotationVariants; + +namespace Imagekit.Models.TextOverlayTransformationProperties; + +/// +/// Specifies the rotation angle of the text overlay. Accepts a numeric value for +/// clockwise rotation or a string prefixed with "N" for counter-clockwise rotation. +/// +[JsonConverter(typeof(RotationConverter))] +public abstract record class Rotation +{ + internal Rotation() { } + + public static implicit operator Rotation(double value) => new RotationVariants::Double(value); + + public static implicit operator Rotation(string value) => new RotationVariants::String(value); + + public bool TryPickDouble([NotNullWhen(true)] out double? value) + { + value = (this as RotationVariants::Double)?.Value; + return value != null; + } + + public bool TryPickString([NotNullWhen(true)] out string? value) + { + value = (this as RotationVariants::String)?.Value; + return value != null; + } + + public void Switch( + Action @double, + Action @string + ) + { + switch (this) + { + case RotationVariants::Double inner: + @double(inner); + break; + case RotationVariants::String inner: + @string(inner); + break; + default: + throw new InvalidOperationException(); + } + } + + public T Match( + Func @double, + Func @string + ) + { + return this switch + { + RotationVariants::Double inner => @double(inner), + RotationVariants::String inner => @string(inner), + _ => throw new InvalidOperationException(), + }; + } + + public abstract void Validate(); +} + +sealed class RotationConverter : JsonConverter +{ + public override Rotation? Read( + ref Utf8JsonReader reader, + Type typeToConvert, + JsonSerializerOptions options + ) + { + List exceptions = []; + + try + { + return new RotationVariants::Double( + JsonSerializer.Deserialize(ref reader, options) + ); + } + catch (JsonException e) + { + exceptions.Add(e); + } + + try + { + var deserialized = JsonSerializer.Deserialize(ref reader, options); + if (deserialized != null) + { + return new RotationVariants::String(deserialized); + } + } + catch (JsonException e) + { + exceptions.Add(e); + } + + throw new AggregateException(exceptions); + } + + public override void Write(Utf8JsonWriter writer, Rotation value, JsonSerializerOptions options) + { + object variant = value switch + { + RotationVariants::Double(var @double) => @double, + RotationVariants::String(var @string) => @string, + _ => throw new ArgumentOutOfRangeException(nameof(value)), + }; + JsonSerializer.Serialize(writer, variant, options); + } +} diff --git a/src/Imagekit/Models/TextOverlayTransformationProperties/RotationVariants/All.cs b/src/Imagekit/Models/TextOverlayTransformationProperties/RotationVariants/All.cs new file mode 100644 index 00000000..b56a030f --- /dev/null +++ b/src/Imagekit/Models/TextOverlayTransformationProperties/RotationVariants/All.cs @@ -0,0 +1,21 @@ +namespace Imagekit.Models.TextOverlayTransformationProperties.RotationVariants; + +public sealed record class Double(double Value) : Rotation, IVariant +{ + public static Double From(double value) + { + return new(value); + } + + public override void Validate() { } +} + +public sealed record class String(string Value) : Rotation, IVariant +{ + public static String From(string value) + { + return new(value); + } + + public override void Validate() { } +} diff --git a/src/Imagekit/Models/TextOverlayTransformationProperties/Width.cs b/src/Imagekit/Models/TextOverlayTransformationProperties/Width.cs new file mode 100644 index 00000000..9a9f43b7 --- /dev/null +++ b/src/Imagekit/Models/TextOverlayTransformationProperties/Width.cs @@ -0,0 +1,115 @@ +using System; +using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; +using System.Text.Json; +using System.Text.Json.Serialization; +using WidthVariants = Imagekit.Models.TextOverlayTransformationProperties.WidthVariants; + +namespace Imagekit.Models.TextOverlayTransformationProperties; + +/// +/// Specifies the maximum width (in pixels) of the overlaid text. The text wraps +/// automatically, and arithmetic expressions (e.g., `bw_mul_0.2` or `bh_div_2`) +/// are supported. Useful when used in conjunction with the `background`. Learn about +/// [Arithmetic expressions](https://imagekit.io/docs/arithmetic-expressions-in-transformations). +/// +[JsonConverter(typeof(WidthConverter))] +public abstract record class Width +{ + internal Width() { } + + public static implicit operator Width(double value) => new WidthVariants::Double(value); + + public static implicit operator Width(string value) => new WidthVariants::String(value); + + public bool TryPickDouble([NotNullWhen(true)] out double? value) + { + value = (this as WidthVariants::Double)?.Value; + return value != null; + } + + public bool TryPickString([NotNullWhen(true)] out string? value) + { + value = (this as WidthVariants::String)?.Value; + return value != null; + } + + public void Switch(Action @double, Action @string) + { + switch (this) + { + case WidthVariants::Double inner: + @double(inner); + break; + case WidthVariants::String inner: + @string(inner); + break; + default: + throw new InvalidOperationException(); + } + } + + public T Match( + Func @double, + Func @string + ) + { + return this switch + { + WidthVariants::Double inner => @double(inner), + WidthVariants::String inner => @string(inner), + _ => throw new InvalidOperationException(), + }; + } + + public abstract void Validate(); +} + +sealed class WidthConverter : JsonConverter +{ + public override Width? Read( + ref Utf8JsonReader reader, + Type typeToConvert, + JsonSerializerOptions options + ) + { + List exceptions = []; + + try + { + return new WidthVariants::Double( + JsonSerializer.Deserialize(ref reader, options) + ); + } + catch (JsonException e) + { + exceptions.Add(e); + } + + try + { + var deserialized = JsonSerializer.Deserialize(ref reader, options); + if (deserialized != null) + { + return new WidthVariants::String(deserialized); + } + } + catch (JsonException e) + { + exceptions.Add(e); + } + + throw new AggregateException(exceptions); + } + + public override void Write(Utf8JsonWriter writer, Width value, JsonSerializerOptions options) + { + object variant = value switch + { + WidthVariants::Double(var @double) => @double, + WidthVariants::String(var @string) => @string, + _ => throw new ArgumentOutOfRangeException(nameof(value)), + }; + JsonSerializer.Serialize(writer, variant, options); + } +} diff --git a/src/Imagekit/Models/TextOverlayTransformationProperties/WidthVariants/All.cs b/src/Imagekit/Models/TextOverlayTransformationProperties/WidthVariants/All.cs new file mode 100644 index 00000000..e08d3a5e --- /dev/null +++ b/src/Imagekit/Models/TextOverlayTransformationProperties/WidthVariants/All.cs @@ -0,0 +1,21 @@ +namespace Imagekit.Models.TextOverlayTransformationProperties.WidthVariants; + +public sealed record class Double(double Value) : Width, IVariant +{ + public static Double From(double value) + { + return new(value); + } + + public override void Validate() { } +} + +public sealed record class String(string Value) : Width, IVariant +{ + public static String From(string value) + { + return new(value); + } + + public override void Validate() { } +} diff --git a/src/Imagekit/Models/Transformation.cs b/src/Imagekit/Models/Transformation.cs new file mode 100644 index 00000000..e1051a84 --- /dev/null +++ b/src/Imagekit/Models/Transformation.cs @@ -0,0 +1,1320 @@ +using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; +using System.Text.Json; +using System.Text.Json.Serialization; +using Imagekit.Models.TransformationProperties; + +namespace Imagekit.Models; + +/// +/// The SDK provides easy-to-use names for transformations. These names are converted +/// to the corresponding transformation string before being added to the URL. SDKs +/// are updated regularly to support new transformations. If you want to use a transformation +/// that is not supported by the SDK, You can use the `raw` parameter to pass the +/// transformation string directly. See the [Transformations documentation](https://imagekit.io/docs/transformations). +/// +[JsonConverter(typeof(ModelConverter))] +public sealed record class Transformation : ModelBase, IFromRaw +{ + /// + /// Uses AI to change the background. Provide a text prompt or a base64-encoded + /// prompt, e.g., `prompt-snow road` or `prompte-[urlencoded_base64_encoded_text]`. + /// Not supported inside overlay. See [AI Change Background](https://imagekit.io/docs/ai-transformations#change-background-e-changebg). + /// + public string? AIChangeBackground + { + get + { + if (!this.Properties.TryGetValue("aiChangeBackground", out JsonElement element)) + return null; + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions); + } + set + { + this.Properties["aiChangeBackground"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + /// + /// Adds an AI-based drop shadow around a foreground object on a transparent or + /// removed background. Optionally, control the direction, elevation, and saturation + /// of the light source (e.g., `az-45` to change light direction). Pass `true` + /// for the default drop shadow, or provide a string for a custom drop shadow. + /// Supported inside overlay. See [AI Drop Shadow](https://imagekit.io/docs/ai-transformations#ai-drop-shadow-e-dropshadow). + /// + public AIDropShadow? AIDropShadow + { + get + { + if (!this.Properties.TryGetValue("aiDropShadow", out JsonElement element)) + return null; + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions); + } + set + { + this.Properties["aiDropShadow"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + /// + /// Uses AI to edit images based on a text prompt. Provide a text prompt or a + /// base64-encoded prompt, e.g., `prompt-snow road` or `prompte-[urlencoded_base64_encoded_text]`. + /// Not supported inside overlay. See [AI Edit](https://imagekit.io/docs/ai-transformations#edit-image-e-edit). + /// + public string? AIEdit + { + get + { + if (!this.Properties.TryGetValue("aiEdit", out JsonElement element)) + return null; + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions); + } + set + { + this.Properties["aiEdit"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + /// + /// Applies ImageKit's in-house background removal. Supported inside overlay. + /// See [AI Background Removal](https://imagekit.io/docs/ai-transformations#imagekit-background-removal-e-bgremove). + /// + public ApiEnum? AIRemoveBackground + { + get + { + if (!this.Properties.TryGetValue("aiRemoveBackground", out JsonElement element)) + return null; + + return JsonSerializer.Deserialize?>( + element, + ModelBase.SerializerOptions + ); + } + set + { + this.Properties["aiRemoveBackground"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + /// + /// Uses third-party background removal. Note: It is recommended to use aiRemoveBackground, + /// ImageKit's in-house solution, which is more cost-effective. Supported inside + /// overlay. See [External Background Removal](https://imagekit.io/docs/ai-transformations#background-removal-e-removedotbg). + /// + public ApiEnum? AIRemoveBackgroundExternal + { + get + { + if (!this.Properties.TryGetValue("aiRemoveBackgroundExternal", out JsonElement element)) + return null; + + return JsonSerializer.Deserialize?>( + element, + ModelBase.SerializerOptions + ); + } + set + { + this.Properties["aiRemoveBackgroundExternal"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + /// + /// Performs AI-based retouching to improve faces or product shots. Not supported + /// inside overlay. See [AI Retouch](https://imagekit.io/docs/ai-transformations#retouch-e-retouch). + /// + public ApiEnum? AIRetouch + { + get + { + if (!this.Properties.TryGetValue("aiRetouch", out JsonElement element)) + return null; + + return JsonSerializer.Deserialize?>( + element, + ModelBase.SerializerOptions + ); + } + set + { + this.Properties["aiRetouch"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + /// + /// Upscales images beyond their original dimensions using AI. Not supported inside + /// overlay. See [AI Upscale](https://imagekit.io/docs/ai-transformations#upscale-e-upscale). + /// + public ApiEnum? AIUpscale + { + get + { + if (!this.Properties.TryGetValue("aiUpscale", out JsonElement element)) + return null; + + return JsonSerializer.Deserialize?>( + element, + ModelBase.SerializerOptions + ); + } + set + { + this.Properties["aiUpscale"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + /// + /// Generates a variation of an image using AI. This produces a new image with + /// slight variations from the original, such as changes in color, texture, + /// and other visual elements, while preserving the structure and essence of the + /// original image. Not supported inside overlay. See [AI Generate Variations](https://imagekit.io/docs/ai-transformations#generate-variations-of-an-image-e-genvar). + /// + public ApiEnum? AIVariation + { + get + { + if (!this.Properties.TryGetValue("aiVariation", out JsonElement element)) + return null; + + return JsonSerializer.Deserialize?>( + element, + ModelBase.SerializerOptions + ); + } + set + { + this.Properties["aiVariation"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + /// + /// Specifies the aspect ratio for the output, e.g., "ar-4-3". Typically used + /// with either width or height (but not both). For example: aspectRatio = `4:3`, + /// `4_3`, or an expression like `iar_div_2`. See [Image resize and crop – Aspect + /// ratio](https://imagekit.io/docs/image-resize-and-crop#aspect-ratio---ar). + /// + public AspectRatio? AspectRatio + { + get + { + if (!this.Properties.TryGetValue("aspectRatio", out JsonElement element)) + return null; + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions); + } + set + { + this.Properties["aspectRatio"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + /// + /// Specifies the audio codec, e.g., `aac`, `opus`, or `none`. See [Audio codec](https://imagekit.io/docs/video-optimization#audio-codec---ac). + /// + public ApiEnum? AudioCodec + { + get + { + if (!this.Properties.TryGetValue("audioCodec", out JsonElement element)) + return null; + + return JsonSerializer.Deserialize?>( + element, + ModelBase.SerializerOptions + ); + } + set + { + this.Properties["audioCodec"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + /// + /// Specifies the background to be used in conjunction with certain cropping + /// strategies when resizing an image. - A solid color: e.g., `red`, `F3F3F3`, + /// `AAFF0010`. See [Solid color background](https://imagekit.io/docs/effects-and-enhancements#solid-color-background). + /// - A blurred background: e.g., `blurred`, `blurred_25_N15`, etc. See [Blurred + /// background](https://imagekit.io/docs/effects-and-enhancements#blurred-background). + /// - Expand the image boundaries using generative fill: `genfill`. Not supported + /// inside overlay. Optionally, control the background scene by passing a text + /// prompt: `genfill[:-prompt-${text}]` or `genfill[:-prompte-${urlencoded_base64_encoded_text}]`. + /// See [Generative fill background](https://imagekit.io/docs/ai-transformations#generative-fill-bg-genfill). + /// + public string? Background + { + get + { + if (!this.Properties.TryGetValue("background", out JsonElement element)) + return null; + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions); + } + set + { + this.Properties["background"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + /// + /// Specifies the Gaussian blur level. Accepts an integer value between 1 and + /// 100, or an expression like `bl-10`. See [Blur](https://imagekit.io/docs/effects-and-enhancements#blur---bl). + /// + public double? Blur + { + get + { + if (!this.Properties.TryGetValue("blur", out JsonElement element)) + return null; + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions); + } + set + { + this.Properties["blur"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + /// + /// Adds a border to the output media. Accepts a string in the format `_` + /// (e.g., `5_FFF000` for a 5px yellow border), or an expression like `ih_div_20_FF00FF`. + /// See [Border](https://imagekit.io/docs/effects-and-enhancements#border---b). + /// + public string? Border + { + get + { + if (!this.Properties.TryGetValue("border", out JsonElement element)) + return null; + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions); + } + set + { + this.Properties["border"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + /// + /// Indicates whether the output image should retain the original color profile. + /// See [Color profile](https://imagekit.io/docs/image-optimization#color-profile---cp). + /// + public bool? ColorProfile + { + get + { + if (!this.Properties.TryGetValue("colorProfile", out JsonElement element)) + return null; + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions); + } + set + { + this.Properties["colorProfile"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + /// + /// Automatically enhances the contrast of an image (contrast stretch). See [Contrast + /// Stretch](https://imagekit.io/docs/effects-and-enhancements#contrast-stretch---e-contrast). + /// + public ApiEnum? ContrastStretch + { + get + { + if (!this.Properties.TryGetValue("contrastStretch", out JsonElement element)) + return null; + + return JsonSerializer.Deserialize?>( + element, + ModelBase.SerializerOptions + ); + } + set + { + this.Properties["contrastStretch"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + /// + /// Crop modes for image resizing. See [Crop modes & focus](https://imagekit.io/docs/image-resize-and-crop#crop-crop-modes--focus). + /// + public ApiEnum? Crop + { + get + { + if (!this.Properties.TryGetValue("crop", out JsonElement element)) + return null; + + return JsonSerializer.Deserialize?>( + element, + ModelBase.SerializerOptions + ); + } + set + { + this.Properties["crop"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + /// + /// Additional crop modes for image resizing. See [Crop modes & focus](https://imagekit.io/docs/image-resize-and-crop#crop-crop-modes--focus). + /// + public ApiEnum? CropMode + { + get + { + if (!this.Properties.TryGetValue("cropMode", out JsonElement element)) + return null; + + return JsonSerializer.Deserialize?>( + element, + ModelBase.SerializerOptions + ); + } + set + { + this.Properties["cropMode"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + /// + /// Specifies a fallback image if the resource is not found, e.g., a URL or file + /// path. See [Default image](https://imagekit.io/docs/image-transformation#default-image---di). + /// + public string? DefaultImage + { + get + { + if (!this.Properties.TryGetValue("defaultImage", out JsonElement element)) + return null; + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions); + } + set + { + this.Properties["defaultImage"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + /// + /// Accepts values between 0.1 and 5, or `auto` for automatic device pixel ratio + /// (DPR) calculation. See [DPR](https://imagekit.io/docs/image-resize-and-crop#dpr---dpr). + /// + public double? Dpr + { + get + { + if (!this.Properties.TryGetValue("dpr", out JsonElement element)) + return null; + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions); + } + set + { + this.Properties["dpr"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + /// + /// Specifies the duration (in seconds) for trimming videos, e.g., `5` or `10.5`. + /// Typically used with startOffset to indicate the length from the start offset. + /// Arithmetic expressions are supported. See [Trim videos – Duration](https://imagekit.io/docs/trim-videos#duration---du). + /// + public Duration? Duration + { + get + { + if (!this.Properties.TryGetValue("duration", out JsonElement element)) + return null; + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions); + } + set + { + this.Properties["duration"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + /// + /// Specifies the end offset (in seconds) for trimming videos, e.g., `5` or `10.5`. + /// Typically used with startOffset to define a time window. Arithmetic expressions + /// are supported. See [Trim videos – End offset](https://imagekit.io/docs/trim-videos#end-offset---eo). + /// + public EndOffset? EndOffset + { + get + { + if (!this.Properties.TryGetValue("endOffset", out JsonElement element)) + return null; + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions); + } + set + { + this.Properties["endOffset"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + /// + /// Flips or mirrors an image either horizontally, vertically, or both. Acceptable + /// values: `h` (horizontal), `v` (vertical), `h_v` (horizontal and vertical), + /// or `v_h`. See [Flip](https://imagekit.io/docs/effects-and-enhancements#flip---fl). + /// + public ApiEnum? Flip + { + get + { + if (!this.Properties.TryGetValue("flip", out JsonElement element)) + return null; + + return JsonSerializer.Deserialize?>( + element, + ModelBase.SerializerOptions + ); + } + set + { + this.Properties["flip"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + /// + /// Refines padding and cropping behavior for pad resize, maintain ratio, and + /// extract crop modes. Supports manual positions and coordinate-based focus. + /// With AI-based cropping, you can automatically keep key subjects in frame—such + /// as faces or detected objects (e.g., `fo-face`, `fo-person`, `fo-car`)— while + /// resizing. - See [Focus](https://imagekit.io/docs/image-resize-and-crop#focus---fo). + /// - [Object aware cropping](https://imagekit.io/docs/image-resize-and-crop#object-aware-cropping---fo-object-name) + /// + public string? Focus + { + get + { + if (!this.Properties.TryGetValue("focus", out JsonElement element)) + return null; + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions); + } + set + { + this.Properties["focus"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + /// + /// Specifies the output format for images or videos, e.g., `jpg`, `png`, `webp`, + /// `mp4`, or `auto`. You can also pass `orig` for images to return the original + /// format. ImageKit automatically delivers images and videos in the optimal format + /// based on device support unless overridden by the dashboard settings or the + /// format parameter. See [Image format](https://imagekit.io/docs/image-optimization#format---f) + /// and [Video format](https://imagekit.io/docs/video-optimization#format---f). + /// + public ApiEnum? Format + { + get + { + if (!this.Properties.TryGetValue("format", out JsonElement element)) + return null; + + return JsonSerializer.Deserialize?>( + element, + ModelBase.SerializerOptions + ); + } + set + { + this.Properties["format"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + /// + /// Creates a linear gradient with two colors. Pass `true` for a default gradient, + /// or provide a string for a custom gradient. See [Gradient](https://imagekit.io/docs/effects-and-enhancements#gradient---e-gradient). + /// + public Gradient? Gradient + { + get + { + if (!this.Properties.TryGetValue("gradient", out JsonElement element)) + return null; + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions); + } + set + { + this.Properties["gradient"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + /// + /// Enables a grayscale effect for images. See [Grayscale](https://imagekit.io/docs/effects-and-enhancements#grayscale---e-grayscale). + /// + public ApiEnum? Grayscale + { + get + { + if (!this.Properties.TryGetValue("grayscale", out JsonElement element)) + return null; + + return JsonSerializer.Deserialize?>( + element, + ModelBase.SerializerOptions + ); + } + set + { + this.Properties["grayscale"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + /// + /// Specifies the height of the output. If a value between 0 and 1 is provided, + /// it is treated as a percentage (e.g., `0.5` represents 50% of the original + /// height). You can also supply arithmetic expressions (e.g., `ih_mul_0.5`). + /// Height transformation – [Images](https://imagekit.io/docs/image-resize-and-crop#height---h) + /// · [Videos](https://imagekit.io/docs/video-resize-and-crop#height---h) + /// + public Height? Height + { + get + { + if (!this.Properties.TryGetValue("height", out JsonElement element)) + return null; + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions); + } + set + { + this.Properties["height"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + /// + /// Specifies whether the output image (in JPEG or PNG) should be compressed losslessly. + /// See [Lossless compression](https://imagekit.io/docs/image-optimization#lossless-webp-and-png---lo). + /// + public bool? Lossless + { + get + { + if (!this.Properties.TryGetValue("lossless", out JsonElement element)) + return null; + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions); + } + set + { + this.Properties["lossless"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + /// + /// By default, ImageKit removes all metadata during automatic image compression. + /// Set this to true to preserve metadata. See [Image metadata](https://imagekit.io/docs/image-optimization#image-metadata---md). + /// + public bool? Metadata + { + get + { + if (!this.Properties.TryGetValue("metadata", out JsonElement element)) + return null; + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions); + } + set + { + this.Properties["metadata"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + /// + /// Named transformation reference. See [Named transformations](https://imagekit.io/docs/transformations#named-transformations). + /// + public string? Named + { + get + { + if (!this.Properties.TryGetValue("named", out JsonElement element)) + return null; + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions); + } + set + { + this.Properties["named"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + /// + /// Specifies the opacity level of the output image. See [Opacity](https://imagekit.io/docs/effects-and-enhancements#opacity---o). + /// + public double? Opacity + { + get + { + if (!this.Properties.TryGetValue("opacity", out JsonElement element)) + return null; + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions); + } + set + { + this.Properties["opacity"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + /// + /// If set to true, serves the original file without applying any transformations. + /// See [Deliver original file as-is](https://imagekit.io/docs/core-delivery-features#deliver-original-file-as-is---orig-true). + /// + public bool? Original + { + get + { + if (!this.Properties.TryGetValue("original", out JsonElement element)) + return null; + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions); + } + set + { + this.Properties["original"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + /// + /// Specifies an overlay to be applied on the parent image or video. ImageKit + /// supports overlays including images, text, videos, subtitles, and solid colors. + /// See [Overlay using layers](https://imagekit.io/docs/transformations#overlay-using-layers). + /// + public Overlay? Overlay + { + get + { + if (!this.Properties.TryGetValue("overlay", out JsonElement element)) + return null; + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions); + } + set + { + this.Properties["overlay"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + /// + /// Extracts a specific page or frame from multi-page or layered files (PDF, PSD, + /// AI). For example, specify by number (e.g., `2`), a range (e.g., `3-4` for + /// the 2nd and 3rd layers), or by name (e.g., `name-layer-4` for a PSD layer). + /// See [Thumbnail extraction](https://imagekit.io/docs/vector-and-animated-images#get-thumbnail-from-psd-pdf-ai-eps-and-animated-files). + /// + public Page? Page + { + get + { + if (!this.Properties.TryGetValue("page", out JsonElement element)) + return null; + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions); + } + set + { + this.Properties["page"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + /// + /// Specifies whether the output JPEG image should be rendered progressively. + /// Progressive loading begins with a low-quality, pixelated version of the full + /// image, which gradually improves to provide a faster perceived load time. See + /// [Progressive images](https://imagekit.io/docs/image-optimization#progressive-image---pr). + /// + public bool? Progressive + { + get + { + if (!this.Properties.TryGetValue("progressive", out JsonElement element)) + return null; + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions); + } + set + { + this.Properties["progressive"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + /// + /// Specifies the quality of the output image for lossy formats such as JPEG, + /// WebP, and AVIF. A higher quality value results in a larger file size with + /// better quality, while a lower value produces a smaller file size with reduced + /// quality. See [Quality](https://imagekit.io/docs/image-optimization#quality---q). + /// + public double? Quality + { + get + { + if (!this.Properties.TryGetValue("quality", out JsonElement element)) + return null; + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions); + } + set + { + this.Properties["quality"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + /// + /// Specifies the corner radius for rounded corners (e.g., 20) or `max` for circular + /// or oval shape. See [Radius](https://imagekit.io/docs/effects-and-enhancements#radius---r). + /// + public Radius? Radius + { + get + { + if (!this.Properties.TryGetValue("radius", out JsonElement element)) + return null; + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions); + } + set + { + this.Properties["radius"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + /// + /// Pass any transformation not directly supported by the SDK. This transformation + /// string is appended to the URL as provided. + /// + public string? Raw + { + get + { + if (!this.Properties.TryGetValue("raw", out JsonElement element)) + return null; + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions); + } + set + { + this.Properties["raw"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + /// + /// Specifies the rotation angle in degrees. Positive values rotate the image + /// clockwise; you can also use, for example, `N40` for counterclockwise rotation + /// or `auto` to use the orientation specified in the image's EXIF data. For + /// videos, only the following values are supported: 0, 90, 180, 270, or 360. + /// See [Rotate](https://imagekit.io/docs/effects-and-enhancements#rotate---rt). + /// + public Rotation? Rotation + { + get + { + if (!this.Properties.TryGetValue("rotation", out JsonElement element)) + return null; + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions); + } + set + { + this.Properties["rotation"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + /// + /// Adds a shadow beneath solid objects in an image with a transparent background. + /// For AI-based drop shadows, refer to aiDropShadow. Pass `true` for a default + /// shadow, or provide a string for a custom shadow. See [Shadow](https://imagekit.io/docs/effects-and-enhancements#shadow---e-shadow). + /// + public Shadow? Shadow + { + get + { + if (!this.Properties.TryGetValue("shadow", out JsonElement element)) + return null; + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions); + } + set + { + this.Properties["shadow"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + /// + /// Sharpens the input image, highlighting edges and finer details. Pass `true` + /// for default sharpening, or provide a numeric value for custom sharpening. + /// See [Sharpen](https://imagekit.io/docs/effects-and-enhancements#sharpen---e-sharpen). + /// + public Sharpen? Sharpen + { + get + { + if (!this.Properties.TryGetValue("sharpen", out JsonElement element)) + return null; + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions); + } + set + { + this.Properties["sharpen"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + /// + /// Specifies the start offset (in seconds) for trimming videos, e.g., `5` or + /// `10.5`. Arithmetic expressions are also supported. See [Trim videos – Start + /// offset](https://imagekit.io/docs/trim-videos#start-offset---so). + /// + public StartOffset? StartOffset + { + get + { + if (!this.Properties.TryGetValue("startOffset", out JsonElement element)) + return null; + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions); + } + set + { + this.Properties["startOffset"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + /// + /// An array of resolutions for adaptive bitrate streaming, e.g., [`240`, `360`, + /// `480`, `720`, `1080`]. See [Adaptive Bitrate Streaming](https://imagekit.io/docs/adaptive-bitrate-streaming). + /// + public List>? StreamingResolutions + { + get + { + if (!this.Properties.TryGetValue("streamingResolutions", out JsonElement element)) + return null; + + return JsonSerializer.Deserialize>?>( + element, + ModelBase.SerializerOptions + ); + } + set + { + this.Properties["streamingResolutions"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + /// + /// Useful for images with a solid or nearly solid background and a central object. + /// This parameter trims the background, leaving only the central object in + /// the output image. See [Trim edges](https://imagekit.io/docs/effects-and-enhancements#trim-edges---t). + /// + public Trim? Trim + { + get + { + if (!this.Properties.TryGetValue("trim", out JsonElement element)) + return null; + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions); + } + set + { + this.Properties["trim"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + /// + /// Applies Unsharp Masking (USM), an image sharpening technique. Pass `true` + /// for a default unsharp mask, or provide a string for a custom unsharp mask. + /// See [Unsharp Mask](https://imagekit.io/docs/effects-and-enhancements#unsharp-mask---e-usm). + /// + public UnsharpMask? UnsharpMask + { + get + { + if (!this.Properties.TryGetValue("unsharpMask", out JsonElement element)) + return null; + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions); + } + set + { + this.Properties["unsharpMask"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + /// + /// Specifies the video codec, e.g., `h264`, `vp9`, `av1`, or `none`. See [Video codec](https://imagekit.io/docs/video-optimization#video-codec---vc). + /// + public ApiEnum? VideoCodec + { + get + { + if (!this.Properties.TryGetValue("videoCodec", out JsonElement element)) + return null; + + return JsonSerializer.Deserialize?>( + element, + ModelBase.SerializerOptions + ); + } + set + { + this.Properties["videoCodec"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + /// + /// Specifies the width of the output. If a value between 0 and 1 is provided, + /// it is treated as a percentage (e.g., `0.4` represents 40% of the original + /// width). You can also supply arithmetic expressions (e.g., `iw_div_2`). Width + /// transformation – [Images](https://imagekit.io/docs/image-resize-and-crop#width---w) + /// · [Videos](https://imagekit.io/docs/video-resize-and-crop#width---w) + /// + public Width? Width + { + get + { + if (!this.Properties.TryGetValue("width", out JsonElement element)) + return null; + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions); + } + set + { + this.Properties["width"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + /// + /// Focus using cropped image coordinates - X coordinate. See [Focus using cropped coordinates](https://imagekit.io/docs/image-resize-and-crop#example---focus-using-cropped-image-coordinates). + /// + public X? X + { + get + { + if (!this.Properties.TryGetValue("x", out JsonElement element)) + return null; + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions); + } + set + { + this.Properties["x"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + /// + /// Focus using cropped image coordinates - X center coordinate. See [Focus using + /// cropped coordinates](https://imagekit.io/docs/image-resize-and-crop#example---focus-using-cropped-image-coordinates). + /// + public XCenter? XCenter + { + get + { + if (!this.Properties.TryGetValue("xCenter", out JsonElement element)) + return null; + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions); + } + set + { + this.Properties["xCenter"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + /// + /// Focus using cropped image coordinates - Y coordinate. See [Focus using cropped coordinates](https://imagekit.io/docs/image-resize-and-crop#example---focus-using-cropped-image-coordinates). + /// + public Y? Y + { + get + { + if (!this.Properties.TryGetValue("y", out JsonElement element)) + return null; + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions); + } + set + { + this.Properties["y"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + /// + /// Focus using cropped image coordinates - Y center coordinate. See [Focus using + /// cropped coordinates](https://imagekit.io/docs/image-resize-and-crop#example---focus-using-cropped-image-coordinates). + /// + public YCenter? YCenter + { + get + { + if (!this.Properties.TryGetValue("yCenter", out JsonElement element)) + return null; + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions); + } + set + { + this.Properties["yCenter"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + /// + /// Accepts a numeric value that determines how much to zoom in or out of the + /// cropped area. It should be used in conjunction with fo-face or fo-. + /// See [Zoom](https://imagekit.io/docs/image-resize-and-crop#zoom---z). + /// + public double? Zoom + { + get + { + if (!this.Properties.TryGetValue("zoom", out JsonElement element)) + return null; + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions); + } + set + { + this.Properties["zoom"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + public override void Validate() + { + _ = this.AIChangeBackground; + this.AIDropShadow?.Validate(); + _ = this.AIEdit; + this.AIRemoveBackground?.Validate(); + this.AIRemoveBackgroundExternal?.Validate(); + this.AIRetouch?.Validate(); + this.AIUpscale?.Validate(); + this.AIVariation?.Validate(); + this.AspectRatio?.Validate(); + this.AudioCodec?.Validate(); + _ = this.Background; + _ = this.Blur; + _ = this.Border; + _ = this.ColorProfile; + this.ContrastStretch?.Validate(); + this.Crop?.Validate(); + this.CropMode?.Validate(); + _ = this.DefaultImage; + _ = this.Dpr; + this.Duration?.Validate(); + this.EndOffset?.Validate(); + this.Flip?.Validate(); + _ = this.Focus; + this.Format?.Validate(); + this.Gradient?.Validate(); + this.Grayscale?.Validate(); + this.Height?.Validate(); + _ = this.Lossless; + _ = this.Metadata; + _ = this.Named; + _ = this.Opacity; + _ = this.Original; + this.Overlay?.Validate(); + this.Page?.Validate(); + _ = this.Progressive; + _ = this.Quality; + this.Radius?.Validate(); + _ = this.Raw; + this.Rotation?.Validate(); + this.Shadow?.Validate(); + this.Sharpen?.Validate(); + this.StartOffset?.Validate(); + foreach (var item in this.StreamingResolutions ?? []) + { + item.Validate(); + } + this.Trim?.Validate(); + this.UnsharpMask?.Validate(); + this.VideoCodec?.Validate(); + this.Width?.Validate(); + this.X?.Validate(); + this.XCenter?.Validate(); + this.Y?.Validate(); + this.YCenter?.Validate(); + _ = this.Zoom; + } + + public Transformation() { } + +#pragma warning disable CS8618 + [SetsRequiredMembers] + Transformation(Dictionary properties) + { + Properties = properties; + } +#pragma warning restore CS8618 + + public static Transformation FromRawUnchecked(Dictionary properties) + { + return new(properties); + } +} diff --git a/src/Imagekit/Models/TransformationPosition.cs b/src/Imagekit/Models/TransformationPosition.cs new file mode 100644 index 00000000..2f6aba22 --- /dev/null +++ b/src/Imagekit/Models/TransformationPosition.cs @@ -0,0 +1,52 @@ +using System; +using System.Text.Json; +using System.Text.Json.Serialization; + +namespace Imagekit.Models; + +/// +/// By default, the transformation string is added as a query parameter in the URL, +/// e.g., `?tr=w-100,h-100`. If you want to add the transformation string in the +/// path of the URL, set this to `path`. Learn more in the [Transformations guide](https://imagekit.io/docs/transformations). +/// +[JsonConverter(typeof(TransformationPositionConverter))] +public enum TransformationPosition +{ + Path, + Query, +} + +sealed class TransformationPositionConverter : JsonConverter +{ + public override TransformationPosition Read( + ref Utf8JsonReader reader, + Type typeToConvert, + JsonSerializerOptions options + ) + { + return JsonSerializer.Deserialize(ref reader, options) switch + { + "path" => TransformationPosition.Path, + "query" => TransformationPosition.Query, + _ => (TransformationPosition)(-1), + }; + } + + public override void Write( + Utf8JsonWriter writer, + TransformationPosition value, + JsonSerializerOptions options + ) + { + JsonSerializer.Serialize( + writer, + value switch + { + TransformationPosition.Path => "path", + TransformationPosition.Query => "query", + _ => throw new ArgumentOutOfRangeException(nameof(value)), + }, + options + ); + } +} diff --git a/src/Imagekit/Models/TransformationProperties/AIDropShadow.cs b/src/Imagekit/Models/TransformationProperties/AIDropShadow.cs new file mode 100644 index 00000000..9298e807 --- /dev/null +++ b/src/Imagekit/Models/TransformationProperties/AIDropShadow.cs @@ -0,0 +1,122 @@ +using System; +using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; +using System.Text.Json; +using System.Text.Json.Serialization; +using AIDropShadowVariants = Imagekit.Models.TransformationProperties.AIDropShadowVariants; + +namespace Imagekit.Models.TransformationProperties; + +/// +/// Adds an AI-based drop shadow around a foreground object on a transparent or removed +/// background. Optionally, control the direction, elevation, and saturation of +/// the light source (e.g., `az-45` to change light direction). Pass `true` for the +/// default drop shadow, or provide a string for a custom drop shadow. Supported +/// inside overlay. See [AI Drop Shadow](https://imagekit.io/docs/ai-transformations#ai-drop-shadow-e-dropshadow). +/// +[JsonConverter(typeof(AIDropShadowConverter))] +public abstract record class AIDropShadow +{ + internal AIDropShadow() { } + + public static implicit operator AIDropShadow(string value) => + new AIDropShadowVariants::String(value); + + public bool TryPickTrue([NotNullWhen(true)] out JsonElement? value) + { + value = (this as AIDropShadowVariants::True)?.Value; + return value != null; + } + + public bool TryPickString([NotNullWhen(true)] out string? value) + { + value = (this as AIDropShadowVariants::String)?.Value; + return value != null; + } + + public void Switch( + Action true1, + Action @string + ) + { + switch (this) + { + case AIDropShadowVariants::True inner: + true1(inner); + break; + case AIDropShadowVariants::String inner: + @string(inner); + break; + default: + throw new InvalidOperationException(); + } + } + + public T Match( + Func true1, + Func @string + ) + { + return this switch + { + AIDropShadowVariants::True inner => true1(inner), + AIDropShadowVariants::String inner => @string(inner), + _ => throw new InvalidOperationException(), + }; + } + + public abstract void Validate(); +} + +sealed class AIDropShadowConverter : JsonConverter +{ + public override AIDropShadow? Read( + ref Utf8JsonReader reader, + Type typeToConvert, + JsonSerializerOptions options + ) + { + List exceptions = []; + + try + { + return new AIDropShadowVariants::True( + JsonSerializer.Deserialize(ref reader, options) + ); + } + catch (JsonException e) + { + exceptions.Add(e); + } + + try + { + var deserialized = JsonSerializer.Deserialize(ref reader, options); + if (deserialized != null) + { + return new AIDropShadowVariants::String(deserialized); + } + } + catch (JsonException e) + { + exceptions.Add(e); + } + + throw new AggregateException(exceptions); + } + + public override void Write( + Utf8JsonWriter writer, + AIDropShadow value, + JsonSerializerOptions options + ) + { + object variant = value switch + { + AIDropShadowVariants::True(var true1) => true1, + AIDropShadowVariants::String(var @string) => @string, + _ => throw new ArgumentOutOfRangeException(nameof(value)), + }; + JsonSerializer.Serialize(writer, variant, options); + } +} diff --git a/src/Imagekit/Models/TransformationProperties/AIDropShadowVariants/All.cs b/src/Imagekit/Models/TransformationProperties/AIDropShadowVariants/All.cs new file mode 100644 index 00000000..8efb0f9e --- /dev/null +++ b/src/Imagekit/Models/TransformationProperties/AIDropShadowVariants/All.cs @@ -0,0 +1,23 @@ +using System.Text.Json; + +namespace Imagekit.Models.TransformationProperties.AIDropShadowVariants; + +public sealed record class True(JsonElement Value) : AIDropShadow, IVariant +{ + public static True From(JsonElement value) + { + return new(value); + } + + public override void Validate() { } +} + +public sealed record class String(string Value) : AIDropShadow, IVariant +{ + public static String From(string value) + { + return new(value); + } + + public override void Validate() { } +} diff --git a/src/Imagekit/Models/TransformationProperties/AIRemoveBackground.cs b/src/Imagekit/Models/TransformationProperties/AIRemoveBackground.cs new file mode 100644 index 00000000..dae6c3e7 --- /dev/null +++ b/src/Imagekit/Models/TransformationProperties/AIRemoveBackground.cs @@ -0,0 +1,48 @@ +using System; +using System.Text.Json; +using System.Text.Json.Serialization; + +namespace Imagekit.Models.TransformationProperties; + +/// +/// Applies ImageKit's in-house background removal. Supported inside overlay. See +/// [AI Background Removal](https://imagekit.io/docs/ai-transformations#imagekit-background-removal-e-bgremove). +/// +[JsonConverter(typeof(AIRemoveBackgroundConverter))] +public enum AIRemoveBackground +{ + True, +} + +sealed class AIRemoveBackgroundConverter : JsonConverter +{ + public override AIRemoveBackground Read( + ref Utf8JsonReader reader, + Type typeToConvert, + JsonSerializerOptions options + ) + { + return JsonSerializer.Deserialize(ref reader, options) switch + { + true => AIRemoveBackground.True, + _ => (AIRemoveBackground)(-1), + }; + } + + public override void Write( + Utf8JsonWriter writer, + AIRemoveBackground value, + JsonSerializerOptions options + ) + { + JsonSerializer.Serialize( + writer, + value switch + { + AIRemoveBackground.True => true, + _ => throw new ArgumentOutOfRangeException(nameof(value)), + }, + options + ); + } +} diff --git a/src/Imagekit/Models/TransformationProperties/AIRemoveBackgroundExternal.cs b/src/Imagekit/Models/TransformationProperties/AIRemoveBackgroundExternal.cs new file mode 100644 index 00000000..263eeab4 --- /dev/null +++ b/src/Imagekit/Models/TransformationProperties/AIRemoveBackgroundExternal.cs @@ -0,0 +1,49 @@ +using System; +using System.Text.Json; +using System.Text.Json.Serialization; + +namespace Imagekit.Models.TransformationProperties; + +/// +/// Uses third-party background removal. Note: It is recommended to use aiRemoveBackground, +/// ImageKit's in-house solution, which is more cost-effective. Supported inside overlay. +/// See [External Background Removal](https://imagekit.io/docs/ai-transformations#background-removal-e-removedotbg). +/// +[JsonConverter(typeof(AIRemoveBackgroundExternalConverter))] +public enum AIRemoveBackgroundExternal +{ + True, +} + +sealed class AIRemoveBackgroundExternalConverter : JsonConverter +{ + public override AIRemoveBackgroundExternal Read( + ref Utf8JsonReader reader, + Type typeToConvert, + JsonSerializerOptions options + ) + { + return JsonSerializer.Deserialize(ref reader, options) switch + { + true => AIRemoveBackgroundExternal.True, + _ => (AIRemoveBackgroundExternal)(-1), + }; + } + + public override void Write( + Utf8JsonWriter writer, + AIRemoveBackgroundExternal value, + JsonSerializerOptions options + ) + { + JsonSerializer.Serialize( + writer, + value switch + { + AIRemoveBackgroundExternal.True => true, + _ => throw new ArgumentOutOfRangeException(nameof(value)), + }, + options + ); + } +} diff --git a/src/Imagekit/Models/TransformationProperties/AIRetouch.cs b/src/Imagekit/Models/TransformationProperties/AIRetouch.cs new file mode 100644 index 00000000..19472a80 --- /dev/null +++ b/src/Imagekit/Models/TransformationProperties/AIRetouch.cs @@ -0,0 +1,48 @@ +using System; +using System.Text.Json; +using System.Text.Json.Serialization; + +namespace Imagekit.Models.TransformationProperties; + +/// +/// Performs AI-based retouching to improve faces or product shots. Not supported +/// inside overlay. See [AI Retouch](https://imagekit.io/docs/ai-transformations#retouch-e-retouch). +/// +[JsonConverter(typeof(AIRetouchConverter))] +public enum AIRetouch +{ + True, +} + +sealed class AIRetouchConverter : JsonConverter +{ + public override AIRetouch Read( + ref Utf8JsonReader reader, + Type typeToConvert, + JsonSerializerOptions options + ) + { + return JsonSerializer.Deserialize(ref reader, options) switch + { + true => AIRetouch.True, + _ => (AIRetouch)(-1), + }; + } + + public override void Write( + Utf8JsonWriter writer, + AIRetouch value, + JsonSerializerOptions options + ) + { + JsonSerializer.Serialize( + writer, + value switch + { + AIRetouch.True => true, + _ => throw new ArgumentOutOfRangeException(nameof(value)), + }, + options + ); + } +} diff --git a/src/Imagekit/Models/TransformationProperties/AIUpscale.cs b/src/Imagekit/Models/TransformationProperties/AIUpscale.cs new file mode 100644 index 00000000..0ff1ab45 --- /dev/null +++ b/src/Imagekit/Models/TransformationProperties/AIUpscale.cs @@ -0,0 +1,48 @@ +using System; +using System.Text.Json; +using System.Text.Json.Serialization; + +namespace Imagekit.Models.TransformationProperties; + +/// +/// Upscales images beyond their original dimensions using AI. Not supported inside +/// overlay. See [AI Upscale](https://imagekit.io/docs/ai-transformations#upscale-e-upscale). +/// +[JsonConverter(typeof(AIUpscaleConverter))] +public enum AIUpscale +{ + True, +} + +sealed class AIUpscaleConverter : JsonConverter +{ + public override AIUpscale Read( + ref Utf8JsonReader reader, + Type typeToConvert, + JsonSerializerOptions options + ) + { + return JsonSerializer.Deserialize(ref reader, options) switch + { + true => AIUpscale.True, + _ => (AIUpscale)(-1), + }; + } + + public override void Write( + Utf8JsonWriter writer, + AIUpscale value, + JsonSerializerOptions options + ) + { + JsonSerializer.Serialize( + writer, + value switch + { + AIUpscale.True => true, + _ => throw new ArgumentOutOfRangeException(nameof(value)), + }, + options + ); + } +} diff --git a/src/Imagekit/Models/TransformationProperties/AIVariation.cs b/src/Imagekit/Models/TransformationProperties/AIVariation.cs new file mode 100644 index 00000000..4f6d49e0 --- /dev/null +++ b/src/Imagekit/Models/TransformationProperties/AIVariation.cs @@ -0,0 +1,50 @@ +using System; +using System.Text.Json; +using System.Text.Json.Serialization; + +namespace Imagekit.Models.TransformationProperties; + +/// +/// Generates a variation of an image using AI. This produces a new image with slight +/// variations from the original, such as changes in color, texture, and other visual +/// elements, while preserving the structure and essence of the original image. Not +/// supported inside overlay. See [AI Generate Variations](https://imagekit.io/docs/ai-transformations#generate-variations-of-an-image-e-genvar). +/// +[JsonConverter(typeof(AIVariationConverter))] +public enum AIVariation +{ + True, +} + +sealed class AIVariationConverter : JsonConverter +{ + public override AIVariation Read( + ref Utf8JsonReader reader, + Type typeToConvert, + JsonSerializerOptions options + ) + { + return JsonSerializer.Deserialize(ref reader, options) switch + { + true => AIVariation.True, + _ => (AIVariation)(-1), + }; + } + + public override void Write( + Utf8JsonWriter writer, + AIVariation value, + JsonSerializerOptions options + ) + { + JsonSerializer.Serialize( + writer, + value switch + { + AIVariation.True => true, + _ => throw new ArgumentOutOfRangeException(nameof(value)), + }, + options + ); + } +} diff --git a/src/Imagekit/Models/TransformationProperties/AspectRatio.cs b/src/Imagekit/Models/TransformationProperties/AspectRatio.cs new file mode 100644 index 00000000..6ce169b1 --- /dev/null +++ b/src/Imagekit/Models/TransformationProperties/AspectRatio.cs @@ -0,0 +1,123 @@ +using System; +using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; +using System.Text.Json; +using System.Text.Json.Serialization; +using AspectRatioVariants = Imagekit.Models.TransformationProperties.AspectRatioVariants; + +namespace Imagekit.Models.TransformationProperties; + +/// +/// Specifies the aspect ratio for the output, e.g., "ar-4-3". Typically used with +/// either width or height (but not both). For example: aspectRatio = `4:3`, `4_3`, +/// or an expression like `iar_div_2`. See [Image resize and crop – Aspect ratio](https://imagekit.io/docs/image-resize-and-crop#aspect-ratio---ar). +/// +[JsonConverter(typeof(AspectRatioConverter))] +public abstract record class AspectRatio +{ + internal AspectRatio() { } + + public static implicit operator AspectRatio(double value) => + new AspectRatioVariants::Double(value); + + public static implicit operator AspectRatio(string value) => + new AspectRatioVariants::String(value); + + public bool TryPickDouble([NotNullWhen(true)] out double? value) + { + value = (this as AspectRatioVariants::Double)?.Value; + return value != null; + } + + public bool TryPickString([NotNullWhen(true)] out string? value) + { + value = (this as AspectRatioVariants::String)?.Value; + return value != null; + } + + public void Switch( + Action @double, + Action @string + ) + { + switch (this) + { + case AspectRatioVariants::Double inner: + @double(inner); + break; + case AspectRatioVariants::String inner: + @string(inner); + break; + default: + throw new InvalidOperationException(); + } + } + + public T Match( + Func @double, + Func @string + ) + { + return this switch + { + AspectRatioVariants::Double inner => @double(inner), + AspectRatioVariants::String inner => @string(inner), + _ => throw new InvalidOperationException(), + }; + } + + public abstract void Validate(); +} + +sealed class AspectRatioConverter : JsonConverter +{ + public override AspectRatio? Read( + ref Utf8JsonReader reader, + Type typeToConvert, + JsonSerializerOptions options + ) + { + List exceptions = []; + + try + { + return new AspectRatioVariants::Double( + JsonSerializer.Deserialize(ref reader, options) + ); + } + catch (JsonException e) + { + exceptions.Add(e); + } + + try + { + var deserialized = JsonSerializer.Deserialize(ref reader, options); + if (deserialized != null) + { + return new AspectRatioVariants::String(deserialized); + } + } + catch (JsonException e) + { + exceptions.Add(e); + } + + throw new AggregateException(exceptions); + } + + public override void Write( + Utf8JsonWriter writer, + AspectRatio value, + JsonSerializerOptions options + ) + { + object variant = value switch + { + AspectRatioVariants::Double(var @double) => @double, + AspectRatioVariants::String(var @string) => @string, + _ => throw new ArgumentOutOfRangeException(nameof(value)), + }; + JsonSerializer.Serialize(writer, variant, options); + } +} diff --git a/src/Imagekit/Models/TransformationProperties/AspectRatioVariants/All.cs b/src/Imagekit/Models/TransformationProperties/AspectRatioVariants/All.cs new file mode 100644 index 00000000..d22b4b13 --- /dev/null +++ b/src/Imagekit/Models/TransformationProperties/AspectRatioVariants/All.cs @@ -0,0 +1,21 @@ +namespace Imagekit.Models.TransformationProperties.AspectRatioVariants; + +public sealed record class Double(double Value) : AspectRatio, IVariant +{ + public static Double From(double value) + { + return new(value); + } + + public override void Validate() { } +} + +public sealed record class String(string Value) : AspectRatio, IVariant +{ + public static String From(string value) + { + return new(value); + } + + public override void Validate() { } +} diff --git a/src/Imagekit/Models/TransformationProperties/AudioCodec.cs b/src/Imagekit/Models/TransformationProperties/AudioCodec.cs new file mode 100644 index 00000000..c5a861d3 --- /dev/null +++ b/src/Imagekit/Models/TransformationProperties/AudioCodec.cs @@ -0,0 +1,53 @@ +using System; +using System.Text.Json; +using System.Text.Json.Serialization; + +namespace Imagekit.Models.TransformationProperties; + +/// +/// Specifies the audio codec, e.g., `aac`, `opus`, or `none`. See [Audio codec](https://imagekit.io/docs/video-optimization#audio-codec---ac). +/// +[JsonConverter(typeof(AudioCodecConverter))] +public enum AudioCodec +{ + Aac, + Opus, + None, +} + +sealed class AudioCodecConverter : JsonConverter +{ + public override AudioCodec Read( + ref Utf8JsonReader reader, + Type typeToConvert, + JsonSerializerOptions options + ) + { + return JsonSerializer.Deserialize(ref reader, options) switch + { + "aac" => AudioCodec.Aac, + "opus" => AudioCodec.Opus, + "none" => AudioCodec.None, + _ => (AudioCodec)(-1), + }; + } + + public override void Write( + Utf8JsonWriter writer, + AudioCodec value, + JsonSerializerOptions options + ) + { + JsonSerializer.Serialize( + writer, + value switch + { + AudioCodec.Aac => "aac", + AudioCodec.Opus => "opus", + AudioCodec.None => "none", + _ => throw new ArgumentOutOfRangeException(nameof(value)), + }, + options + ); + } +} diff --git a/src/Imagekit/Models/TransformationProperties/ContrastStretch.cs b/src/Imagekit/Models/TransformationProperties/ContrastStretch.cs new file mode 100644 index 00000000..4ee3ec61 --- /dev/null +++ b/src/Imagekit/Models/TransformationProperties/ContrastStretch.cs @@ -0,0 +1,48 @@ +using System; +using System.Text.Json; +using System.Text.Json.Serialization; + +namespace Imagekit.Models.TransformationProperties; + +/// +/// Automatically enhances the contrast of an image (contrast stretch). See [Contrast +/// Stretch](https://imagekit.io/docs/effects-and-enhancements#contrast-stretch---e-contrast). +/// +[JsonConverter(typeof(ContrastStretchConverter))] +public enum ContrastStretch +{ + True, +} + +sealed class ContrastStretchConverter : JsonConverter +{ + public override ContrastStretch Read( + ref Utf8JsonReader reader, + Type typeToConvert, + JsonSerializerOptions options + ) + { + return JsonSerializer.Deserialize(ref reader, options) switch + { + true => ContrastStretch.True, + _ => (ContrastStretch)(-1), + }; + } + + public override void Write( + Utf8JsonWriter writer, + ContrastStretch value, + JsonSerializerOptions options + ) + { + JsonSerializer.Serialize( + writer, + value switch + { + ContrastStretch.True => true, + _ => throw new ArgumentOutOfRangeException(nameof(value)), + }, + options + ); + } +} diff --git a/src/Imagekit/Models/TransformationProperties/Crop.cs b/src/Imagekit/Models/TransformationProperties/Crop.cs new file mode 100644 index 00000000..eb549d7a --- /dev/null +++ b/src/Imagekit/Models/TransformationProperties/Crop.cs @@ -0,0 +1,55 @@ +using System; +using System.Text.Json; +using System.Text.Json.Serialization; + +namespace Imagekit.Models.TransformationProperties; + +/// +/// Crop modes for image resizing. See [Crop modes & focus](https://imagekit.io/docs/image-resize-and-crop#crop-crop-modes--focus). +/// +[JsonConverter(typeof(CropConverter))] +public enum Crop +{ + Force, + AtMax, + AtMaxEnlarge, + AtLeast, + MaintainRatio, +} + +sealed class CropConverter : JsonConverter +{ + public override Crop Read( + ref Utf8JsonReader reader, + Type typeToConvert, + JsonSerializerOptions options + ) + { + return JsonSerializer.Deserialize(ref reader, options) switch + { + "force" => Crop.Force, + "at_max" => Crop.AtMax, + "at_max_enlarge" => Crop.AtMaxEnlarge, + "at_least" => Crop.AtLeast, + "maintain_ratio" => Crop.MaintainRatio, + _ => (Crop)(-1), + }; + } + + public override void Write(Utf8JsonWriter writer, Crop value, JsonSerializerOptions options) + { + JsonSerializer.Serialize( + writer, + value switch + { + Crop.Force => "force", + Crop.AtMax => "at_max", + Crop.AtMaxEnlarge => "at_max_enlarge", + Crop.AtLeast => "at_least", + Crop.MaintainRatio => "maintain_ratio", + _ => throw new ArgumentOutOfRangeException(nameof(value)), + }, + options + ); + } +} diff --git a/src/Imagekit/Models/TransformationProperties/CropMode.cs b/src/Imagekit/Models/TransformationProperties/CropMode.cs new file mode 100644 index 00000000..ec058dc1 --- /dev/null +++ b/src/Imagekit/Models/TransformationProperties/CropMode.cs @@ -0,0 +1,49 @@ +using System; +using System.Text.Json; +using System.Text.Json.Serialization; + +namespace Imagekit.Models.TransformationProperties; + +/// +/// Additional crop modes for image resizing. See [Crop modes & focus](https://imagekit.io/docs/image-resize-and-crop#crop-crop-modes--focus). +/// +[JsonConverter(typeof(CropModeConverter))] +public enum CropMode +{ + PadResize, + Extract, + PadExtract, +} + +sealed class CropModeConverter : JsonConverter +{ + public override CropMode Read( + ref Utf8JsonReader reader, + Type typeToConvert, + JsonSerializerOptions options + ) + { + return JsonSerializer.Deserialize(ref reader, options) switch + { + "pad_resize" => CropMode.PadResize, + "extract" => CropMode.Extract, + "pad_extract" => CropMode.PadExtract, + _ => (CropMode)(-1), + }; + } + + public override void Write(Utf8JsonWriter writer, CropMode value, JsonSerializerOptions options) + { + JsonSerializer.Serialize( + writer, + value switch + { + CropMode.PadResize => "pad_resize", + CropMode.Extract => "extract", + CropMode.PadExtract => "pad_extract", + _ => throw new ArgumentOutOfRangeException(nameof(value)), + }, + options + ); + } +} diff --git a/src/Imagekit/Models/TransformationProperties/Duration.cs b/src/Imagekit/Models/TransformationProperties/Duration.cs new file mode 100644 index 00000000..c1cd0a7b --- /dev/null +++ b/src/Imagekit/Models/TransformationProperties/Duration.cs @@ -0,0 +1,117 @@ +using System; +using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; +using System.Text.Json; +using System.Text.Json.Serialization; +using DurationVariants = Imagekit.Models.TransformationProperties.DurationVariants; + +namespace Imagekit.Models.TransformationProperties; + +/// +/// Specifies the duration (in seconds) for trimming videos, e.g., `5` or `10.5`. +/// Typically used with startOffset to indicate the length from the start offset. +/// Arithmetic expressions are supported. See [Trim videos – Duration](https://imagekit.io/docs/trim-videos#duration---du). +/// +[JsonConverter(typeof(DurationConverter))] +public abstract record class Duration +{ + internal Duration() { } + + public static implicit operator Duration(double value) => new DurationVariants::Double(value); + + public static implicit operator Duration(string value) => new DurationVariants::String(value); + + public bool TryPickDouble([NotNullWhen(true)] out double? value) + { + value = (this as DurationVariants::Double)?.Value; + return value != null; + } + + public bool TryPickString([NotNullWhen(true)] out string? value) + { + value = (this as DurationVariants::String)?.Value; + return value != null; + } + + public void Switch( + Action @double, + Action @string + ) + { + switch (this) + { + case DurationVariants::Double inner: + @double(inner); + break; + case DurationVariants::String inner: + @string(inner); + break; + default: + throw new InvalidOperationException(); + } + } + + public T Match( + Func @double, + Func @string + ) + { + return this switch + { + DurationVariants::Double inner => @double(inner), + DurationVariants::String inner => @string(inner), + _ => throw new InvalidOperationException(), + }; + } + + public abstract void Validate(); +} + +sealed class DurationConverter : JsonConverter +{ + public override Duration? Read( + ref Utf8JsonReader reader, + Type typeToConvert, + JsonSerializerOptions options + ) + { + List exceptions = []; + + try + { + return new DurationVariants::Double( + JsonSerializer.Deserialize(ref reader, options) + ); + } + catch (JsonException e) + { + exceptions.Add(e); + } + + try + { + var deserialized = JsonSerializer.Deserialize(ref reader, options); + if (deserialized != null) + { + return new DurationVariants::String(deserialized); + } + } + catch (JsonException e) + { + exceptions.Add(e); + } + + throw new AggregateException(exceptions); + } + + public override void Write(Utf8JsonWriter writer, Duration value, JsonSerializerOptions options) + { + object variant = value switch + { + DurationVariants::Double(var @double) => @double, + DurationVariants::String(var @string) => @string, + _ => throw new ArgumentOutOfRangeException(nameof(value)), + }; + JsonSerializer.Serialize(writer, variant, options); + } +} diff --git a/src/Imagekit/Models/TransformationProperties/DurationVariants/All.cs b/src/Imagekit/Models/TransformationProperties/DurationVariants/All.cs new file mode 100644 index 00000000..0aafb7f0 --- /dev/null +++ b/src/Imagekit/Models/TransformationProperties/DurationVariants/All.cs @@ -0,0 +1,21 @@ +namespace Imagekit.Models.TransformationProperties.DurationVariants; + +public sealed record class Double(double Value) : Duration, IVariant +{ + public static Double From(double value) + { + return new(value); + } + + public override void Validate() { } +} + +public sealed record class String(string Value) : Duration, IVariant +{ + public static String From(string value) + { + return new(value); + } + + public override void Validate() { } +} diff --git a/src/Imagekit/Models/TransformationProperties/EndOffset.cs b/src/Imagekit/Models/TransformationProperties/EndOffset.cs new file mode 100644 index 00000000..2badea7b --- /dev/null +++ b/src/Imagekit/Models/TransformationProperties/EndOffset.cs @@ -0,0 +1,121 @@ +using System; +using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; +using System.Text.Json; +using System.Text.Json.Serialization; +using EndOffsetVariants = Imagekit.Models.TransformationProperties.EndOffsetVariants; + +namespace Imagekit.Models.TransformationProperties; + +/// +/// Specifies the end offset (in seconds) for trimming videos, e.g., `5` or `10.5`. +/// Typically used with startOffset to define a time window. Arithmetic expressions +/// are supported. See [Trim videos – End offset](https://imagekit.io/docs/trim-videos#end-offset---eo). +/// +[JsonConverter(typeof(EndOffsetConverter))] +public abstract record class EndOffset +{ + internal EndOffset() { } + + public static implicit operator EndOffset(double value) => new EndOffsetVariants::Double(value); + + public static implicit operator EndOffset(string value) => new EndOffsetVariants::String(value); + + public bool TryPickDouble([NotNullWhen(true)] out double? value) + { + value = (this as EndOffsetVariants::Double)?.Value; + return value != null; + } + + public bool TryPickString([NotNullWhen(true)] out string? value) + { + value = (this as EndOffsetVariants::String)?.Value; + return value != null; + } + + public void Switch( + Action @double, + Action @string + ) + { + switch (this) + { + case EndOffsetVariants::Double inner: + @double(inner); + break; + case EndOffsetVariants::String inner: + @string(inner); + break; + default: + throw new InvalidOperationException(); + } + } + + public T Match( + Func @double, + Func @string + ) + { + return this switch + { + EndOffsetVariants::Double inner => @double(inner), + EndOffsetVariants::String inner => @string(inner), + _ => throw new InvalidOperationException(), + }; + } + + public abstract void Validate(); +} + +sealed class EndOffsetConverter : JsonConverter +{ + public override EndOffset? Read( + ref Utf8JsonReader reader, + Type typeToConvert, + JsonSerializerOptions options + ) + { + List exceptions = []; + + try + { + return new EndOffsetVariants::Double( + JsonSerializer.Deserialize(ref reader, options) + ); + } + catch (JsonException e) + { + exceptions.Add(e); + } + + try + { + var deserialized = JsonSerializer.Deserialize(ref reader, options); + if (deserialized != null) + { + return new EndOffsetVariants::String(deserialized); + } + } + catch (JsonException e) + { + exceptions.Add(e); + } + + throw new AggregateException(exceptions); + } + + public override void Write( + Utf8JsonWriter writer, + EndOffset value, + JsonSerializerOptions options + ) + { + object variant = value switch + { + EndOffsetVariants::Double(var @double) => @double, + EndOffsetVariants::String(var @string) => @string, + _ => throw new ArgumentOutOfRangeException(nameof(value)), + }; + JsonSerializer.Serialize(writer, variant, options); + } +} diff --git a/src/Imagekit/Models/TransformationProperties/EndOffsetVariants/All.cs b/src/Imagekit/Models/TransformationProperties/EndOffsetVariants/All.cs new file mode 100644 index 00000000..062c3931 --- /dev/null +++ b/src/Imagekit/Models/TransformationProperties/EndOffsetVariants/All.cs @@ -0,0 +1,21 @@ +namespace Imagekit.Models.TransformationProperties.EndOffsetVariants; + +public sealed record class Double(double Value) : EndOffset, IVariant +{ + public static Double From(double value) + { + return new(value); + } + + public override void Validate() { } +} + +public sealed record class String(string Value) : EndOffset, IVariant +{ + public static String From(string value) + { + return new(value); + } + + public override void Validate() { } +} diff --git a/src/Imagekit/Models/TransformationProperties/Flip.cs b/src/Imagekit/Models/TransformationProperties/Flip.cs new file mode 100644 index 00000000..581d36a2 --- /dev/null +++ b/src/Imagekit/Models/TransformationProperties/Flip.cs @@ -0,0 +1,54 @@ +using System; +using System.Text.Json; +using System.Text.Json.Serialization; + +namespace Imagekit.Models.TransformationProperties; + +/// +/// Flips or mirrors an image either horizontally, vertically, or both. Acceptable +/// values: `h` (horizontal), `v` (vertical), `h_v` (horizontal and vertical), or +/// `v_h`. See [Flip](https://imagekit.io/docs/effects-and-enhancements#flip---fl). +/// +[JsonConverter(typeof(FlipConverter))] +public enum Flip +{ + H, + V, + HV, + VH, +} + +sealed class FlipConverter : JsonConverter +{ + public override Flip Read( + ref Utf8JsonReader reader, + Type typeToConvert, + JsonSerializerOptions options + ) + { + return JsonSerializer.Deserialize(ref reader, options) switch + { + "h" => Flip.H, + "v" => Flip.V, + "h_v" => Flip.HV, + "v_h" => Flip.VH, + _ => (Flip)(-1), + }; + } + + public override void Write(Utf8JsonWriter writer, Flip value, JsonSerializerOptions options) + { + JsonSerializer.Serialize( + writer, + value switch + { + Flip.H => "h", + Flip.V => "v", + Flip.HV => "h_v", + Flip.VH => "v_h", + _ => throw new ArgumentOutOfRangeException(nameof(value)), + }, + options + ); + } +} diff --git a/src/Imagekit/Models/TransformationProperties/Format.cs b/src/Imagekit/Models/TransformationProperties/Format.cs new file mode 100644 index 00000000..261f1417 --- /dev/null +++ b/src/Imagekit/Models/TransformationProperties/Format.cs @@ -0,0 +1,78 @@ +using System; +using System.Text.Json; +using System.Text.Json.Serialization; + +namespace Imagekit.Models.TransformationProperties; + +/// +/// Specifies the output format for images or videos, e.g., `jpg`, `png`, `webp`, +/// `mp4`, or `auto`. You can also pass `orig` for images to return the original +/// format. ImageKit automatically delivers images and videos in the optimal format +/// based on device support unless overridden by the dashboard settings or the format +/// parameter. See [Image format](https://imagekit.io/docs/image-optimization#format---f) +/// and [Video format](https://imagekit.io/docs/video-optimization#format---f). +/// +[JsonConverter(typeof(FormatConverter))] +public enum Format +{ + Auto, + Webp, + Jpg, + Jpeg, + Png, + Gif, + Svg, + MP4, + Webm, + Avif, + Orig, +} + +sealed class FormatConverter : JsonConverter +{ + public override Format Read( + ref Utf8JsonReader reader, + Type typeToConvert, + JsonSerializerOptions options + ) + { + return JsonSerializer.Deserialize(ref reader, options) switch + { + "auto" => Format.Auto, + "webp" => Format.Webp, + "jpg" => Format.Jpg, + "jpeg" => Format.Jpeg, + "png" => Format.Png, + "gif" => Format.Gif, + "svg" => Format.Svg, + "mp4" => Format.MP4, + "webm" => Format.Webm, + "avif" => Format.Avif, + "orig" => Format.Orig, + _ => (Format)(-1), + }; + } + + public override void Write(Utf8JsonWriter writer, Format value, JsonSerializerOptions options) + { + JsonSerializer.Serialize( + writer, + value switch + { + Format.Auto => "auto", + Format.Webp => "webp", + Format.Jpg => "jpg", + Format.Jpeg => "jpeg", + Format.Png => "png", + Format.Gif => "gif", + Format.Svg => "svg", + Format.MP4 => "mp4", + Format.Webm => "webm", + Format.Avif => "avif", + Format.Orig => "orig", + _ => throw new ArgumentOutOfRangeException(nameof(value)), + }, + options + ); + } +} diff --git a/src/Imagekit/Models/TransformationProperties/Gradient.cs b/src/Imagekit/Models/TransformationProperties/Gradient.cs new file mode 100644 index 00000000..b1bbef64 --- /dev/null +++ b/src/Imagekit/Models/TransformationProperties/Gradient.cs @@ -0,0 +1,114 @@ +using System; +using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; +using System.Text.Json; +using System.Text.Json.Serialization; +using GradientVariants = Imagekit.Models.TransformationProperties.GradientVariants; + +namespace Imagekit.Models.TransformationProperties; + +/// +/// Creates a linear gradient with two colors. Pass `true` for a default gradient, +/// or provide a string for a custom gradient. See [Gradient](https://imagekit.io/docs/effects-and-enhancements#gradient---e-gradient). +/// +[JsonConverter(typeof(GradientConverter))] +public abstract record class Gradient +{ + internal Gradient() { } + + public static implicit operator Gradient(string value) => new GradientVariants::String(value); + + public bool TryPickTrue([NotNullWhen(true)] out JsonElement? value) + { + value = (this as GradientVariants::True)?.Value; + return value != null; + } + + public bool TryPickString([NotNullWhen(true)] out string? value) + { + value = (this as GradientVariants::String)?.Value; + return value != null; + } + + public void Switch( + Action true1, + Action @string + ) + { + switch (this) + { + case GradientVariants::True inner: + true1(inner); + break; + case GradientVariants::String inner: + @string(inner); + break; + default: + throw new InvalidOperationException(); + } + } + + public T Match( + Func true1, + Func @string + ) + { + return this switch + { + GradientVariants::True inner => true1(inner), + GradientVariants::String inner => @string(inner), + _ => throw new InvalidOperationException(), + }; + } + + public abstract void Validate(); +} + +sealed class GradientConverter : JsonConverter +{ + public override Gradient? Read( + ref Utf8JsonReader reader, + Type typeToConvert, + JsonSerializerOptions options + ) + { + List exceptions = []; + + try + { + return new GradientVariants::True( + JsonSerializer.Deserialize(ref reader, options) + ); + } + catch (JsonException e) + { + exceptions.Add(e); + } + + try + { + var deserialized = JsonSerializer.Deserialize(ref reader, options); + if (deserialized != null) + { + return new GradientVariants::String(deserialized); + } + } + catch (JsonException e) + { + exceptions.Add(e); + } + + throw new AggregateException(exceptions); + } + + public override void Write(Utf8JsonWriter writer, Gradient value, JsonSerializerOptions options) + { + object variant = value switch + { + GradientVariants::True(var true1) => true1, + GradientVariants::String(var @string) => @string, + _ => throw new ArgumentOutOfRangeException(nameof(value)), + }; + JsonSerializer.Serialize(writer, variant, options); + } +} diff --git a/src/Imagekit/Models/TransformationProperties/GradientVariants/All.cs b/src/Imagekit/Models/TransformationProperties/GradientVariants/All.cs new file mode 100644 index 00000000..6fc6bc18 --- /dev/null +++ b/src/Imagekit/Models/TransformationProperties/GradientVariants/All.cs @@ -0,0 +1,23 @@ +using System.Text.Json; + +namespace Imagekit.Models.TransformationProperties.GradientVariants; + +public sealed record class True(JsonElement Value) : Gradient, IVariant +{ + public static True From(JsonElement value) + { + return new(value); + } + + public override void Validate() { } +} + +public sealed record class String(string Value) : Gradient, IVariant +{ + public static String From(string value) + { + return new(value); + } + + public override void Validate() { } +} diff --git a/src/Imagekit/Models/TransformationProperties/Grayscale.cs b/src/Imagekit/Models/TransformationProperties/Grayscale.cs new file mode 100644 index 00000000..4dac211d --- /dev/null +++ b/src/Imagekit/Models/TransformationProperties/Grayscale.cs @@ -0,0 +1,47 @@ +using System; +using System.Text.Json; +using System.Text.Json.Serialization; + +namespace Imagekit.Models.TransformationProperties; + +/// +/// Enables a grayscale effect for images. See [Grayscale](https://imagekit.io/docs/effects-and-enhancements#grayscale---e-grayscale). +/// +[JsonConverter(typeof(GrayscaleConverter))] +public enum Grayscale +{ + True, +} + +sealed class GrayscaleConverter : JsonConverter +{ + public override Grayscale Read( + ref Utf8JsonReader reader, + Type typeToConvert, + JsonSerializerOptions options + ) + { + return JsonSerializer.Deserialize(ref reader, options) switch + { + true => Grayscale.True, + _ => (Grayscale)(-1), + }; + } + + public override void Write( + Utf8JsonWriter writer, + Grayscale value, + JsonSerializerOptions options + ) + { + JsonSerializer.Serialize( + writer, + value switch + { + Grayscale.True => true, + _ => throw new ArgumentOutOfRangeException(nameof(value)), + }, + options + ); + } +} diff --git a/src/Imagekit/Models/TransformationProperties/Height.cs b/src/Imagekit/Models/TransformationProperties/Height.cs new file mode 100644 index 00000000..8c42abb6 --- /dev/null +++ b/src/Imagekit/Models/TransformationProperties/Height.cs @@ -0,0 +1,118 @@ +using System; +using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; +using System.Text.Json; +using System.Text.Json.Serialization; +using HeightVariants = Imagekit.Models.TransformationProperties.HeightVariants; + +namespace Imagekit.Models.TransformationProperties; + +/// +/// Specifies the height of the output. If a value between 0 and 1 is provided, it +/// is treated as a percentage (e.g., `0.5` represents 50% of the original height). +/// You can also supply arithmetic expressions (e.g., `ih_mul_0.5`). Height transformation +/// – [Images](https://imagekit.io/docs/image-resize-and-crop#height---h) · [Videos](https://imagekit.io/docs/video-resize-and-crop#height---h) +/// +[JsonConverter(typeof(HeightConverter))] +public abstract record class Height +{ + internal Height() { } + + public static implicit operator Height(double value) => new HeightVariants::Double(value); + + public static implicit operator Height(string value) => new HeightVariants::String(value); + + public bool TryPickDouble([NotNullWhen(true)] out double? value) + { + value = (this as HeightVariants::Double)?.Value; + return value != null; + } + + public bool TryPickString([NotNullWhen(true)] out string? value) + { + value = (this as HeightVariants::String)?.Value; + return value != null; + } + + public void Switch( + Action @double, + Action @string + ) + { + switch (this) + { + case HeightVariants::Double inner: + @double(inner); + break; + case HeightVariants::String inner: + @string(inner); + break; + default: + throw new InvalidOperationException(); + } + } + + public T Match( + Func @double, + Func @string + ) + { + return this switch + { + HeightVariants::Double inner => @double(inner), + HeightVariants::String inner => @string(inner), + _ => throw new InvalidOperationException(), + }; + } + + public abstract void Validate(); +} + +sealed class HeightConverter : JsonConverter +{ + public override Height? Read( + ref Utf8JsonReader reader, + Type typeToConvert, + JsonSerializerOptions options + ) + { + List exceptions = []; + + try + { + return new HeightVariants::Double( + JsonSerializer.Deserialize(ref reader, options) + ); + } + catch (JsonException e) + { + exceptions.Add(e); + } + + try + { + var deserialized = JsonSerializer.Deserialize(ref reader, options); + if (deserialized != null) + { + return new HeightVariants::String(deserialized); + } + } + catch (JsonException e) + { + exceptions.Add(e); + } + + throw new AggregateException(exceptions); + } + + public override void Write(Utf8JsonWriter writer, Height value, JsonSerializerOptions options) + { + object variant = value switch + { + HeightVariants::Double(var @double) => @double, + HeightVariants::String(var @string) => @string, + _ => throw new ArgumentOutOfRangeException(nameof(value)), + }; + JsonSerializer.Serialize(writer, variant, options); + } +} diff --git a/src/Imagekit/Models/TransformationProperties/HeightVariants/All.cs b/src/Imagekit/Models/TransformationProperties/HeightVariants/All.cs new file mode 100644 index 00000000..52dece91 --- /dev/null +++ b/src/Imagekit/Models/TransformationProperties/HeightVariants/All.cs @@ -0,0 +1,21 @@ +namespace Imagekit.Models.TransformationProperties.HeightVariants; + +public sealed record class Double(double Value) : Height, IVariant +{ + public static Double From(double value) + { + return new(value); + } + + public override void Validate() { } +} + +public sealed record class String(string Value) : Height, IVariant +{ + public static String From(string value) + { + return new(value); + } + + public override void Validate() { } +} diff --git a/src/Imagekit/Models/TransformationProperties/Page.cs b/src/Imagekit/Models/TransformationProperties/Page.cs new file mode 100644 index 00000000..8774faaa --- /dev/null +++ b/src/Imagekit/Models/TransformationProperties/Page.cs @@ -0,0 +1,112 @@ +using System; +using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; +using System.Text.Json; +using System.Text.Json.Serialization; +using PageVariants = Imagekit.Models.TransformationProperties.PageVariants; + +namespace Imagekit.Models.TransformationProperties; + +/// +/// Extracts a specific page or frame from multi-page or layered files (PDF, PSD, +/// AI). For example, specify by number (e.g., `2`), a range (e.g., `3-4` for the +/// 2nd and 3rd layers), or by name (e.g., `name-layer-4` for a PSD layer). See [Thumbnail +/// extraction](https://imagekit.io/docs/vector-and-animated-images#get-thumbnail-from-psd-pdf-ai-eps-and-animated-files). +/// +[JsonConverter(typeof(PageConverter))] +public abstract record class Page +{ + internal Page() { } + + public static implicit operator Page(double value) => new PageVariants::Double(value); + + public static implicit operator Page(string value) => new PageVariants::String(value); + + public bool TryPickDouble([NotNullWhen(true)] out double? value) + { + value = (this as PageVariants::Double)?.Value; + return value != null; + } + + public bool TryPickString([NotNullWhen(true)] out string? value) + { + value = (this as PageVariants::String)?.Value; + return value != null; + } + + public void Switch(Action @double, Action @string) + { + switch (this) + { + case PageVariants::Double inner: + @double(inner); + break; + case PageVariants::String inner: + @string(inner); + break; + default: + throw new InvalidOperationException(); + } + } + + public T Match(Func @double, Func @string) + { + return this switch + { + PageVariants::Double inner => @double(inner), + PageVariants::String inner => @string(inner), + _ => throw new InvalidOperationException(), + }; + } + + public abstract void Validate(); +} + +sealed class PageConverter : JsonConverter +{ + public override Page? Read( + ref Utf8JsonReader reader, + Type typeToConvert, + JsonSerializerOptions options + ) + { + List exceptions = []; + + try + { + return new PageVariants::Double( + JsonSerializer.Deserialize(ref reader, options) + ); + } + catch (JsonException e) + { + exceptions.Add(e); + } + + try + { + var deserialized = JsonSerializer.Deserialize(ref reader, options); + if (deserialized != null) + { + return new PageVariants::String(deserialized); + } + } + catch (JsonException e) + { + exceptions.Add(e); + } + + throw new AggregateException(exceptions); + } + + public override void Write(Utf8JsonWriter writer, Page value, JsonSerializerOptions options) + { + object variant = value switch + { + PageVariants::Double(var @double) => @double, + PageVariants::String(var @string) => @string, + _ => throw new ArgumentOutOfRangeException(nameof(value)), + }; + JsonSerializer.Serialize(writer, variant, options); + } +} diff --git a/src/Imagekit/Models/TransformationProperties/PageVariants/All.cs b/src/Imagekit/Models/TransformationProperties/PageVariants/All.cs new file mode 100644 index 00000000..ef065b2d --- /dev/null +++ b/src/Imagekit/Models/TransformationProperties/PageVariants/All.cs @@ -0,0 +1,21 @@ +namespace Imagekit.Models.TransformationProperties.PageVariants; + +public sealed record class Double(double Value) : Page, IVariant +{ + public static Double From(double value) + { + return new(value); + } + + public override void Validate() { } +} + +public sealed record class String(string Value) : Page, IVariant +{ + public static String From(string value) + { + return new(value); + } + + public override void Validate() { } +} diff --git a/src/Imagekit/Models/TransformationProperties/Radius.cs b/src/Imagekit/Models/TransformationProperties/Radius.cs new file mode 100644 index 00000000..af6dca7d --- /dev/null +++ b/src/Imagekit/Models/TransformationProperties/Radius.cs @@ -0,0 +1,106 @@ +using System; +using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; +using System.Text.Json; +using System.Text.Json.Serialization; +using RadiusVariants = Imagekit.Models.TransformationProperties.RadiusVariants; + +namespace Imagekit.Models.TransformationProperties; + +/// +/// Specifies the corner radius for rounded corners (e.g., 20) or `max` for circular +/// or oval shape. See [Radius](https://imagekit.io/docs/effects-and-enhancements#radius---r). +/// +[JsonConverter(typeof(RadiusConverter))] +public abstract record class Radius +{ + internal Radius() { } + + public static implicit operator Radius(double value) => new RadiusVariants::Double(value); + + public bool TryPickDouble([NotNullWhen(true)] out double? value) + { + value = (this as RadiusVariants::Double)?.Value; + return value != null; + } + + public bool TryPickMax([NotNullWhen(true)] out JsonElement? value) + { + value = (this as RadiusVariants::Max)?.Value; + return value != null; + } + + public void Switch(Action @double, Action max) + { + switch (this) + { + case RadiusVariants::Double inner: + @double(inner); + break; + case RadiusVariants::Max inner: + max(inner); + break; + default: + throw new InvalidOperationException(); + } + } + + public T Match(Func @double, Func max) + { + return this switch + { + RadiusVariants::Double inner => @double(inner), + RadiusVariants::Max inner => max(inner), + _ => throw new InvalidOperationException(), + }; + } + + public abstract void Validate(); +} + +sealed class RadiusConverter : JsonConverter +{ + public override Radius? Read( + ref Utf8JsonReader reader, + Type typeToConvert, + JsonSerializerOptions options + ) + { + List exceptions = []; + + try + { + return new RadiusVariants::Max( + JsonSerializer.Deserialize(ref reader, options) + ); + } + catch (JsonException e) + { + exceptions.Add(e); + } + + try + { + return new RadiusVariants::Double( + JsonSerializer.Deserialize(ref reader, options) + ); + } + catch (JsonException e) + { + exceptions.Add(e); + } + + throw new AggregateException(exceptions); + } + + public override void Write(Utf8JsonWriter writer, Radius value, JsonSerializerOptions options) + { + object variant = value switch + { + RadiusVariants::Double(var @double) => @double, + RadiusVariants::Max(var max) => max, + _ => throw new ArgumentOutOfRangeException(nameof(value)), + }; + JsonSerializer.Serialize(writer, variant, options); + } +} diff --git a/src/Imagekit/Models/TransformationProperties/RadiusVariants/All.cs b/src/Imagekit/Models/TransformationProperties/RadiusVariants/All.cs new file mode 100644 index 00000000..78448ae7 --- /dev/null +++ b/src/Imagekit/Models/TransformationProperties/RadiusVariants/All.cs @@ -0,0 +1,23 @@ +using System.Text.Json; + +namespace Imagekit.Models.TransformationProperties.RadiusVariants; + +public sealed record class Double(double Value) : Radius, IVariant +{ + public static Double From(double value) + { + return new(value); + } + + public override void Validate() { } +} + +public sealed record class Max(JsonElement Value) : Radius, IVariant +{ + public static Max From(JsonElement value) + { + return new(value); + } + + public override void Validate() { } +} diff --git a/src/Imagekit/Models/TransformationProperties/Rotation.cs b/src/Imagekit/Models/TransformationProperties/Rotation.cs new file mode 100644 index 00000000..60a011aa --- /dev/null +++ b/src/Imagekit/Models/TransformationProperties/Rotation.cs @@ -0,0 +1,118 @@ +using System; +using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; +using System.Text.Json; +using System.Text.Json.Serialization; +using RotationVariants = Imagekit.Models.TransformationProperties.RotationVariants; + +namespace Imagekit.Models.TransformationProperties; + +/// +/// Specifies the rotation angle in degrees. Positive values rotate the image clockwise; +/// you can also use, for example, `N40` for counterclockwise rotation or `auto` +/// to use the orientation specified in the image's EXIF data. For videos, only the +/// following values are supported: 0, 90, 180, 270, or 360. See [Rotate](https://imagekit.io/docs/effects-and-enhancements#rotate---rt). +/// +[JsonConverter(typeof(RotationConverter))] +public abstract record class Rotation +{ + internal Rotation() { } + + public static implicit operator Rotation(double value) => new RotationVariants::Double(value); + + public static implicit operator Rotation(string value) => new RotationVariants::String(value); + + public bool TryPickDouble([NotNullWhen(true)] out double? value) + { + value = (this as RotationVariants::Double)?.Value; + return value != null; + } + + public bool TryPickString([NotNullWhen(true)] out string? value) + { + value = (this as RotationVariants::String)?.Value; + return value != null; + } + + public void Switch( + Action @double, + Action @string + ) + { + switch (this) + { + case RotationVariants::Double inner: + @double(inner); + break; + case RotationVariants::String inner: + @string(inner); + break; + default: + throw new InvalidOperationException(); + } + } + + public T Match( + Func @double, + Func @string + ) + { + return this switch + { + RotationVariants::Double inner => @double(inner), + RotationVariants::String inner => @string(inner), + _ => throw new InvalidOperationException(), + }; + } + + public abstract void Validate(); +} + +sealed class RotationConverter : JsonConverter +{ + public override Rotation? Read( + ref Utf8JsonReader reader, + Type typeToConvert, + JsonSerializerOptions options + ) + { + List exceptions = []; + + try + { + return new RotationVariants::Double( + JsonSerializer.Deserialize(ref reader, options) + ); + } + catch (JsonException e) + { + exceptions.Add(e); + } + + try + { + var deserialized = JsonSerializer.Deserialize(ref reader, options); + if (deserialized != null) + { + return new RotationVariants::String(deserialized); + } + } + catch (JsonException e) + { + exceptions.Add(e); + } + + throw new AggregateException(exceptions); + } + + public override void Write(Utf8JsonWriter writer, Rotation value, JsonSerializerOptions options) + { + object variant = value switch + { + RotationVariants::Double(var @double) => @double, + RotationVariants::String(var @string) => @string, + _ => throw new ArgumentOutOfRangeException(nameof(value)), + }; + JsonSerializer.Serialize(writer, variant, options); + } +} diff --git a/src/Imagekit/Models/TransformationProperties/RotationVariants/All.cs b/src/Imagekit/Models/TransformationProperties/RotationVariants/All.cs new file mode 100644 index 00000000..2e7fac03 --- /dev/null +++ b/src/Imagekit/Models/TransformationProperties/RotationVariants/All.cs @@ -0,0 +1,21 @@ +namespace Imagekit.Models.TransformationProperties.RotationVariants; + +public sealed record class Double(double Value) : Rotation, IVariant +{ + public static Double From(double value) + { + return new(value); + } + + public override void Validate() { } +} + +public sealed record class String(string Value) : Rotation, IVariant +{ + public static String From(string value) + { + return new(value); + } + + public override void Validate() { } +} diff --git a/src/Imagekit/Models/TransformationProperties/Shadow.cs b/src/Imagekit/Models/TransformationProperties/Shadow.cs new file mode 100644 index 00000000..1a8f8e34 --- /dev/null +++ b/src/Imagekit/Models/TransformationProperties/Shadow.cs @@ -0,0 +1,109 @@ +using System; +using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; +using System.Text.Json; +using System.Text.Json.Serialization; +using ShadowVariants = Imagekit.Models.TransformationProperties.ShadowVariants; + +namespace Imagekit.Models.TransformationProperties; + +/// +/// Adds a shadow beneath solid objects in an image with a transparent background. +/// For AI-based drop shadows, refer to aiDropShadow. Pass `true` for a default +/// shadow, or provide a string for a custom shadow. See [Shadow](https://imagekit.io/docs/effects-and-enhancements#shadow---e-shadow). +/// +[JsonConverter(typeof(ShadowConverter))] +public abstract record class Shadow +{ + internal Shadow() { } + + public static implicit operator Shadow(string value) => new ShadowVariants::String(value); + + public bool TryPickTrue([NotNullWhen(true)] out JsonElement? value) + { + value = (this as ShadowVariants::True)?.Value; + return value != null; + } + + public bool TryPickString([NotNullWhen(true)] out string? value) + { + value = (this as ShadowVariants::String)?.Value; + return value != null; + } + + public void Switch(Action true1, Action @string) + { + switch (this) + { + case ShadowVariants::True inner: + true1(inner); + break; + case ShadowVariants::String inner: + @string(inner); + break; + default: + throw new InvalidOperationException(); + } + } + + public T Match(Func true1, Func @string) + { + return this switch + { + ShadowVariants::True inner => true1(inner), + ShadowVariants::String inner => @string(inner), + _ => throw new InvalidOperationException(), + }; + } + + public abstract void Validate(); +} + +sealed class ShadowConverter : JsonConverter +{ + public override Shadow? Read( + ref Utf8JsonReader reader, + Type typeToConvert, + JsonSerializerOptions options + ) + { + List exceptions = []; + + try + { + return new ShadowVariants::True( + JsonSerializer.Deserialize(ref reader, options) + ); + } + catch (JsonException e) + { + exceptions.Add(e); + } + + try + { + var deserialized = JsonSerializer.Deserialize(ref reader, options); + if (deserialized != null) + { + return new ShadowVariants::String(deserialized); + } + } + catch (JsonException e) + { + exceptions.Add(e); + } + + throw new AggregateException(exceptions); + } + + public override void Write(Utf8JsonWriter writer, Shadow value, JsonSerializerOptions options) + { + object variant = value switch + { + ShadowVariants::True(var true1) => true1, + ShadowVariants::String(var @string) => @string, + _ => throw new ArgumentOutOfRangeException(nameof(value)), + }; + JsonSerializer.Serialize(writer, variant, options); + } +} diff --git a/src/Imagekit/Models/TransformationProperties/ShadowVariants/All.cs b/src/Imagekit/Models/TransformationProperties/ShadowVariants/All.cs new file mode 100644 index 00000000..94e02120 --- /dev/null +++ b/src/Imagekit/Models/TransformationProperties/ShadowVariants/All.cs @@ -0,0 +1,23 @@ +using System.Text.Json; + +namespace Imagekit.Models.TransformationProperties.ShadowVariants; + +public sealed record class True(JsonElement Value) : Shadow, IVariant +{ + public static True From(JsonElement value) + { + return new(value); + } + + public override void Validate() { } +} + +public sealed record class String(string Value) : Shadow, IVariant +{ + public static String From(string value) + { + return new(value); + } + + public override void Validate() { } +} diff --git a/src/Imagekit/Models/TransformationProperties/Sharpen.cs b/src/Imagekit/Models/TransformationProperties/Sharpen.cs new file mode 100644 index 00000000..27d65714 --- /dev/null +++ b/src/Imagekit/Models/TransformationProperties/Sharpen.cs @@ -0,0 +1,110 @@ +using System; +using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; +using System.Text.Json; +using System.Text.Json.Serialization; +using SharpenVariants = Imagekit.Models.TransformationProperties.SharpenVariants; + +namespace Imagekit.Models.TransformationProperties; + +/// +/// Sharpens the input image, highlighting edges and finer details. Pass `true` +/// for default sharpening, or provide a numeric value for custom sharpening. See +/// [Sharpen](https://imagekit.io/docs/effects-and-enhancements#sharpen---e-sharpen). +/// +[JsonConverter(typeof(SharpenConverter))] +public abstract record class Sharpen +{ + internal Sharpen() { } + + public static implicit operator Sharpen(double value) => new SharpenVariants::Double(value); + + public bool TryPickTrue([NotNullWhen(true)] out JsonElement? value) + { + value = (this as SharpenVariants::True)?.Value; + return value != null; + } + + public bool TryPickDouble([NotNullWhen(true)] out double? value) + { + value = (this as SharpenVariants::Double)?.Value; + return value != null; + } + + public void Switch(Action true1, Action @double) + { + switch (this) + { + case SharpenVariants::True inner: + true1(inner); + break; + case SharpenVariants::Double inner: + @double(inner); + break; + default: + throw new InvalidOperationException(); + } + } + + public T Match( + Func true1, + Func @double + ) + { + return this switch + { + SharpenVariants::True inner => true1(inner), + SharpenVariants::Double inner => @double(inner), + _ => throw new InvalidOperationException(), + }; + } + + public abstract void Validate(); +} + +sealed class SharpenConverter : JsonConverter +{ + public override Sharpen? Read( + ref Utf8JsonReader reader, + Type typeToConvert, + JsonSerializerOptions options + ) + { + List exceptions = []; + + try + { + return new SharpenVariants::True( + JsonSerializer.Deserialize(ref reader, options) + ); + } + catch (JsonException e) + { + exceptions.Add(e); + } + + try + { + return new SharpenVariants::Double( + JsonSerializer.Deserialize(ref reader, options) + ); + } + catch (JsonException e) + { + exceptions.Add(e); + } + + throw new AggregateException(exceptions); + } + + public override void Write(Utf8JsonWriter writer, Sharpen value, JsonSerializerOptions options) + { + object variant = value switch + { + SharpenVariants::True(var true1) => true1, + SharpenVariants::Double(var @double) => @double, + _ => throw new ArgumentOutOfRangeException(nameof(value)), + }; + JsonSerializer.Serialize(writer, variant, options); + } +} diff --git a/src/Imagekit/Models/TransformationProperties/SharpenVariants/All.cs b/src/Imagekit/Models/TransformationProperties/SharpenVariants/All.cs new file mode 100644 index 00000000..aa226c35 --- /dev/null +++ b/src/Imagekit/Models/TransformationProperties/SharpenVariants/All.cs @@ -0,0 +1,23 @@ +using System.Text.Json; + +namespace Imagekit.Models.TransformationProperties.SharpenVariants; + +public sealed record class True(JsonElement Value) : Sharpen, IVariant +{ + public static True From(JsonElement value) + { + return new(value); + } + + public override void Validate() { } +} + +public sealed record class Double(double Value) : Sharpen, IVariant +{ + public static Double From(double value) + { + return new(value); + } + + public override void Validate() { } +} diff --git a/src/Imagekit/Models/TransformationProperties/StartOffset.cs b/src/Imagekit/Models/TransformationProperties/StartOffset.cs new file mode 100644 index 00000000..eb9f79bd --- /dev/null +++ b/src/Imagekit/Models/TransformationProperties/StartOffset.cs @@ -0,0 +1,122 @@ +using System; +using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; +using System.Text.Json; +using System.Text.Json.Serialization; +using StartOffsetVariants = Imagekit.Models.TransformationProperties.StartOffsetVariants; + +namespace Imagekit.Models.TransformationProperties; + +/// +/// Specifies the start offset (in seconds) for trimming videos, e.g., `5` or `10.5`. +/// Arithmetic expressions are also supported. See [Trim videos – Start offset](https://imagekit.io/docs/trim-videos#start-offset---so). +/// +[JsonConverter(typeof(StartOffsetConverter))] +public abstract record class StartOffset +{ + internal StartOffset() { } + + public static implicit operator StartOffset(double value) => + new StartOffsetVariants::Double(value); + + public static implicit operator StartOffset(string value) => + new StartOffsetVariants::String(value); + + public bool TryPickDouble([NotNullWhen(true)] out double? value) + { + value = (this as StartOffsetVariants::Double)?.Value; + return value != null; + } + + public bool TryPickString([NotNullWhen(true)] out string? value) + { + value = (this as StartOffsetVariants::String)?.Value; + return value != null; + } + + public void Switch( + Action @double, + Action @string + ) + { + switch (this) + { + case StartOffsetVariants::Double inner: + @double(inner); + break; + case StartOffsetVariants::String inner: + @string(inner); + break; + default: + throw new InvalidOperationException(); + } + } + + public T Match( + Func @double, + Func @string + ) + { + return this switch + { + StartOffsetVariants::Double inner => @double(inner), + StartOffsetVariants::String inner => @string(inner), + _ => throw new InvalidOperationException(), + }; + } + + public abstract void Validate(); +} + +sealed class StartOffsetConverter : JsonConverter +{ + public override StartOffset? Read( + ref Utf8JsonReader reader, + Type typeToConvert, + JsonSerializerOptions options + ) + { + List exceptions = []; + + try + { + return new StartOffsetVariants::Double( + JsonSerializer.Deserialize(ref reader, options) + ); + } + catch (JsonException e) + { + exceptions.Add(e); + } + + try + { + var deserialized = JsonSerializer.Deserialize(ref reader, options); + if (deserialized != null) + { + return new StartOffsetVariants::String(deserialized); + } + } + catch (JsonException e) + { + exceptions.Add(e); + } + + throw new AggregateException(exceptions); + } + + public override void Write( + Utf8JsonWriter writer, + StartOffset value, + JsonSerializerOptions options + ) + { + object variant = value switch + { + StartOffsetVariants::Double(var @double) => @double, + StartOffsetVariants::String(var @string) => @string, + _ => throw new ArgumentOutOfRangeException(nameof(value)), + }; + JsonSerializer.Serialize(writer, variant, options); + } +} diff --git a/src/Imagekit/Models/TransformationProperties/StartOffsetVariants/All.cs b/src/Imagekit/Models/TransformationProperties/StartOffsetVariants/All.cs new file mode 100644 index 00000000..652e3912 --- /dev/null +++ b/src/Imagekit/Models/TransformationProperties/StartOffsetVariants/All.cs @@ -0,0 +1,21 @@ +namespace Imagekit.Models.TransformationProperties.StartOffsetVariants; + +public sealed record class Double(double Value) : StartOffset, IVariant +{ + public static Double From(double value) + { + return new(value); + } + + public override void Validate() { } +} + +public sealed record class String(string Value) : StartOffset, IVariant +{ + public static String From(string value) + { + return new(value); + } + + public override void Validate() { } +} diff --git a/src/Imagekit/Models/TransformationProperties/Trim.cs b/src/Imagekit/Models/TransformationProperties/Trim.cs new file mode 100644 index 00000000..ff235c78 --- /dev/null +++ b/src/Imagekit/Models/TransformationProperties/Trim.cs @@ -0,0 +1,107 @@ +using System; +using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; +using System.Text.Json; +using System.Text.Json.Serialization; +using TrimVariants = Imagekit.Models.TransformationProperties.TrimVariants; + +namespace Imagekit.Models.TransformationProperties; + +/// +/// Useful for images with a solid or nearly solid background and a central object. +/// This parameter trims the background, leaving only the central object in the output +/// image. See [Trim edges](https://imagekit.io/docs/effects-and-enhancements#trim-edges---t). +/// +[JsonConverter(typeof(TrimConverter))] +public abstract record class Trim +{ + internal Trim() { } + + public static implicit operator Trim(double value) => new TrimVariants::Double(value); + + public bool TryPickTrue([NotNullWhen(true)] out JsonElement? value) + { + value = (this as TrimVariants::True)?.Value; + return value != null; + } + + public bool TryPickDouble([NotNullWhen(true)] out double? value) + { + value = (this as TrimVariants::Double)?.Value; + return value != null; + } + + public void Switch(Action true1, Action @double) + { + switch (this) + { + case TrimVariants::True inner: + true1(inner); + break; + case TrimVariants::Double inner: + @double(inner); + break; + default: + throw new InvalidOperationException(); + } + } + + public T Match(Func true1, Func @double) + { + return this switch + { + TrimVariants::True inner => true1(inner), + TrimVariants::Double inner => @double(inner), + _ => throw new InvalidOperationException(), + }; + } + + public abstract void Validate(); +} + +sealed class TrimConverter : JsonConverter +{ + public override Trim? Read( + ref Utf8JsonReader reader, + Type typeToConvert, + JsonSerializerOptions options + ) + { + List exceptions = []; + + try + { + return new TrimVariants::True( + JsonSerializer.Deserialize(ref reader, options) + ); + } + catch (JsonException e) + { + exceptions.Add(e); + } + + try + { + return new TrimVariants::Double( + JsonSerializer.Deserialize(ref reader, options) + ); + } + catch (JsonException e) + { + exceptions.Add(e); + } + + throw new AggregateException(exceptions); + } + + public override void Write(Utf8JsonWriter writer, Trim value, JsonSerializerOptions options) + { + object variant = value switch + { + TrimVariants::True(var true1) => true1, + TrimVariants::Double(var @double) => @double, + _ => throw new ArgumentOutOfRangeException(nameof(value)), + }; + JsonSerializer.Serialize(writer, variant, options); + } +} diff --git a/src/Imagekit/Models/TransformationProperties/TrimVariants/All.cs b/src/Imagekit/Models/TransformationProperties/TrimVariants/All.cs new file mode 100644 index 00000000..e26ab0d0 --- /dev/null +++ b/src/Imagekit/Models/TransformationProperties/TrimVariants/All.cs @@ -0,0 +1,23 @@ +using System.Text.Json; + +namespace Imagekit.Models.TransformationProperties.TrimVariants; + +public sealed record class True(JsonElement Value) : Trim, IVariant +{ + public static True From(JsonElement value) + { + return new(value); + } + + public override void Validate() { } +} + +public sealed record class Double(double Value) : Trim, IVariant +{ + public static Double From(double value) + { + return new(value); + } + + public override void Validate() { } +} diff --git a/src/Imagekit/Models/TransformationProperties/UnsharpMask.cs b/src/Imagekit/Models/TransformationProperties/UnsharpMask.cs new file mode 100644 index 00000000..c66dc5c7 --- /dev/null +++ b/src/Imagekit/Models/TransformationProperties/UnsharpMask.cs @@ -0,0 +1,120 @@ +using System; +using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; +using System.Text.Json; +using System.Text.Json.Serialization; +using UnsharpMaskVariants = Imagekit.Models.TransformationProperties.UnsharpMaskVariants; + +namespace Imagekit.Models.TransformationProperties; + +/// +/// Applies Unsharp Masking (USM), an image sharpening technique. Pass `true` for +/// a default unsharp mask, or provide a string for a custom unsharp mask. See [Unsharp +/// Mask](https://imagekit.io/docs/effects-and-enhancements#unsharp-mask---e-usm). +/// +[JsonConverter(typeof(UnsharpMaskConverter))] +public abstract record class UnsharpMask +{ + internal UnsharpMask() { } + + public static implicit operator UnsharpMask(string value) => + new UnsharpMaskVariants::String(value); + + public bool TryPickTrue([NotNullWhen(true)] out JsonElement? value) + { + value = (this as UnsharpMaskVariants::True)?.Value; + return value != null; + } + + public bool TryPickString([NotNullWhen(true)] out string? value) + { + value = (this as UnsharpMaskVariants::String)?.Value; + return value != null; + } + + public void Switch( + Action true1, + Action @string + ) + { + switch (this) + { + case UnsharpMaskVariants::True inner: + true1(inner); + break; + case UnsharpMaskVariants::String inner: + @string(inner); + break; + default: + throw new InvalidOperationException(); + } + } + + public T Match( + Func true1, + Func @string + ) + { + return this switch + { + UnsharpMaskVariants::True inner => true1(inner), + UnsharpMaskVariants::String inner => @string(inner), + _ => throw new InvalidOperationException(), + }; + } + + public abstract void Validate(); +} + +sealed class UnsharpMaskConverter : JsonConverter +{ + public override UnsharpMask? Read( + ref Utf8JsonReader reader, + Type typeToConvert, + JsonSerializerOptions options + ) + { + List exceptions = []; + + try + { + return new UnsharpMaskVariants::True( + JsonSerializer.Deserialize(ref reader, options) + ); + } + catch (JsonException e) + { + exceptions.Add(e); + } + + try + { + var deserialized = JsonSerializer.Deserialize(ref reader, options); + if (deserialized != null) + { + return new UnsharpMaskVariants::String(deserialized); + } + } + catch (JsonException e) + { + exceptions.Add(e); + } + + throw new AggregateException(exceptions); + } + + public override void Write( + Utf8JsonWriter writer, + UnsharpMask value, + JsonSerializerOptions options + ) + { + object variant = value switch + { + UnsharpMaskVariants::True(var true1) => true1, + UnsharpMaskVariants::String(var @string) => @string, + _ => throw new ArgumentOutOfRangeException(nameof(value)), + }; + JsonSerializer.Serialize(writer, variant, options); + } +} diff --git a/src/Imagekit/Models/TransformationProperties/UnsharpMaskVariants/All.cs b/src/Imagekit/Models/TransformationProperties/UnsharpMaskVariants/All.cs new file mode 100644 index 00000000..6662a69b --- /dev/null +++ b/src/Imagekit/Models/TransformationProperties/UnsharpMaskVariants/All.cs @@ -0,0 +1,23 @@ +using System.Text.Json; + +namespace Imagekit.Models.TransformationProperties.UnsharpMaskVariants; + +public sealed record class True(JsonElement Value) : UnsharpMask, IVariant +{ + public static True From(JsonElement value) + { + return new(value); + } + + public override void Validate() { } +} + +public sealed record class String(string Value) : UnsharpMask, IVariant +{ + public static String From(string value) + { + return new(value); + } + + public override void Validate() { } +} diff --git a/src/Imagekit/Models/TransformationProperties/VideoCodec.cs b/src/Imagekit/Models/TransformationProperties/VideoCodec.cs new file mode 100644 index 00000000..c00b2b3b --- /dev/null +++ b/src/Imagekit/Models/TransformationProperties/VideoCodec.cs @@ -0,0 +1,56 @@ +using System; +using System.Text.Json; +using System.Text.Json.Serialization; + +namespace Imagekit.Models.TransformationProperties; + +/// +/// Specifies the video codec, e.g., `h264`, `vp9`, `av1`, or `none`. See [Video codec](https://imagekit.io/docs/video-optimization#video-codec---vc). +/// +[JsonConverter(typeof(VideoCodecConverter))] +public enum VideoCodec +{ + H264, + Vp9, + Av1, + None, +} + +sealed class VideoCodecConverter : JsonConverter +{ + public override VideoCodec Read( + ref Utf8JsonReader reader, + Type typeToConvert, + JsonSerializerOptions options + ) + { + return JsonSerializer.Deserialize(ref reader, options) switch + { + "h264" => VideoCodec.H264, + "vp9" => VideoCodec.Vp9, + "av1" => VideoCodec.Av1, + "none" => VideoCodec.None, + _ => (VideoCodec)(-1), + }; + } + + public override void Write( + Utf8JsonWriter writer, + VideoCodec value, + JsonSerializerOptions options + ) + { + JsonSerializer.Serialize( + writer, + value switch + { + VideoCodec.H264 => "h264", + VideoCodec.Vp9 => "vp9", + VideoCodec.Av1 => "av1", + VideoCodec.None => "none", + _ => throw new ArgumentOutOfRangeException(nameof(value)), + }, + options + ); + } +} diff --git a/src/Imagekit/Models/TransformationProperties/Width.cs b/src/Imagekit/Models/TransformationProperties/Width.cs new file mode 100644 index 00000000..f1dd1b24 --- /dev/null +++ b/src/Imagekit/Models/TransformationProperties/Width.cs @@ -0,0 +1,115 @@ +using System; +using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; +using System.Text.Json; +using System.Text.Json.Serialization; +using WidthVariants = Imagekit.Models.TransformationProperties.WidthVariants; + +namespace Imagekit.Models.TransformationProperties; + +/// +/// Specifies the width of the output. If a value between 0 and 1 is provided, it +/// is treated as a percentage (e.g., `0.4` represents 40% of the original width). +/// You can also supply arithmetic expressions (e.g., `iw_div_2`). Width transformation +/// – [Images](https://imagekit.io/docs/image-resize-and-crop#width---w) · [Videos](https://imagekit.io/docs/video-resize-and-crop#width---w) +/// +[JsonConverter(typeof(WidthConverter))] +public abstract record class Width +{ + internal Width() { } + + public static implicit operator Width(double value) => new WidthVariants::Double(value); + + public static implicit operator Width(string value) => new WidthVariants::String(value); + + public bool TryPickDouble([NotNullWhen(true)] out double? value) + { + value = (this as WidthVariants::Double)?.Value; + return value != null; + } + + public bool TryPickString([NotNullWhen(true)] out string? value) + { + value = (this as WidthVariants::String)?.Value; + return value != null; + } + + public void Switch(Action @double, Action @string) + { + switch (this) + { + case WidthVariants::Double inner: + @double(inner); + break; + case WidthVariants::String inner: + @string(inner); + break; + default: + throw new InvalidOperationException(); + } + } + + public T Match( + Func @double, + Func @string + ) + { + return this switch + { + WidthVariants::Double inner => @double(inner), + WidthVariants::String inner => @string(inner), + _ => throw new InvalidOperationException(), + }; + } + + public abstract void Validate(); +} + +sealed class WidthConverter : JsonConverter +{ + public override Width? Read( + ref Utf8JsonReader reader, + Type typeToConvert, + JsonSerializerOptions options + ) + { + List exceptions = []; + + try + { + return new WidthVariants::Double( + JsonSerializer.Deserialize(ref reader, options) + ); + } + catch (JsonException e) + { + exceptions.Add(e); + } + + try + { + var deserialized = JsonSerializer.Deserialize(ref reader, options); + if (deserialized != null) + { + return new WidthVariants::String(deserialized); + } + } + catch (JsonException e) + { + exceptions.Add(e); + } + + throw new AggregateException(exceptions); + } + + public override void Write(Utf8JsonWriter writer, Width value, JsonSerializerOptions options) + { + object variant = value switch + { + WidthVariants::Double(var @double) => @double, + WidthVariants::String(var @string) => @string, + _ => throw new ArgumentOutOfRangeException(nameof(value)), + }; + JsonSerializer.Serialize(writer, variant, options); + } +} diff --git a/src/Imagekit/Models/TransformationProperties/WidthVariants/All.cs b/src/Imagekit/Models/TransformationProperties/WidthVariants/All.cs new file mode 100644 index 00000000..3899be2b --- /dev/null +++ b/src/Imagekit/Models/TransformationProperties/WidthVariants/All.cs @@ -0,0 +1,21 @@ +namespace Imagekit.Models.TransformationProperties.WidthVariants; + +public sealed record class Double(double Value) : Width, IVariant +{ + public static Double From(double value) + { + return new(value); + } + + public override void Validate() { } +} + +public sealed record class String(string Value) : Width, IVariant +{ + public static String From(string value) + { + return new(value); + } + + public override void Validate() { } +} diff --git a/src/Imagekit/Models/TransformationProperties/X.cs b/src/Imagekit/Models/TransformationProperties/X.cs new file mode 100644 index 00000000..44c09b52 --- /dev/null +++ b/src/Imagekit/Models/TransformationProperties/X.cs @@ -0,0 +1,107 @@ +using System; +using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; +using System.Text.Json; +using System.Text.Json.Serialization; +using XVariants = Imagekit.Models.TransformationProperties.XVariants; + +namespace Imagekit.Models.TransformationProperties; + +/// +/// Focus using cropped image coordinates - X coordinate. See [Focus using cropped coordinates](https://imagekit.io/docs/image-resize-and-crop#example---focus-using-cropped-image-coordinates). +/// +[JsonConverter(typeof(XConverter))] +public abstract record class X +{ + internal X() { } + + public static implicit operator X(double value) => new XVariants::Double(value); + + public static implicit operator X(string value) => new XVariants::String(value); + + public bool TryPickDouble([NotNullWhen(true)] out double? value) + { + value = (this as XVariants::Double)?.Value; + return value != null; + } + + public bool TryPickString([NotNullWhen(true)] out string? value) + { + value = (this as XVariants::String)?.Value; + return value != null; + } + + public void Switch(Action @double, Action @string) + { + switch (this) + { + case XVariants::Double inner: + @double(inner); + break; + case XVariants::String inner: + @string(inner); + break; + default: + throw new InvalidOperationException(); + } + } + + public T Match(Func @double, Func @string) + { + return this switch + { + XVariants::Double inner => @double(inner), + XVariants::String inner => @string(inner), + _ => throw new InvalidOperationException(), + }; + } + + public abstract void Validate(); +} + +sealed class XConverter : JsonConverter +{ + public override X? Read( + ref Utf8JsonReader reader, + Type typeToConvert, + JsonSerializerOptions options + ) + { + List exceptions = []; + + try + { + return new XVariants::Double(JsonSerializer.Deserialize(ref reader, options)); + } + catch (JsonException e) + { + exceptions.Add(e); + } + + try + { + var deserialized = JsonSerializer.Deserialize(ref reader, options); + if (deserialized != null) + { + return new XVariants::String(deserialized); + } + } + catch (JsonException e) + { + exceptions.Add(e); + } + + throw new AggregateException(exceptions); + } + + public override void Write(Utf8JsonWriter writer, X value, JsonSerializerOptions options) + { + object variant = value switch + { + XVariants::Double(var @double) => @double, + XVariants::String(var @string) => @string, + _ => throw new ArgumentOutOfRangeException(nameof(value)), + }; + JsonSerializer.Serialize(writer, variant, options); + } +} diff --git a/src/Imagekit/Models/TransformationProperties/XCenter.cs b/src/Imagekit/Models/TransformationProperties/XCenter.cs new file mode 100644 index 00000000..03db6407 --- /dev/null +++ b/src/Imagekit/Models/TransformationProperties/XCenter.cs @@ -0,0 +1,116 @@ +using System; +using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; +using System.Text.Json; +using System.Text.Json.Serialization; +using XCenterVariants = Imagekit.Models.TransformationProperties.XCenterVariants; + +namespace Imagekit.Models.TransformationProperties; + +/// +/// Focus using cropped image coordinates - X center coordinate. See [Focus using +/// cropped coordinates](https://imagekit.io/docs/image-resize-and-crop#example---focus-using-cropped-image-coordinates). +/// +[JsonConverter(typeof(XCenterConverter))] +public abstract record class XCenter +{ + internal XCenter() { } + + public static implicit operator XCenter(double value) => new XCenterVariants::Double(value); + + public static implicit operator XCenter(string value) => new XCenterVariants::String(value); + + public bool TryPickDouble([NotNullWhen(true)] out double? value) + { + value = (this as XCenterVariants::Double)?.Value; + return value != null; + } + + public bool TryPickString([NotNullWhen(true)] out string? value) + { + value = (this as XCenterVariants::String)?.Value; + return value != null; + } + + public void Switch( + Action @double, + Action @string + ) + { + switch (this) + { + case XCenterVariants::Double inner: + @double(inner); + break; + case XCenterVariants::String inner: + @string(inner); + break; + default: + throw new InvalidOperationException(); + } + } + + public T Match( + Func @double, + Func @string + ) + { + return this switch + { + XCenterVariants::Double inner => @double(inner), + XCenterVariants::String inner => @string(inner), + _ => throw new InvalidOperationException(), + }; + } + + public abstract void Validate(); +} + +sealed class XCenterConverter : JsonConverter +{ + public override XCenter? Read( + ref Utf8JsonReader reader, + Type typeToConvert, + JsonSerializerOptions options + ) + { + List exceptions = []; + + try + { + return new XCenterVariants::Double( + JsonSerializer.Deserialize(ref reader, options) + ); + } + catch (JsonException e) + { + exceptions.Add(e); + } + + try + { + var deserialized = JsonSerializer.Deserialize(ref reader, options); + if (deserialized != null) + { + return new XCenterVariants::String(deserialized); + } + } + catch (JsonException e) + { + exceptions.Add(e); + } + + throw new AggregateException(exceptions); + } + + public override void Write(Utf8JsonWriter writer, XCenter value, JsonSerializerOptions options) + { + object variant = value switch + { + XCenterVariants::Double(var @double) => @double, + XCenterVariants::String(var @string) => @string, + _ => throw new ArgumentOutOfRangeException(nameof(value)), + }; + JsonSerializer.Serialize(writer, variant, options); + } +} diff --git a/src/Imagekit/Models/TransformationProperties/XCenterVariants/All.cs b/src/Imagekit/Models/TransformationProperties/XCenterVariants/All.cs new file mode 100644 index 00000000..af356397 --- /dev/null +++ b/src/Imagekit/Models/TransformationProperties/XCenterVariants/All.cs @@ -0,0 +1,21 @@ +namespace Imagekit.Models.TransformationProperties.XCenterVariants; + +public sealed record class Double(double Value) : XCenter, IVariant +{ + public static Double From(double value) + { + return new(value); + } + + public override void Validate() { } +} + +public sealed record class String(string Value) : XCenter, IVariant +{ + public static String From(string value) + { + return new(value); + } + + public override void Validate() { } +} diff --git a/src/Imagekit/Models/TransformationProperties/XVariants/All.cs b/src/Imagekit/Models/TransformationProperties/XVariants/All.cs new file mode 100644 index 00000000..f147a03c --- /dev/null +++ b/src/Imagekit/Models/TransformationProperties/XVariants/All.cs @@ -0,0 +1,21 @@ +namespace Imagekit.Models.TransformationProperties.XVariants; + +public sealed record class Double(double Value) : X, IVariant +{ + public static Double From(double value) + { + return new(value); + } + + public override void Validate() { } +} + +public sealed record class String(string Value) : X, IVariant +{ + public static String From(string value) + { + return new(value); + } + + public override void Validate() { } +} diff --git a/src/Imagekit/Models/TransformationProperties/Y.cs b/src/Imagekit/Models/TransformationProperties/Y.cs new file mode 100644 index 00000000..7fa77408 --- /dev/null +++ b/src/Imagekit/Models/TransformationProperties/Y.cs @@ -0,0 +1,107 @@ +using System; +using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; +using System.Text.Json; +using System.Text.Json.Serialization; +using YVariants = Imagekit.Models.TransformationProperties.YVariants; + +namespace Imagekit.Models.TransformationProperties; + +/// +/// Focus using cropped image coordinates - Y coordinate. See [Focus using cropped coordinates](https://imagekit.io/docs/image-resize-and-crop#example---focus-using-cropped-image-coordinates). +/// +[JsonConverter(typeof(YConverter))] +public abstract record class Y +{ + internal Y() { } + + public static implicit operator Y(double value) => new YVariants::Double(value); + + public static implicit operator Y(string value) => new YVariants::String(value); + + public bool TryPickDouble([NotNullWhen(true)] out double? value) + { + value = (this as YVariants::Double)?.Value; + return value != null; + } + + public bool TryPickString([NotNullWhen(true)] out string? value) + { + value = (this as YVariants::String)?.Value; + return value != null; + } + + public void Switch(Action @double, Action @string) + { + switch (this) + { + case YVariants::Double inner: + @double(inner); + break; + case YVariants::String inner: + @string(inner); + break; + default: + throw new InvalidOperationException(); + } + } + + public T Match(Func @double, Func @string) + { + return this switch + { + YVariants::Double inner => @double(inner), + YVariants::String inner => @string(inner), + _ => throw new InvalidOperationException(), + }; + } + + public abstract void Validate(); +} + +sealed class YConverter : JsonConverter +{ + public override Y? Read( + ref Utf8JsonReader reader, + Type typeToConvert, + JsonSerializerOptions options + ) + { + List exceptions = []; + + try + { + return new YVariants::Double(JsonSerializer.Deserialize(ref reader, options)); + } + catch (JsonException e) + { + exceptions.Add(e); + } + + try + { + var deserialized = JsonSerializer.Deserialize(ref reader, options); + if (deserialized != null) + { + return new YVariants::String(deserialized); + } + } + catch (JsonException e) + { + exceptions.Add(e); + } + + throw new AggregateException(exceptions); + } + + public override void Write(Utf8JsonWriter writer, Y value, JsonSerializerOptions options) + { + object variant = value switch + { + YVariants::Double(var @double) => @double, + YVariants::String(var @string) => @string, + _ => throw new ArgumentOutOfRangeException(nameof(value)), + }; + JsonSerializer.Serialize(writer, variant, options); + } +} diff --git a/src/Imagekit/Models/TransformationProperties/YCenter.cs b/src/Imagekit/Models/TransformationProperties/YCenter.cs new file mode 100644 index 00000000..76038e88 --- /dev/null +++ b/src/Imagekit/Models/TransformationProperties/YCenter.cs @@ -0,0 +1,116 @@ +using System; +using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; +using System.Text.Json; +using System.Text.Json.Serialization; +using YCenterVariants = Imagekit.Models.TransformationProperties.YCenterVariants; + +namespace Imagekit.Models.TransformationProperties; + +/// +/// Focus using cropped image coordinates - Y center coordinate. See [Focus using +/// cropped coordinates](https://imagekit.io/docs/image-resize-and-crop#example---focus-using-cropped-image-coordinates). +/// +[JsonConverter(typeof(YCenterConverter))] +public abstract record class YCenter +{ + internal YCenter() { } + + public static implicit operator YCenter(double value) => new YCenterVariants::Double(value); + + public static implicit operator YCenter(string value) => new YCenterVariants::String(value); + + public bool TryPickDouble([NotNullWhen(true)] out double? value) + { + value = (this as YCenterVariants::Double)?.Value; + return value != null; + } + + public bool TryPickString([NotNullWhen(true)] out string? value) + { + value = (this as YCenterVariants::String)?.Value; + return value != null; + } + + public void Switch( + Action @double, + Action @string + ) + { + switch (this) + { + case YCenterVariants::Double inner: + @double(inner); + break; + case YCenterVariants::String inner: + @string(inner); + break; + default: + throw new InvalidOperationException(); + } + } + + public T Match( + Func @double, + Func @string + ) + { + return this switch + { + YCenterVariants::Double inner => @double(inner), + YCenterVariants::String inner => @string(inner), + _ => throw new InvalidOperationException(), + }; + } + + public abstract void Validate(); +} + +sealed class YCenterConverter : JsonConverter +{ + public override YCenter? Read( + ref Utf8JsonReader reader, + Type typeToConvert, + JsonSerializerOptions options + ) + { + List exceptions = []; + + try + { + return new YCenterVariants::Double( + JsonSerializer.Deserialize(ref reader, options) + ); + } + catch (JsonException e) + { + exceptions.Add(e); + } + + try + { + var deserialized = JsonSerializer.Deserialize(ref reader, options); + if (deserialized != null) + { + return new YCenterVariants::String(deserialized); + } + } + catch (JsonException e) + { + exceptions.Add(e); + } + + throw new AggregateException(exceptions); + } + + public override void Write(Utf8JsonWriter writer, YCenter value, JsonSerializerOptions options) + { + object variant = value switch + { + YCenterVariants::Double(var @double) => @double, + YCenterVariants::String(var @string) => @string, + _ => throw new ArgumentOutOfRangeException(nameof(value)), + }; + JsonSerializer.Serialize(writer, variant, options); + } +} diff --git a/src/Imagekit/Models/TransformationProperties/YCenterVariants/All.cs b/src/Imagekit/Models/TransformationProperties/YCenterVariants/All.cs new file mode 100644 index 00000000..beec9696 --- /dev/null +++ b/src/Imagekit/Models/TransformationProperties/YCenterVariants/All.cs @@ -0,0 +1,21 @@ +namespace Imagekit.Models.TransformationProperties.YCenterVariants; + +public sealed record class Double(double Value) : YCenter, IVariant +{ + public static Double From(double value) + { + return new(value); + } + + public override void Validate() { } +} + +public sealed record class String(string Value) : YCenter, IVariant +{ + public static String From(string value) + { + return new(value); + } + + public override void Validate() { } +} diff --git a/src/Imagekit/Models/TransformationProperties/YVariants/All.cs b/src/Imagekit/Models/TransformationProperties/YVariants/All.cs new file mode 100644 index 00000000..eff97584 --- /dev/null +++ b/src/Imagekit/Models/TransformationProperties/YVariants/All.cs @@ -0,0 +1,21 @@ +namespace Imagekit.Models.TransformationProperties.YVariants; + +public sealed record class Double(double Value) : Y, IVariant +{ + public static Double From(double value) + { + return new(value); + } + + public override void Validate() { } +} + +public sealed record class String(string Value) : Y, IVariant +{ + public static String From(string value) + { + return new(value); + } + + public override void Validate() { } +} diff --git a/src/Imagekit/Models/VideoOverlay.cs b/src/Imagekit/Models/VideoOverlay.cs new file mode 100644 index 00000000..2ff8384f --- /dev/null +++ b/src/Imagekit/Models/VideoOverlay.cs @@ -0,0 +1,183 @@ +using System; +using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; +using System.Text.Json; +using System.Text.Json.Serialization; +using Imagekit.Models.VideoOverlayProperties.IntersectionMember1Properties; + +namespace Imagekit.Models; + +[JsonConverter(typeof(ModelConverter))] +public sealed record class VideoOverlay : ModelBase, IFromRaw +{ + public OverlayPosition? Position + { + get + { + if (!this.Properties.TryGetValue("position", out JsonElement element)) + return null; + + return JsonSerializer.Deserialize( + element, + ModelBase.SerializerOptions + ); + } + set + { + this.Properties["position"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + public OverlayTiming? Timing + { + get + { + if (!this.Properties.TryGetValue("timing", out JsonElement element)) + return null; + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions); + } + set + { + this.Properties["timing"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + /// + /// Specifies the relative path to the video used as an overlay. + /// + public required string Input + { + get + { + if (!this.Properties.TryGetValue("input", out JsonElement element)) + throw new ArgumentOutOfRangeException("input", "Missing required argument"); + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions) + ?? throw new ArgumentNullException("input"); + } + set + { + this.Properties["input"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + public JsonElement Type + { + get + { + if (!this.Properties.TryGetValue("type", out JsonElement element)) + throw new ArgumentOutOfRangeException("type", "Missing required argument"); + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions); + } + set + { + this.Properties["type"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + /// + /// The input path can be included in the layer as either `i-{input}` or `ie-{base64_encoded_input}`. + /// By default, the SDK determines the appropriate format automatically. To + /// always use base64 encoding (`ie-{base64}`), set this parameter to `base64`. + /// To always use plain text (`i-{input}`), set it to `plain`. + /// + public ApiEnum? Encoding + { + get + { + if (!this.Properties.TryGetValue("encoding", out JsonElement element)) + return null; + + return JsonSerializer.Deserialize?>( + element, + ModelBase.SerializerOptions + ); + } + set + { + this.Properties["encoding"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + /// + /// Array of transformation to be applied to the overlay video. Except `streamingResolutions`, + /// all other video transformations are supported. See [Video transformations](https://imagekit.io/docs/video-transformation). + /// + public List? Transformation + { + get + { + if (!this.Properties.TryGetValue("transformation", out JsonElement element)) + return null; + + return JsonSerializer.Deserialize?>( + element, + ModelBase.SerializerOptions + ); + } + set + { + this.Properties["transformation"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + public static implicit operator BaseOverlay(VideoOverlay videoOverlay) => + new() { Position = videoOverlay.Position, Timing = videoOverlay.Timing }; + + public override void Validate() + { + this.Position?.Validate(); + this.Timing?.Validate(); + _ = this.Input; + this.Encoding?.Validate(); + foreach (var item in this.Transformation ?? []) + { + item.Validate(); + } + } + + public VideoOverlay() + { + this.Type = JsonSerializer.Deserialize("\"video\""); + } + +#pragma warning disable CS8618 + [SetsRequiredMembers] + VideoOverlay(Dictionary properties) + { + Properties = properties; + } +#pragma warning restore CS8618 + + public static VideoOverlay FromRawUnchecked(Dictionary properties) + { + return new(properties); + } + + [SetsRequiredMembers] + public VideoOverlay(string input) + : this() + { + this.Input = input; + } +} diff --git a/src/Imagekit/Models/VideoOverlayProperties/IntersectionMember1.cs b/src/Imagekit/Models/VideoOverlayProperties/IntersectionMember1.cs new file mode 100644 index 00000000..8b13763d --- /dev/null +++ b/src/Imagekit/Models/VideoOverlayProperties/IntersectionMember1.cs @@ -0,0 +1,139 @@ +using System; +using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; +using System.Text.Json; +using System.Text.Json.Serialization; +using Imagekit.Models.VideoOverlayProperties.IntersectionMember1Properties; + +namespace Imagekit.Models.VideoOverlayProperties; + +[JsonConverter(typeof(ModelConverter))] +public sealed record class IntersectionMember1 : ModelBase, IFromRaw +{ + /// + /// Specifies the relative path to the video used as an overlay. + /// + public required string Input + { + get + { + if (!this.Properties.TryGetValue("input", out JsonElement element)) + throw new ArgumentOutOfRangeException("input", "Missing required argument"); + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions) + ?? throw new ArgumentNullException("input"); + } + set + { + this.Properties["input"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + public JsonElement Type + { + get + { + if (!this.Properties.TryGetValue("type", out JsonElement element)) + throw new ArgumentOutOfRangeException("type", "Missing required argument"); + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions); + } + set + { + this.Properties["type"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + /// + /// The input path can be included in the layer as either `i-{input}` or `ie-{base64_encoded_input}`. + /// By default, the SDK determines the appropriate format automatically. To + /// always use base64 encoding (`ie-{base64}`), set this parameter to `base64`. + /// To always use plain text (`i-{input}`), set it to `plain`. + /// + public ApiEnum? Encoding + { + get + { + if (!this.Properties.TryGetValue("encoding", out JsonElement element)) + return null; + + return JsonSerializer.Deserialize?>( + element, + ModelBase.SerializerOptions + ); + } + set + { + this.Properties["encoding"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + /// + /// Array of transformation to be applied to the overlay video. Except `streamingResolutions`, + /// all other video transformations are supported. See [Video transformations](https://imagekit.io/docs/video-transformation). + /// + public List? Transformation + { + get + { + if (!this.Properties.TryGetValue("transformation", out JsonElement element)) + return null; + + return JsonSerializer.Deserialize?>( + element, + ModelBase.SerializerOptions + ); + } + set + { + this.Properties["transformation"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + public override void Validate() + { + _ = this.Input; + this.Encoding?.Validate(); + foreach (var item in this.Transformation ?? []) + { + item.Validate(); + } + } + + public IntersectionMember1() + { + this.Type = JsonSerializer.Deserialize("\"video\""); + } + +#pragma warning disable CS8618 + [SetsRequiredMembers] + IntersectionMember1(Dictionary properties) + { + Properties = properties; + } +#pragma warning restore CS8618 + + public static IntersectionMember1 FromRawUnchecked(Dictionary properties) + { + return new(properties); + } + + [SetsRequiredMembers] + public IntersectionMember1(string input) + : this() + { + this.Input = input; + } +} diff --git a/src/Imagekit/Models/VideoOverlayProperties/IntersectionMember1Properties/Encoding.cs b/src/Imagekit/Models/VideoOverlayProperties/IntersectionMember1Properties/Encoding.cs new file mode 100644 index 00000000..8252c649 --- /dev/null +++ b/src/Imagekit/Models/VideoOverlayProperties/IntersectionMember1Properties/Encoding.cs @@ -0,0 +1,52 @@ +using System; +using System.Text.Json; +using System.Text.Json.Serialization; + +namespace Imagekit.Models.VideoOverlayProperties.IntersectionMember1Properties; + +/// +/// The input path can be included in the layer as either `i-{input}` or `ie-{base64_encoded_input}`. +/// By default, the SDK determines the appropriate format automatically. To always +/// use base64 encoding (`ie-{base64}`), set this parameter to `base64`. To always +/// use plain text (`i-{input}`), set it to `plain`. +/// +[JsonConverter(typeof(EncodingConverter))] +public enum Encoding +{ + Auto, + Plain, + Base64, +} + +sealed class EncodingConverter : JsonConverter +{ + public override Encoding Read( + ref Utf8JsonReader reader, + Type typeToConvert, + JsonSerializerOptions options + ) + { + return JsonSerializer.Deserialize(ref reader, options) switch + { + "auto" => Encoding.Auto, + "plain" => Encoding.Plain, + "base64" => Encoding.Base64, + _ => (Encoding)(-1), + }; + } + + public override void Write(Utf8JsonWriter writer, Encoding value, JsonSerializerOptions options) + { + JsonSerializer.Serialize( + writer, + value switch + { + Encoding.Auto => "auto", + Encoding.Plain => "plain", + Encoding.Base64 => "base64", + _ => throw new ArgumentOutOfRangeException(nameof(value)), + }, + options + ); + } +} diff --git a/src/Imagekit/Models/Webhooks/UnsafeUnwrapWebhookEvent.cs b/src/Imagekit/Models/Webhooks/UnsafeUnwrapWebhookEvent.cs new file mode 100644 index 00000000..a837e3d1 --- /dev/null +++ b/src/Imagekit/Models/Webhooks/UnsafeUnwrapWebhookEvent.cs @@ -0,0 +1,364 @@ +using System; +using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; +using System.Text.Json; +using System.Text.Json.Serialization; +using UnsafeUnwrapWebhookEventVariants = Imagekit.Models.Webhooks.UnsafeUnwrapWebhookEventVariants; + +namespace Imagekit.Models.Webhooks; + +/// +/// Triggered when a new video transformation request is accepted for processing. +/// This event confirms that ImageKit has received and queued your transformation +/// request. Use this for debugging and tracking transformation lifecycle. +/// +[JsonConverter(typeof(UnsafeUnwrapWebhookEventConverter))] +public abstract record class UnsafeUnwrapWebhookEvent +{ + internal UnsafeUnwrapWebhookEvent() { } + + public static implicit operator UnsafeUnwrapWebhookEvent( + VideoTransformationAcceptedEvent value + ) => new UnsafeUnwrapWebhookEventVariants::VideoTransformationAcceptedEvent(value); + + public static implicit operator UnsafeUnwrapWebhookEvent(VideoTransformationReadyEvent value) => + new UnsafeUnwrapWebhookEventVariants::VideoTransformationReadyEvent(value); + + public static implicit operator UnsafeUnwrapWebhookEvent(VideoTransformationErrorEvent value) => + new UnsafeUnwrapWebhookEventVariants::VideoTransformationErrorEvent(value); + + public static implicit operator UnsafeUnwrapWebhookEvent( + UploadPreTransformSuccessEvent value + ) => new UnsafeUnwrapWebhookEventVariants::UploadPreTransformSuccessEvent(value); + + public static implicit operator UnsafeUnwrapWebhookEvent(UploadPreTransformErrorEvent value) => + new UnsafeUnwrapWebhookEventVariants::UploadPreTransformErrorEvent(value); + + public static implicit operator UnsafeUnwrapWebhookEvent( + UploadPostTransformSuccessEvent value + ) => new UnsafeUnwrapWebhookEventVariants::UploadPostTransformSuccessEvent(value); + + public static implicit operator UnsafeUnwrapWebhookEvent(UploadPostTransformErrorEvent value) => + new UnsafeUnwrapWebhookEventVariants::UploadPostTransformErrorEvent(value); + + public bool TryPickVideoTransformationAccepted( + [NotNullWhen(true)] out VideoTransformationAcceptedEvent? value + ) + { + value = (this as UnsafeUnwrapWebhookEventVariants::VideoTransformationAcceptedEvent)?.Value; + return value != null; + } + + public bool TryPickVideoTransformationReady( + [NotNullWhen(true)] out VideoTransformationReadyEvent? value + ) + { + value = (this as UnsafeUnwrapWebhookEventVariants::VideoTransformationReadyEvent)?.Value; + return value != null; + } + + public bool TryPickVideoTransformationError( + [NotNullWhen(true)] out VideoTransformationErrorEvent? value + ) + { + value = (this as UnsafeUnwrapWebhookEventVariants::VideoTransformationErrorEvent)?.Value; + return value != null; + } + + public bool TryPickUploadPreTransformSuccess( + [NotNullWhen(true)] out UploadPreTransformSuccessEvent? value + ) + { + value = (this as UnsafeUnwrapWebhookEventVariants::UploadPreTransformSuccessEvent)?.Value; + return value != null; + } + + public bool TryPickUploadPreTransformError( + [NotNullWhen(true)] out UploadPreTransformErrorEvent? value + ) + { + value = (this as UnsafeUnwrapWebhookEventVariants::UploadPreTransformErrorEvent)?.Value; + return value != null; + } + + public bool TryPickUploadPostTransformSuccess( + [NotNullWhen(true)] out UploadPostTransformSuccessEvent? value + ) + { + value = (this as UnsafeUnwrapWebhookEventVariants::UploadPostTransformSuccessEvent)?.Value; + return value != null; + } + + public bool TryPickUploadPostTransformError( + [NotNullWhen(true)] out UploadPostTransformErrorEvent? value + ) + { + value = (this as UnsafeUnwrapWebhookEventVariants::UploadPostTransformErrorEvent)?.Value; + return value != null; + } + + public void Switch( + Action videoTransformationAccepted, + Action videoTransformationReady, + Action videoTransformationError, + Action uploadPreTransformSuccess, + Action uploadPreTransformError, + Action uploadPostTransformSuccess, + Action uploadPostTransformError + ) + { + switch (this) + { + case UnsafeUnwrapWebhookEventVariants::VideoTransformationAcceptedEvent inner: + videoTransformationAccepted(inner); + break; + case UnsafeUnwrapWebhookEventVariants::VideoTransformationReadyEvent inner: + videoTransformationReady(inner); + break; + case UnsafeUnwrapWebhookEventVariants::VideoTransformationErrorEvent inner: + videoTransformationError(inner); + break; + case UnsafeUnwrapWebhookEventVariants::UploadPreTransformSuccessEvent inner: + uploadPreTransformSuccess(inner); + break; + case UnsafeUnwrapWebhookEventVariants::UploadPreTransformErrorEvent inner: + uploadPreTransformError(inner); + break; + case UnsafeUnwrapWebhookEventVariants::UploadPostTransformSuccessEvent inner: + uploadPostTransformSuccess(inner); + break; + case UnsafeUnwrapWebhookEventVariants::UploadPostTransformErrorEvent inner: + uploadPostTransformError(inner); + break; + default: + throw new InvalidOperationException(); + } + } + + public T Match( + Func< + UnsafeUnwrapWebhookEventVariants::VideoTransformationAcceptedEvent, + T + > videoTransformationAccepted, + Func< + UnsafeUnwrapWebhookEventVariants::VideoTransformationReadyEvent, + T + > videoTransformationReady, + Func< + UnsafeUnwrapWebhookEventVariants::VideoTransformationErrorEvent, + T + > videoTransformationError, + Func< + UnsafeUnwrapWebhookEventVariants::UploadPreTransformSuccessEvent, + T + > uploadPreTransformSuccess, + Func< + UnsafeUnwrapWebhookEventVariants::UploadPreTransformErrorEvent, + T + > uploadPreTransformError, + Func< + UnsafeUnwrapWebhookEventVariants::UploadPostTransformSuccessEvent, + T + > uploadPostTransformSuccess, + Func< + UnsafeUnwrapWebhookEventVariants::UploadPostTransformErrorEvent, + T + > uploadPostTransformError + ) + { + return this switch + { + UnsafeUnwrapWebhookEventVariants::VideoTransformationAcceptedEvent inner => + videoTransformationAccepted(inner), + UnsafeUnwrapWebhookEventVariants::VideoTransformationReadyEvent inner => + videoTransformationReady(inner), + UnsafeUnwrapWebhookEventVariants::VideoTransformationErrorEvent inner => + videoTransformationError(inner), + UnsafeUnwrapWebhookEventVariants::UploadPreTransformSuccessEvent inner => + uploadPreTransformSuccess(inner), + UnsafeUnwrapWebhookEventVariants::UploadPreTransformErrorEvent inner => + uploadPreTransformError(inner), + UnsafeUnwrapWebhookEventVariants::UploadPostTransformSuccessEvent inner => + uploadPostTransformSuccess(inner), + UnsafeUnwrapWebhookEventVariants::UploadPostTransformErrorEvent inner => + uploadPostTransformError(inner), + _ => throw new InvalidOperationException(), + }; + } + + public abstract void Validate(); +} + +sealed class UnsafeUnwrapWebhookEventConverter : JsonConverter +{ + public override UnsafeUnwrapWebhookEvent? Read( + ref Utf8JsonReader reader, + Type typeToConvert, + JsonSerializerOptions options + ) + { + List exceptions = []; + + try + { + var deserialized = JsonSerializer.Deserialize( + ref reader, + options + ); + if (deserialized != null) + { + return new UnsafeUnwrapWebhookEventVariants::VideoTransformationAcceptedEvent( + deserialized + ); + } + } + catch (JsonException e) + { + exceptions.Add(e); + } + + try + { + var deserialized = JsonSerializer.Deserialize( + ref reader, + options + ); + if (deserialized != null) + { + return new UnsafeUnwrapWebhookEventVariants::VideoTransformationReadyEvent( + deserialized + ); + } + } + catch (JsonException e) + { + exceptions.Add(e); + } + + try + { + var deserialized = JsonSerializer.Deserialize( + ref reader, + options + ); + if (deserialized != null) + { + return new UnsafeUnwrapWebhookEventVariants::VideoTransformationErrorEvent( + deserialized + ); + } + } + catch (JsonException e) + { + exceptions.Add(e); + } + + try + { + var deserialized = JsonSerializer.Deserialize( + ref reader, + options + ); + if (deserialized != null) + { + return new UnsafeUnwrapWebhookEventVariants::UploadPreTransformSuccessEvent( + deserialized + ); + } + } + catch (JsonException e) + { + exceptions.Add(e); + } + + try + { + var deserialized = JsonSerializer.Deserialize( + ref reader, + options + ); + if (deserialized != null) + { + return new UnsafeUnwrapWebhookEventVariants::UploadPreTransformErrorEvent( + deserialized + ); + } + } + catch (JsonException e) + { + exceptions.Add(e); + } + + try + { + var deserialized = JsonSerializer.Deserialize( + ref reader, + options + ); + if (deserialized != null) + { + return new UnsafeUnwrapWebhookEventVariants::UploadPostTransformSuccessEvent( + deserialized + ); + } + } + catch (JsonException e) + { + exceptions.Add(e); + } + + try + { + var deserialized = JsonSerializer.Deserialize( + ref reader, + options + ); + if (deserialized != null) + { + return new UnsafeUnwrapWebhookEventVariants::UploadPostTransformErrorEvent( + deserialized + ); + } + } + catch (JsonException e) + { + exceptions.Add(e); + } + + throw new AggregateException(exceptions); + } + + public override void Write( + Utf8JsonWriter writer, + UnsafeUnwrapWebhookEvent value, + JsonSerializerOptions options + ) + { + object variant = value switch + { + UnsafeUnwrapWebhookEventVariants::VideoTransformationAcceptedEvent( + var videoTransformationAccepted + ) => videoTransformationAccepted, + UnsafeUnwrapWebhookEventVariants::VideoTransformationReadyEvent( + var videoTransformationReady + ) => videoTransformationReady, + UnsafeUnwrapWebhookEventVariants::VideoTransformationErrorEvent( + var videoTransformationError + ) => videoTransformationError, + UnsafeUnwrapWebhookEventVariants::UploadPreTransformSuccessEvent( + var uploadPreTransformSuccess + ) => uploadPreTransformSuccess, + UnsafeUnwrapWebhookEventVariants::UploadPreTransformErrorEvent( + var uploadPreTransformError + ) => uploadPreTransformError, + UnsafeUnwrapWebhookEventVariants::UploadPostTransformSuccessEvent( + var uploadPostTransformSuccess + ) => uploadPostTransformSuccess, + UnsafeUnwrapWebhookEventVariants::UploadPostTransformErrorEvent( + var uploadPostTransformError + ) => uploadPostTransformError, + _ => throw new ArgumentOutOfRangeException(nameof(value)), + }; + JsonSerializer.Serialize(writer, variant, options); + } +} diff --git a/src/Imagekit/Models/Webhooks/UnsafeUnwrapWebhookEventVariants/All.cs b/src/Imagekit/Models/Webhooks/UnsafeUnwrapWebhookEventVariants/All.cs new file mode 100644 index 00000000..b8e8a816 --- /dev/null +++ b/src/Imagekit/Models/Webhooks/UnsafeUnwrapWebhookEventVariants/All.cs @@ -0,0 +1,163 @@ +using Webhooks = Imagekit.Models.Webhooks; + +namespace Imagekit.Models.Webhooks.UnsafeUnwrapWebhookEventVariants; + +/// +/// Triggered when a new video transformation request is accepted for processing. +/// This event confirms that ImageKit has received and queued your transformation +/// request. Use this for debugging and tracking transformation lifecycle. +/// +public sealed record class VideoTransformationAcceptedEvent( + Webhooks::VideoTransformationAcceptedEvent Value +) + : Webhooks::UnsafeUnwrapWebhookEvent, + IVariant +{ + public static VideoTransformationAcceptedEvent From( + Webhooks::VideoTransformationAcceptedEvent value + ) + { + return new(value); + } + + public override void Validate() + { + this.Value.Validate(); + } +} + +/// +/// Triggered when video encoding is finished and the transformed resource is ready +/// to be served. This is the key event to listen for - update your database or CMS +/// flags when you receive this so your application can start showing the transformed +/// video to users. +/// +public sealed record class VideoTransformationReadyEvent( + Webhooks::VideoTransformationReadyEvent Value +) + : Webhooks::UnsafeUnwrapWebhookEvent, + IVariant +{ + public static VideoTransformationReadyEvent From(Webhooks::VideoTransformationReadyEvent value) + { + return new(value); + } + + public override void Validate() + { + this.Value.Validate(); + } +} + +/// +/// Triggered when an error occurs during video encoding. Listen to this webhook to +/// log error reasons and debug issues. Check your origin and URL endpoint settings +/// if the reason is related to download failure. For other errors, contact ImageKit +/// support. +/// +public sealed record class VideoTransformationErrorEvent( + Webhooks::VideoTransformationErrorEvent Value +) + : Webhooks::UnsafeUnwrapWebhookEvent, + IVariant +{ + public static VideoTransformationErrorEvent From(Webhooks::VideoTransformationErrorEvent value) + { + return new(value); + } + + public override void Validate() + { + this.Value.Validate(); + } +} + +/// +/// Triggered when a pre-transformation completes successfully. The file has been +/// processed with the requested transformation and is now available in the Media +/// Library. +/// +public sealed record class UploadPreTransformSuccessEvent( + Webhooks::UploadPreTransformSuccessEvent Value +) + : Webhooks::UnsafeUnwrapWebhookEvent, + IVariant +{ + public static UploadPreTransformSuccessEvent From( + Webhooks::UploadPreTransformSuccessEvent value + ) + { + return new(value); + } + + public override void Validate() + { + this.Value.Validate(); + } +} + +/// +/// Triggered when a pre-transformation fails. The file upload may have been accepted, +/// but the requested transformation could not be applied. +/// +public sealed record class UploadPreTransformErrorEvent( + Webhooks::UploadPreTransformErrorEvent Value +) + : Webhooks::UnsafeUnwrapWebhookEvent, + IVariant +{ + public static UploadPreTransformErrorEvent From(Webhooks::UploadPreTransformErrorEvent value) + { + return new(value); + } + + public override void Validate() + { + this.Value.Validate(); + } +} + +/// +/// Triggered when a post-transformation completes successfully. The transformed version +/// of the file is now ready and can be accessed via the provided URL. Note that +/// each post-transformation generates a separate webhook event. +/// +public sealed record class UploadPostTransformSuccessEvent( + Webhooks::UploadPostTransformSuccessEvent Value +) + : Webhooks::UnsafeUnwrapWebhookEvent, + IVariant +{ + public static UploadPostTransformSuccessEvent From( + Webhooks::UploadPostTransformSuccessEvent value + ) + { + return new(value); + } + + public override void Validate() + { + this.Value.Validate(); + } +} + +/// +/// Triggered when a post-transformation fails. The original file remains available, +/// but the requested transformation could not be generated. +/// +public sealed record class UploadPostTransformErrorEvent( + Webhooks::UploadPostTransformErrorEvent Value +) + : Webhooks::UnsafeUnwrapWebhookEvent, + IVariant +{ + public static UploadPostTransformErrorEvent From(Webhooks::UploadPostTransformErrorEvent value) + { + return new(value); + } + + public override void Validate() + { + this.Value.Validate(); + } +} diff --git a/src/Imagekit/Models/Webhooks/UnwrapWebhookEvent.cs b/src/Imagekit/Models/Webhooks/UnwrapWebhookEvent.cs new file mode 100644 index 00000000..fbecd090 --- /dev/null +++ b/src/Imagekit/Models/Webhooks/UnwrapWebhookEvent.cs @@ -0,0 +1,338 @@ +using System; +using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; +using System.Text.Json; +using System.Text.Json.Serialization; +using UnwrapWebhookEventVariants = Imagekit.Models.Webhooks.UnwrapWebhookEventVariants; + +namespace Imagekit.Models.Webhooks; + +/// +/// Triggered when a new video transformation request is accepted for processing. +/// This event confirms that ImageKit has received and queued your transformation +/// request. Use this for debugging and tracking transformation lifecycle. +/// +[JsonConverter(typeof(UnwrapWebhookEventConverter))] +public abstract record class UnwrapWebhookEvent +{ + internal UnwrapWebhookEvent() { } + + public static implicit operator UnwrapWebhookEvent(VideoTransformationAcceptedEvent value) => + new UnwrapWebhookEventVariants::VideoTransformationAcceptedEvent(value); + + public static implicit operator UnwrapWebhookEvent(VideoTransformationReadyEvent value) => + new UnwrapWebhookEventVariants::VideoTransformationReadyEvent(value); + + public static implicit operator UnwrapWebhookEvent(VideoTransformationErrorEvent value) => + new UnwrapWebhookEventVariants::VideoTransformationErrorEvent(value); + + public static implicit operator UnwrapWebhookEvent(UploadPreTransformSuccessEvent value) => + new UnwrapWebhookEventVariants::UploadPreTransformSuccessEvent(value); + + public static implicit operator UnwrapWebhookEvent(UploadPreTransformErrorEvent value) => + new UnwrapWebhookEventVariants::UploadPreTransformErrorEvent(value); + + public static implicit operator UnwrapWebhookEvent(UploadPostTransformSuccessEvent value) => + new UnwrapWebhookEventVariants::UploadPostTransformSuccessEvent(value); + + public static implicit operator UnwrapWebhookEvent(UploadPostTransformErrorEvent value) => + new UnwrapWebhookEventVariants::UploadPostTransformErrorEvent(value); + + public bool TryPickVideoTransformationAccepted( + [NotNullWhen(true)] out VideoTransformationAcceptedEvent? value + ) + { + value = (this as UnwrapWebhookEventVariants::VideoTransformationAcceptedEvent)?.Value; + return value != null; + } + + public bool TryPickVideoTransformationReady( + [NotNullWhen(true)] out VideoTransformationReadyEvent? value + ) + { + value = (this as UnwrapWebhookEventVariants::VideoTransformationReadyEvent)?.Value; + return value != null; + } + + public bool TryPickVideoTransformationError( + [NotNullWhen(true)] out VideoTransformationErrorEvent? value + ) + { + value = (this as UnwrapWebhookEventVariants::VideoTransformationErrorEvent)?.Value; + return value != null; + } + + public bool TryPickUploadPreTransformSuccess( + [NotNullWhen(true)] out UploadPreTransformSuccessEvent? value + ) + { + value = (this as UnwrapWebhookEventVariants::UploadPreTransformSuccessEvent)?.Value; + return value != null; + } + + public bool TryPickUploadPreTransformError( + [NotNullWhen(true)] out UploadPreTransformErrorEvent? value + ) + { + value = (this as UnwrapWebhookEventVariants::UploadPreTransformErrorEvent)?.Value; + return value != null; + } + + public bool TryPickUploadPostTransformSuccess( + [NotNullWhen(true)] out UploadPostTransformSuccessEvent? value + ) + { + value = (this as UnwrapWebhookEventVariants::UploadPostTransformSuccessEvent)?.Value; + return value != null; + } + + public bool TryPickUploadPostTransformError( + [NotNullWhen(true)] out UploadPostTransformErrorEvent? value + ) + { + value = (this as UnwrapWebhookEventVariants::UploadPostTransformErrorEvent)?.Value; + return value != null; + } + + public void Switch( + Action videoTransformationAccepted, + Action videoTransformationReady, + Action videoTransformationError, + Action uploadPreTransformSuccess, + Action uploadPreTransformError, + Action uploadPostTransformSuccess, + Action uploadPostTransformError + ) + { + switch (this) + { + case UnwrapWebhookEventVariants::VideoTransformationAcceptedEvent inner: + videoTransformationAccepted(inner); + break; + case UnwrapWebhookEventVariants::VideoTransformationReadyEvent inner: + videoTransformationReady(inner); + break; + case UnwrapWebhookEventVariants::VideoTransformationErrorEvent inner: + videoTransformationError(inner); + break; + case UnwrapWebhookEventVariants::UploadPreTransformSuccessEvent inner: + uploadPreTransformSuccess(inner); + break; + case UnwrapWebhookEventVariants::UploadPreTransformErrorEvent inner: + uploadPreTransformError(inner); + break; + case UnwrapWebhookEventVariants::UploadPostTransformSuccessEvent inner: + uploadPostTransformSuccess(inner); + break; + case UnwrapWebhookEventVariants::UploadPostTransformErrorEvent inner: + uploadPostTransformError(inner); + break; + default: + throw new InvalidOperationException(); + } + } + + public T Match( + Func< + UnwrapWebhookEventVariants::VideoTransformationAcceptedEvent, + T + > videoTransformationAccepted, + Func videoTransformationReady, + Func videoTransformationError, + Func< + UnwrapWebhookEventVariants::UploadPreTransformSuccessEvent, + T + > uploadPreTransformSuccess, + Func uploadPreTransformError, + Func< + UnwrapWebhookEventVariants::UploadPostTransformSuccessEvent, + T + > uploadPostTransformSuccess, + Func uploadPostTransformError + ) + { + return this switch + { + UnwrapWebhookEventVariants::VideoTransformationAcceptedEvent inner => + videoTransformationAccepted(inner), + UnwrapWebhookEventVariants::VideoTransformationReadyEvent inner => + videoTransformationReady(inner), + UnwrapWebhookEventVariants::VideoTransformationErrorEvent inner => + videoTransformationError(inner), + UnwrapWebhookEventVariants::UploadPreTransformSuccessEvent inner => + uploadPreTransformSuccess(inner), + UnwrapWebhookEventVariants::UploadPreTransformErrorEvent inner => + uploadPreTransformError(inner), + UnwrapWebhookEventVariants::UploadPostTransformSuccessEvent inner => + uploadPostTransformSuccess(inner), + UnwrapWebhookEventVariants::UploadPostTransformErrorEvent inner => + uploadPostTransformError(inner), + _ => throw new InvalidOperationException(), + }; + } + + public abstract void Validate(); +} + +sealed class UnwrapWebhookEventConverter : JsonConverter +{ + public override UnwrapWebhookEvent? Read( + ref Utf8JsonReader reader, + Type typeToConvert, + JsonSerializerOptions options + ) + { + List exceptions = []; + + try + { + var deserialized = JsonSerializer.Deserialize( + ref reader, + options + ); + if (deserialized != null) + { + return new UnwrapWebhookEventVariants::VideoTransformationAcceptedEvent( + deserialized + ); + } + } + catch (JsonException e) + { + exceptions.Add(e); + } + + try + { + var deserialized = JsonSerializer.Deserialize( + ref reader, + options + ); + if (deserialized != null) + { + return new UnwrapWebhookEventVariants::VideoTransformationReadyEvent(deserialized); + } + } + catch (JsonException e) + { + exceptions.Add(e); + } + + try + { + var deserialized = JsonSerializer.Deserialize( + ref reader, + options + ); + if (deserialized != null) + { + return new UnwrapWebhookEventVariants::VideoTransformationErrorEvent(deserialized); + } + } + catch (JsonException e) + { + exceptions.Add(e); + } + + try + { + var deserialized = JsonSerializer.Deserialize( + ref reader, + options + ); + if (deserialized != null) + { + return new UnwrapWebhookEventVariants::UploadPreTransformSuccessEvent(deserialized); + } + } + catch (JsonException e) + { + exceptions.Add(e); + } + + try + { + var deserialized = JsonSerializer.Deserialize( + ref reader, + options + ); + if (deserialized != null) + { + return new UnwrapWebhookEventVariants::UploadPreTransformErrorEvent(deserialized); + } + } + catch (JsonException e) + { + exceptions.Add(e); + } + + try + { + var deserialized = JsonSerializer.Deserialize( + ref reader, + options + ); + if (deserialized != null) + { + return new UnwrapWebhookEventVariants::UploadPostTransformSuccessEvent( + deserialized + ); + } + } + catch (JsonException e) + { + exceptions.Add(e); + } + + try + { + var deserialized = JsonSerializer.Deserialize( + ref reader, + options + ); + if (deserialized != null) + { + return new UnwrapWebhookEventVariants::UploadPostTransformErrorEvent(deserialized); + } + } + catch (JsonException e) + { + exceptions.Add(e); + } + + throw new AggregateException(exceptions); + } + + public override void Write( + Utf8JsonWriter writer, + UnwrapWebhookEvent value, + JsonSerializerOptions options + ) + { + object variant = value switch + { + UnwrapWebhookEventVariants::VideoTransformationAcceptedEvent( + var videoTransformationAccepted + ) => videoTransformationAccepted, + UnwrapWebhookEventVariants::VideoTransformationReadyEvent( + var videoTransformationReady + ) => videoTransformationReady, + UnwrapWebhookEventVariants::VideoTransformationErrorEvent( + var videoTransformationError + ) => videoTransformationError, + UnwrapWebhookEventVariants::UploadPreTransformSuccessEvent( + var uploadPreTransformSuccess + ) => uploadPreTransformSuccess, + UnwrapWebhookEventVariants::UploadPreTransformErrorEvent(var uploadPreTransformError) => + uploadPreTransformError, + UnwrapWebhookEventVariants::UploadPostTransformSuccessEvent( + var uploadPostTransformSuccess + ) => uploadPostTransformSuccess, + UnwrapWebhookEventVariants::UploadPostTransformErrorEvent( + var uploadPostTransformError + ) => uploadPostTransformError, + _ => throw new ArgumentOutOfRangeException(nameof(value)), + }; + JsonSerializer.Serialize(writer, variant, options); + } +} diff --git a/src/Imagekit/Models/Webhooks/UnwrapWebhookEventVariants/All.cs b/src/Imagekit/Models/Webhooks/UnwrapWebhookEventVariants/All.cs new file mode 100644 index 00000000..2f40319f --- /dev/null +++ b/src/Imagekit/Models/Webhooks/UnwrapWebhookEventVariants/All.cs @@ -0,0 +1,163 @@ +using Webhooks = Imagekit.Models.Webhooks; + +namespace Imagekit.Models.Webhooks.UnwrapWebhookEventVariants; + +/// +/// Triggered when a new video transformation request is accepted for processing. +/// This event confirms that ImageKit has received and queued your transformation +/// request. Use this for debugging and tracking transformation lifecycle. +/// +public sealed record class VideoTransformationAcceptedEvent( + Webhooks::VideoTransformationAcceptedEvent Value +) + : Webhooks::UnwrapWebhookEvent, + IVariant +{ + public static VideoTransformationAcceptedEvent From( + Webhooks::VideoTransformationAcceptedEvent value + ) + { + return new(value); + } + + public override void Validate() + { + this.Value.Validate(); + } +} + +/// +/// Triggered when video encoding is finished and the transformed resource is ready +/// to be served. This is the key event to listen for - update your database or CMS +/// flags when you receive this so your application can start showing the transformed +/// video to users. +/// +public sealed record class VideoTransformationReadyEvent( + Webhooks::VideoTransformationReadyEvent Value +) + : Webhooks::UnwrapWebhookEvent, + IVariant +{ + public static VideoTransformationReadyEvent From(Webhooks::VideoTransformationReadyEvent value) + { + return new(value); + } + + public override void Validate() + { + this.Value.Validate(); + } +} + +/// +/// Triggered when an error occurs during video encoding. Listen to this webhook to +/// log error reasons and debug issues. Check your origin and URL endpoint settings +/// if the reason is related to download failure. For other errors, contact ImageKit +/// support. +/// +public sealed record class VideoTransformationErrorEvent( + Webhooks::VideoTransformationErrorEvent Value +) + : Webhooks::UnwrapWebhookEvent, + IVariant +{ + public static VideoTransformationErrorEvent From(Webhooks::VideoTransformationErrorEvent value) + { + return new(value); + } + + public override void Validate() + { + this.Value.Validate(); + } +} + +/// +/// Triggered when a pre-transformation completes successfully. The file has been +/// processed with the requested transformation and is now available in the Media +/// Library. +/// +public sealed record class UploadPreTransformSuccessEvent( + Webhooks::UploadPreTransformSuccessEvent Value +) + : Webhooks::UnwrapWebhookEvent, + IVariant +{ + public static UploadPreTransformSuccessEvent From( + Webhooks::UploadPreTransformSuccessEvent value + ) + { + return new(value); + } + + public override void Validate() + { + this.Value.Validate(); + } +} + +/// +/// Triggered when a pre-transformation fails. The file upload may have been accepted, +/// but the requested transformation could not be applied. +/// +public sealed record class UploadPreTransformErrorEvent( + Webhooks::UploadPreTransformErrorEvent Value +) + : Webhooks::UnwrapWebhookEvent, + IVariant +{ + public static UploadPreTransformErrorEvent From(Webhooks::UploadPreTransformErrorEvent value) + { + return new(value); + } + + public override void Validate() + { + this.Value.Validate(); + } +} + +/// +/// Triggered when a post-transformation completes successfully. The transformed version +/// of the file is now ready and can be accessed via the provided URL. Note that +/// each post-transformation generates a separate webhook event. +/// +public sealed record class UploadPostTransformSuccessEvent( + Webhooks::UploadPostTransformSuccessEvent Value +) + : Webhooks::UnwrapWebhookEvent, + IVariant +{ + public static UploadPostTransformSuccessEvent From( + Webhooks::UploadPostTransformSuccessEvent value + ) + { + return new(value); + } + + public override void Validate() + { + this.Value.Validate(); + } +} + +/// +/// Triggered when a post-transformation fails. The original file remains available, +/// but the requested transformation could not be generated. +/// +public sealed record class UploadPostTransformErrorEvent( + Webhooks::UploadPostTransformErrorEvent Value +) + : Webhooks::UnwrapWebhookEvent, + IVariant +{ + public static UploadPostTransformErrorEvent From(Webhooks::UploadPostTransformErrorEvent value) + { + return new(value); + } + + public override void Validate() + { + this.Value.Validate(); + } +} diff --git a/src/Imagekit/Models/Webhooks/UploadPostTransformErrorEvent.cs b/src/Imagekit/Models/Webhooks/UploadPostTransformErrorEvent.cs new file mode 100644 index 00000000..b1b2422e --- /dev/null +++ b/src/Imagekit/Models/Webhooks/UploadPostTransformErrorEvent.cs @@ -0,0 +1,145 @@ +using System; +using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; +using System.Text.Json; +using System.Text.Json.Serialization; +using Imagekit.Models.Webhooks.UploadPostTransformErrorEventProperties; + +namespace Imagekit.Models.Webhooks; + +/// +/// Triggered when a post-transformation fails. The original file remains available, +/// but the requested transformation could not be generated. +/// +[JsonConverter(typeof(ModelConverter))] +public sealed record class UploadPostTransformErrorEvent + : ModelBase, + IFromRaw +{ + /// + /// Unique identifier for the event. + /// + public required string ID + { + get + { + if (!this.Properties.TryGetValue("id", out JsonElement element)) + throw new ArgumentOutOfRangeException("id", "Missing required argument"); + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions) + ?? throw new ArgumentNullException("id"); + } + set + { + this.Properties["id"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + /// + /// Timestamp of when the event occurred in ISO8601 format. + /// + public required DateTime CreatedAt + { + get + { + if (!this.Properties.TryGetValue("created_at", out JsonElement element)) + throw new ArgumentOutOfRangeException("created_at", "Missing required argument"); + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions); + } + set + { + this.Properties["created_at"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + public required Data Data + { + get + { + if (!this.Properties.TryGetValue("data", out JsonElement element)) + throw new ArgumentOutOfRangeException("data", "Missing required argument"); + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions) + ?? throw new ArgumentNullException("data"); + } + set + { + this.Properties["data"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + public required Request Request + { + get + { + if (!this.Properties.TryGetValue("request", out JsonElement element)) + throw new ArgumentOutOfRangeException("request", "Missing required argument"); + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions) + ?? throw new ArgumentNullException("request"); + } + set + { + this.Properties["request"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + public JsonElement Type + { + get + { + if (!this.Properties.TryGetValue("type", out JsonElement element)) + throw new ArgumentOutOfRangeException("type", "Missing required argument"); + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions); + } + set + { + this.Properties["type"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + public override void Validate() + { + _ = this.ID; + _ = this.CreatedAt; + this.Data.Validate(); + this.Request.Validate(); + } + + public UploadPostTransformErrorEvent() + { + this.Type = JsonSerializer.Deserialize("\"upload.post-transform.error\""); + } + +#pragma warning disable CS8618 + [SetsRequiredMembers] + UploadPostTransformErrorEvent(Dictionary properties) + { + Properties = properties; + } +#pragma warning restore CS8618 + + public static UploadPostTransformErrorEvent FromRawUnchecked( + Dictionary properties + ) + { + return new(properties); + } +} diff --git a/src/Imagekit/Models/Webhooks/UploadPostTransformErrorEventProperties/Data.cs b/src/Imagekit/Models/Webhooks/UploadPostTransformErrorEventProperties/Data.cs new file mode 100644 index 00000000..8783690a --- /dev/null +++ b/src/Imagekit/Models/Webhooks/UploadPostTransformErrorEventProperties/Data.cs @@ -0,0 +1,148 @@ +using System; +using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; +using System.Text.Json; +using System.Text.Json.Serialization; +using DataProperties = Imagekit.Models.Webhooks.UploadPostTransformErrorEventProperties.DataProperties; + +namespace Imagekit.Models.Webhooks.UploadPostTransformErrorEventProperties; + +[JsonConverter(typeof(ModelConverter))] +public sealed record class Data : ModelBase, IFromRaw +{ + /// + /// Unique identifier of the originally uploaded file. + /// + public required string FileID + { + get + { + if (!this.Properties.TryGetValue("fileId", out JsonElement element)) + throw new ArgumentOutOfRangeException("fileId", "Missing required argument"); + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions) + ?? throw new ArgumentNullException("fileId"); + } + set + { + this.Properties["fileId"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + /// + /// Name of the file. + /// + public required string Name + { + get + { + if (!this.Properties.TryGetValue("name", out JsonElement element)) + throw new ArgumentOutOfRangeException("name", "Missing required argument"); + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions) + ?? throw new ArgumentNullException("name"); + } + set + { + this.Properties["name"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + /// + /// Path of the file. + /// + public required string Path + { + get + { + if (!this.Properties.TryGetValue("path", out JsonElement element)) + throw new ArgumentOutOfRangeException("path", "Missing required argument"); + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions) + ?? throw new ArgumentNullException("path"); + } + set + { + this.Properties["path"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + public required DataProperties::Transformation Transformation + { + get + { + if (!this.Properties.TryGetValue("transformation", out JsonElement element)) + throw new ArgumentOutOfRangeException( + "transformation", + "Missing required argument" + ); + + return JsonSerializer.Deserialize( + element, + ModelBase.SerializerOptions + ) ?? throw new ArgumentNullException("transformation"); + } + set + { + this.Properties["transformation"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + /// + /// URL of the attempted post-transformation. + /// + public required string URL + { + get + { + if (!this.Properties.TryGetValue("url", out JsonElement element)) + throw new ArgumentOutOfRangeException("url", "Missing required argument"); + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions) + ?? throw new ArgumentNullException("url"); + } + set + { + this.Properties["url"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + public override void Validate() + { + _ = this.FileID; + _ = this.Name; + _ = this.Path; + this.Transformation.Validate(); + _ = this.URL; + } + + public Data() { } + +#pragma warning disable CS8618 + [SetsRequiredMembers] + Data(Dictionary properties) + { + Properties = properties; + } +#pragma warning restore CS8618 + + public static Data FromRawUnchecked(Dictionary properties) + { + return new(properties); + } +} diff --git a/src/Imagekit/Models/Webhooks/UploadPostTransformErrorEventProperties/DataProperties/Transformation.cs b/src/Imagekit/Models/Webhooks/UploadPostTransformErrorEventProperties/DataProperties/Transformation.cs new file mode 100644 index 00000000..bba97cac --- /dev/null +++ b/src/Imagekit/Models/Webhooks/UploadPostTransformErrorEventProperties/DataProperties/Transformation.cs @@ -0,0 +1,58 @@ +using System; +using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; +using System.Text.Json; +using System.Text.Json.Serialization; +using Imagekit.Models.Webhooks.UploadPostTransformErrorEventProperties.DataProperties.TransformationProperties; + +namespace Imagekit.Models.Webhooks.UploadPostTransformErrorEventProperties.DataProperties; + +[JsonConverter(typeof(ModelConverter))] +public sealed record class Transformation : ModelBase, IFromRaw +{ + public required Error Error + { + get + { + if (!this.Properties.TryGetValue("error", out JsonElement element)) + throw new ArgumentOutOfRangeException("error", "Missing required argument"); + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions) + ?? throw new ArgumentNullException("error"); + } + set + { + this.Properties["error"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + public override void Validate() + { + this.Error.Validate(); + } + + public Transformation() { } + +#pragma warning disable CS8618 + [SetsRequiredMembers] + Transformation(Dictionary properties) + { + Properties = properties; + } +#pragma warning restore CS8618 + + public static Transformation FromRawUnchecked(Dictionary properties) + { + return new(properties); + } + + [SetsRequiredMembers] + public Transformation(Error error) + : this() + { + this.Error = error; + } +} diff --git a/src/Imagekit/Models/Webhooks/UploadPostTransformErrorEventProperties/DataProperties/TransformationProperties/Error.cs b/src/Imagekit/Models/Webhooks/UploadPostTransformErrorEventProperties/DataProperties/TransformationProperties/Error.cs new file mode 100644 index 00000000..27ceead4 --- /dev/null +++ b/src/Imagekit/Models/Webhooks/UploadPostTransformErrorEventProperties/DataProperties/TransformationProperties/Error.cs @@ -0,0 +1,60 @@ +using System; +using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; +using System.Text.Json; +using System.Text.Json.Serialization; + +namespace Imagekit.Models.Webhooks.UploadPostTransformErrorEventProperties.DataProperties.TransformationProperties; + +[JsonConverter(typeof(ModelConverter))] +public sealed record class Error : ModelBase, IFromRaw +{ + /// + /// Reason for the post-transformation failure. + /// + public required string Reason + { + get + { + if (!this.Properties.TryGetValue("reason", out JsonElement element)) + throw new ArgumentOutOfRangeException("reason", "Missing required argument"); + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions) + ?? throw new ArgumentNullException("reason"); + } + set + { + this.Properties["reason"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + public override void Validate() + { + _ = this.Reason; + } + + public Error() { } + +#pragma warning disable CS8618 + [SetsRequiredMembers] + Error(Dictionary properties) + { + Properties = properties; + } +#pragma warning restore CS8618 + + public static Error FromRawUnchecked(Dictionary properties) + { + return new(properties); + } + + [SetsRequiredMembers] + public Error(string reason) + : this() + { + this.Reason = reason; + } +} diff --git a/src/Imagekit/Models/Webhooks/UploadPostTransformErrorEventProperties/Request.cs b/src/Imagekit/Models/Webhooks/UploadPostTransformErrorEventProperties/Request.cs new file mode 100644 index 00000000..8ba13301 --- /dev/null +++ b/src/Imagekit/Models/Webhooks/UploadPostTransformErrorEventProperties/Request.cs @@ -0,0 +1,79 @@ +using System; +using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; +using System.Text.Json; +using System.Text.Json.Serialization; +using RequestProperties = Imagekit.Models.Webhooks.UploadPostTransformErrorEventProperties.RequestProperties; + +namespace Imagekit.Models.Webhooks.UploadPostTransformErrorEventProperties; + +[JsonConverter(typeof(ModelConverter))] +public sealed record class Request : ModelBase, IFromRaw +{ + public required RequestProperties::Transformation Transformation + { + get + { + if (!this.Properties.TryGetValue("transformation", out JsonElement element)) + throw new ArgumentOutOfRangeException( + "transformation", + "Missing required argument" + ); + + return JsonSerializer.Deserialize( + element, + ModelBase.SerializerOptions + ) ?? throw new ArgumentNullException("transformation"); + } + set + { + this.Properties["transformation"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + /// + /// Unique identifier for the originating request. + /// + public required string XRequestID + { + get + { + if (!this.Properties.TryGetValue("x_request_id", out JsonElement element)) + throw new ArgumentOutOfRangeException("x_request_id", "Missing required argument"); + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions) + ?? throw new ArgumentNullException("x_request_id"); + } + set + { + this.Properties["x_request_id"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + public override void Validate() + { + this.Transformation.Validate(); + _ = this.XRequestID; + } + + public Request() { } + +#pragma warning disable CS8618 + [SetsRequiredMembers] + Request(Dictionary properties) + { + Properties = properties; + } +#pragma warning restore CS8618 + + public static Request FromRawUnchecked(Dictionary properties) + { + return new(properties); + } +} diff --git a/src/Imagekit/Models/Webhooks/UploadPostTransformErrorEventProperties/RequestProperties/Transformation.cs b/src/Imagekit/Models/Webhooks/UploadPostTransformErrorEventProperties/RequestProperties/Transformation.cs new file mode 100644 index 00000000..d3569f92 --- /dev/null +++ b/src/Imagekit/Models/Webhooks/UploadPostTransformErrorEventProperties/RequestProperties/Transformation.cs @@ -0,0 +1,110 @@ +using System; +using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; +using System.Text.Json; +using System.Text.Json.Serialization; +using TransformationProperties = Imagekit.Models.Webhooks.UploadPostTransformErrorEventProperties.RequestProperties.TransformationProperties; + +namespace Imagekit.Models.Webhooks.UploadPostTransformErrorEventProperties.RequestProperties; + +[JsonConverter(typeof(ModelConverter))] +public sealed record class Transformation : ModelBase, IFromRaw +{ + /// + /// Type of the requested post-transformation. + /// + public required ApiEnum Type + { + get + { + if (!this.Properties.TryGetValue("type", out JsonElement element)) + throw new ArgumentOutOfRangeException("type", "Missing required argument"); + + return JsonSerializer.Deserialize>( + element, + ModelBase.SerializerOptions + ); + } + set + { + this.Properties["type"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + /// + /// Only applicable if transformation type is 'abs'. Streaming protocol used. + /// + public ApiEnum? Protocol + { + get + { + if (!this.Properties.TryGetValue("protocol", out JsonElement element)) + return null; + + return JsonSerializer.Deserialize?>( + element, + ModelBase.SerializerOptions + ); + } + set + { + this.Properties["protocol"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + /// + /// Value for the requested transformation type. + /// + public string? Value + { + get + { + if (!this.Properties.TryGetValue("value", out JsonElement element)) + return null; + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions); + } + set + { + this.Properties["value"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + public override void Validate() + { + this.Type.Validate(); + this.Protocol?.Validate(); + _ = this.Value; + } + + public Transformation() { } + +#pragma warning disable CS8618 + [SetsRequiredMembers] + Transformation(Dictionary properties) + { + Properties = properties; + } +#pragma warning restore CS8618 + + public static Transformation FromRawUnchecked(Dictionary properties) + { + return new(properties); + } + + [SetsRequiredMembers] + public Transformation(ApiEnum type) + : this() + { + this.Type = type; + } +} diff --git a/src/Imagekit/Models/Webhooks/UploadPostTransformErrorEventProperties/RequestProperties/TransformationProperties/Protocol.cs b/src/Imagekit/Models/Webhooks/UploadPostTransformErrorEventProperties/RequestProperties/TransformationProperties/Protocol.cs new file mode 100644 index 00000000..734a713f --- /dev/null +++ b/src/Imagekit/Models/Webhooks/UploadPostTransformErrorEventProperties/RequestProperties/TransformationProperties/Protocol.cs @@ -0,0 +1,46 @@ +using System.Text.Json; +using System.Text.Json.Serialization; +using System = System; + +namespace Imagekit.Models.Webhooks.UploadPostTransformErrorEventProperties.RequestProperties.TransformationProperties; + +/// +/// Only applicable if transformation type is 'abs'. Streaming protocol used. +/// +[JsonConverter(typeof(ProtocolConverter))] +public enum Protocol +{ + Hls, + Dash, +} + +sealed class ProtocolConverter : JsonConverter +{ + public override Protocol Read( + ref Utf8JsonReader reader, + System::Type typeToConvert, + JsonSerializerOptions options + ) + { + return JsonSerializer.Deserialize(ref reader, options) switch + { + "hls" => Protocol.Hls, + "dash" => Protocol.Dash, + _ => (Protocol)(-1), + }; + } + + public override void Write(Utf8JsonWriter writer, Protocol value, JsonSerializerOptions options) + { + JsonSerializer.Serialize( + writer, + value switch + { + Protocol.Hls => "hls", + Protocol.Dash => "dash", + _ => throw new System::ArgumentOutOfRangeException(nameof(value)), + }, + options + ); + } +} diff --git a/src/Imagekit/Models/Webhooks/UploadPostTransformErrorEventProperties/RequestProperties/TransformationProperties/Type.cs b/src/Imagekit/Models/Webhooks/UploadPostTransformErrorEventProperties/RequestProperties/TransformationProperties/Type.cs new file mode 100644 index 00000000..aa052bf9 --- /dev/null +++ b/src/Imagekit/Models/Webhooks/UploadPostTransformErrorEventProperties/RequestProperties/TransformationProperties/Type.cs @@ -0,0 +1,52 @@ +using System.Text.Json; +using System.Text.Json.Serialization; +using System = System; + +namespace Imagekit.Models.Webhooks.UploadPostTransformErrorEventProperties.RequestProperties.TransformationProperties; + +/// +/// Type of the requested post-transformation. +/// +[JsonConverter(typeof(TypeConverter))] +public enum Type +{ + Transformation, + Abs, + GifToVideo, + Thumbnail, +} + +sealed class TypeConverter : JsonConverter +{ + public override Type Read( + ref Utf8JsonReader reader, + System::Type typeToConvert, + JsonSerializerOptions options + ) + { + return JsonSerializer.Deserialize(ref reader, options) switch + { + "transformation" => TransformationProperties.Type.Transformation, + "abs" => TransformationProperties.Type.Abs, + "gif-to-video" => TransformationProperties.Type.GifToVideo, + "thumbnail" => TransformationProperties.Type.Thumbnail, + _ => (Type)(-1), + }; + } + + public override void Write(Utf8JsonWriter writer, Type value, JsonSerializerOptions options) + { + JsonSerializer.Serialize( + writer, + value switch + { + TransformationProperties.Type.Transformation => "transformation", + TransformationProperties.Type.Abs => "abs", + TransformationProperties.Type.GifToVideo => "gif-to-video", + TransformationProperties.Type.Thumbnail => "thumbnail", + _ => throw new System::ArgumentOutOfRangeException(nameof(value)), + }, + options + ); + } +} diff --git a/src/Imagekit/Models/Webhooks/UploadPostTransformSuccessEvent.cs b/src/Imagekit/Models/Webhooks/UploadPostTransformSuccessEvent.cs new file mode 100644 index 00000000..c4e0933c --- /dev/null +++ b/src/Imagekit/Models/Webhooks/UploadPostTransformSuccessEvent.cs @@ -0,0 +1,146 @@ +using System; +using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; +using System.Text.Json; +using System.Text.Json.Serialization; +using Imagekit.Models.Webhooks.UploadPostTransformSuccessEventProperties; + +namespace Imagekit.Models.Webhooks; + +/// +/// Triggered when a post-transformation completes successfully. The transformed version +/// of the file is now ready and can be accessed via the provided URL. Note that +/// each post-transformation generates a separate webhook event. +/// +[JsonConverter(typeof(ModelConverter))] +public sealed record class UploadPostTransformSuccessEvent + : ModelBase, + IFromRaw +{ + /// + /// Unique identifier for the event. + /// + public required string ID + { + get + { + if (!this.Properties.TryGetValue("id", out JsonElement element)) + throw new ArgumentOutOfRangeException("id", "Missing required argument"); + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions) + ?? throw new ArgumentNullException("id"); + } + set + { + this.Properties["id"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + /// + /// Timestamp of when the event occurred in ISO8601 format. + /// + public required DateTime CreatedAt + { + get + { + if (!this.Properties.TryGetValue("created_at", out JsonElement element)) + throw new ArgumentOutOfRangeException("created_at", "Missing required argument"); + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions); + } + set + { + this.Properties["created_at"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + public required Data Data + { + get + { + if (!this.Properties.TryGetValue("data", out JsonElement element)) + throw new ArgumentOutOfRangeException("data", "Missing required argument"); + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions) + ?? throw new ArgumentNullException("data"); + } + set + { + this.Properties["data"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + public required Request Request + { + get + { + if (!this.Properties.TryGetValue("request", out JsonElement element)) + throw new ArgumentOutOfRangeException("request", "Missing required argument"); + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions) + ?? throw new ArgumentNullException("request"); + } + set + { + this.Properties["request"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + public JsonElement Type + { + get + { + if (!this.Properties.TryGetValue("type", out JsonElement element)) + throw new ArgumentOutOfRangeException("type", "Missing required argument"); + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions); + } + set + { + this.Properties["type"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + public override void Validate() + { + _ = this.ID; + _ = this.CreatedAt; + this.Data.Validate(); + this.Request.Validate(); + } + + public UploadPostTransformSuccessEvent() + { + this.Type = JsonSerializer.Deserialize("\"upload.post-transform.success\""); + } + +#pragma warning disable CS8618 + [SetsRequiredMembers] + UploadPostTransformSuccessEvent(Dictionary properties) + { + Properties = properties; + } +#pragma warning restore CS8618 + + public static UploadPostTransformSuccessEvent FromRawUnchecked( + Dictionary properties + ) + { + return new(properties); + } +} diff --git a/src/Imagekit/Models/Webhooks/UploadPostTransformSuccessEventProperties/Data.cs b/src/Imagekit/Models/Webhooks/UploadPostTransformSuccessEventProperties/Data.cs new file mode 100644 index 00000000..e24a161d --- /dev/null +++ b/src/Imagekit/Models/Webhooks/UploadPostTransformSuccessEventProperties/Data.cs @@ -0,0 +1,99 @@ +using System; +using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; +using System.Text.Json; +using System.Text.Json.Serialization; + +namespace Imagekit.Models.Webhooks.UploadPostTransformSuccessEventProperties; + +[JsonConverter(typeof(ModelConverter))] +public sealed record class Data : ModelBase, IFromRaw +{ + /// + /// Unique identifier of the originally uploaded file. + /// + public required string FileID + { + get + { + if (!this.Properties.TryGetValue("fileId", out JsonElement element)) + throw new ArgumentOutOfRangeException("fileId", "Missing required argument"); + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions) + ?? throw new ArgumentNullException("fileId"); + } + set + { + this.Properties["fileId"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + /// + /// Name of the file. + /// + public required string Name + { + get + { + if (!this.Properties.TryGetValue("name", out JsonElement element)) + throw new ArgumentOutOfRangeException("name", "Missing required argument"); + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions) + ?? throw new ArgumentNullException("name"); + } + set + { + this.Properties["name"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + /// + /// URL of the generated post-transformation. + /// + public required string URL + { + get + { + if (!this.Properties.TryGetValue("url", out JsonElement element)) + throw new ArgumentOutOfRangeException("url", "Missing required argument"); + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions) + ?? throw new ArgumentNullException("url"); + } + set + { + this.Properties["url"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + public override void Validate() + { + _ = this.FileID; + _ = this.Name; + _ = this.URL; + } + + public Data() { } + +#pragma warning disable CS8618 + [SetsRequiredMembers] + Data(Dictionary properties) + { + Properties = properties; + } +#pragma warning restore CS8618 + + public static Data FromRawUnchecked(Dictionary properties) + { + return new(properties); + } +} diff --git a/src/Imagekit/Models/Webhooks/UploadPostTransformSuccessEventProperties/Request.cs b/src/Imagekit/Models/Webhooks/UploadPostTransformSuccessEventProperties/Request.cs new file mode 100644 index 00000000..2a643bb9 --- /dev/null +++ b/src/Imagekit/Models/Webhooks/UploadPostTransformSuccessEventProperties/Request.cs @@ -0,0 +1,79 @@ +using System; +using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; +using System.Text.Json; +using System.Text.Json.Serialization; +using RequestProperties = Imagekit.Models.Webhooks.UploadPostTransformSuccessEventProperties.RequestProperties; + +namespace Imagekit.Models.Webhooks.UploadPostTransformSuccessEventProperties; + +[JsonConverter(typeof(ModelConverter))] +public sealed record class Request : ModelBase, IFromRaw +{ + public required RequestProperties::Transformation Transformation + { + get + { + if (!this.Properties.TryGetValue("transformation", out JsonElement element)) + throw new ArgumentOutOfRangeException( + "transformation", + "Missing required argument" + ); + + return JsonSerializer.Deserialize( + element, + ModelBase.SerializerOptions + ) ?? throw new ArgumentNullException("transformation"); + } + set + { + this.Properties["transformation"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + /// + /// Unique identifier for the originating request. + /// + public required string XRequestID + { + get + { + if (!this.Properties.TryGetValue("x_request_id", out JsonElement element)) + throw new ArgumentOutOfRangeException("x_request_id", "Missing required argument"); + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions) + ?? throw new ArgumentNullException("x_request_id"); + } + set + { + this.Properties["x_request_id"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + public override void Validate() + { + this.Transformation.Validate(); + _ = this.XRequestID; + } + + public Request() { } + +#pragma warning disable CS8618 + [SetsRequiredMembers] + Request(Dictionary properties) + { + Properties = properties; + } +#pragma warning restore CS8618 + + public static Request FromRawUnchecked(Dictionary properties) + { + return new(properties); + } +} diff --git a/src/Imagekit/Models/Webhooks/UploadPostTransformSuccessEventProperties/RequestProperties/Transformation.cs b/src/Imagekit/Models/Webhooks/UploadPostTransformSuccessEventProperties/RequestProperties/Transformation.cs new file mode 100644 index 00000000..cf8044dc --- /dev/null +++ b/src/Imagekit/Models/Webhooks/UploadPostTransformSuccessEventProperties/RequestProperties/Transformation.cs @@ -0,0 +1,110 @@ +using System; +using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; +using System.Text.Json; +using System.Text.Json.Serialization; +using TransformationProperties = Imagekit.Models.Webhooks.UploadPostTransformSuccessEventProperties.RequestProperties.TransformationProperties; + +namespace Imagekit.Models.Webhooks.UploadPostTransformSuccessEventProperties.RequestProperties; + +[JsonConverter(typeof(ModelConverter))] +public sealed record class Transformation : ModelBase, IFromRaw +{ + /// + /// Type of the requested post-transformation. + /// + public required ApiEnum Type + { + get + { + if (!this.Properties.TryGetValue("type", out JsonElement element)) + throw new ArgumentOutOfRangeException("type", "Missing required argument"); + + return JsonSerializer.Deserialize>( + element, + ModelBase.SerializerOptions + ); + } + set + { + this.Properties["type"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + /// + /// Only applicable if transformation type is 'abs'. Streaming protocol used. + /// + public ApiEnum? Protocol + { + get + { + if (!this.Properties.TryGetValue("protocol", out JsonElement element)) + return null; + + return JsonSerializer.Deserialize?>( + element, + ModelBase.SerializerOptions + ); + } + set + { + this.Properties["protocol"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + /// + /// Value for the requested transformation type. + /// + public string? Value + { + get + { + if (!this.Properties.TryGetValue("value", out JsonElement element)) + return null; + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions); + } + set + { + this.Properties["value"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + public override void Validate() + { + this.Type.Validate(); + this.Protocol?.Validate(); + _ = this.Value; + } + + public Transformation() { } + +#pragma warning disable CS8618 + [SetsRequiredMembers] + Transformation(Dictionary properties) + { + Properties = properties; + } +#pragma warning restore CS8618 + + public static Transformation FromRawUnchecked(Dictionary properties) + { + return new(properties); + } + + [SetsRequiredMembers] + public Transformation(ApiEnum type) + : this() + { + this.Type = type; + } +} diff --git a/src/Imagekit/Models/Webhooks/UploadPostTransformSuccessEventProperties/RequestProperties/TransformationProperties/Protocol.cs b/src/Imagekit/Models/Webhooks/UploadPostTransformSuccessEventProperties/RequestProperties/TransformationProperties/Protocol.cs new file mode 100644 index 00000000..745547da --- /dev/null +++ b/src/Imagekit/Models/Webhooks/UploadPostTransformSuccessEventProperties/RequestProperties/TransformationProperties/Protocol.cs @@ -0,0 +1,46 @@ +using System.Text.Json; +using System.Text.Json.Serialization; +using System = System; + +namespace Imagekit.Models.Webhooks.UploadPostTransformSuccessEventProperties.RequestProperties.TransformationProperties; + +/// +/// Only applicable if transformation type is 'abs'. Streaming protocol used. +/// +[JsonConverter(typeof(ProtocolConverter))] +public enum Protocol +{ + Hls, + Dash, +} + +sealed class ProtocolConverter : JsonConverter +{ + public override Protocol Read( + ref Utf8JsonReader reader, + System::Type typeToConvert, + JsonSerializerOptions options + ) + { + return JsonSerializer.Deserialize(ref reader, options) switch + { + "hls" => Protocol.Hls, + "dash" => Protocol.Dash, + _ => (Protocol)(-1), + }; + } + + public override void Write(Utf8JsonWriter writer, Protocol value, JsonSerializerOptions options) + { + JsonSerializer.Serialize( + writer, + value switch + { + Protocol.Hls => "hls", + Protocol.Dash => "dash", + _ => throw new System::ArgumentOutOfRangeException(nameof(value)), + }, + options + ); + } +} diff --git a/src/Imagekit/Models/Webhooks/UploadPostTransformSuccessEventProperties/RequestProperties/TransformationProperties/Type.cs b/src/Imagekit/Models/Webhooks/UploadPostTransformSuccessEventProperties/RequestProperties/TransformationProperties/Type.cs new file mode 100644 index 00000000..5ef8fe08 --- /dev/null +++ b/src/Imagekit/Models/Webhooks/UploadPostTransformSuccessEventProperties/RequestProperties/TransformationProperties/Type.cs @@ -0,0 +1,52 @@ +using System.Text.Json; +using System.Text.Json.Serialization; +using System = System; + +namespace Imagekit.Models.Webhooks.UploadPostTransformSuccessEventProperties.RequestProperties.TransformationProperties; + +/// +/// Type of the requested post-transformation. +/// +[JsonConverter(typeof(TypeConverter))] +public enum Type +{ + Transformation, + Abs, + GifToVideo, + Thumbnail, +} + +sealed class TypeConverter : JsonConverter +{ + public override Type Read( + ref Utf8JsonReader reader, + System::Type typeToConvert, + JsonSerializerOptions options + ) + { + return JsonSerializer.Deserialize(ref reader, options) switch + { + "transformation" => TransformationProperties.Type.Transformation, + "abs" => TransformationProperties.Type.Abs, + "gif-to-video" => TransformationProperties.Type.GifToVideo, + "thumbnail" => TransformationProperties.Type.Thumbnail, + _ => (Type)(-1), + }; + } + + public override void Write(Utf8JsonWriter writer, Type value, JsonSerializerOptions options) + { + JsonSerializer.Serialize( + writer, + value switch + { + TransformationProperties.Type.Transformation => "transformation", + TransformationProperties.Type.Abs => "abs", + TransformationProperties.Type.GifToVideo => "gif-to-video", + TransformationProperties.Type.Thumbnail => "thumbnail", + _ => throw new System::ArgumentOutOfRangeException(nameof(value)), + }, + options + ); + } +} diff --git a/src/Imagekit/Models/Webhooks/UploadPreTransformErrorEvent.cs b/src/Imagekit/Models/Webhooks/UploadPreTransformErrorEvent.cs new file mode 100644 index 00000000..c3d1ac50 --- /dev/null +++ b/src/Imagekit/Models/Webhooks/UploadPreTransformErrorEvent.cs @@ -0,0 +1,145 @@ +using System; +using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; +using System.Text.Json; +using System.Text.Json.Serialization; +using Imagekit.Models.Webhooks.UploadPreTransformErrorEventProperties; + +namespace Imagekit.Models.Webhooks; + +/// +/// Triggered when a pre-transformation fails. The file upload may have been accepted, +/// but the requested transformation could not be applied. +/// +[JsonConverter(typeof(ModelConverter))] +public sealed record class UploadPreTransformErrorEvent + : ModelBase, + IFromRaw +{ + /// + /// Unique identifier for the event. + /// + public required string ID + { + get + { + if (!this.Properties.TryGetValue("id", out JsonElement element)) + throw new ArgumentOutOfRangeException("id", "Missing required argument"); + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions) + ?? throw new ArgumentNullException("id"); + } + set + { + this.Properties["id"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + /// + /// Timestamp of when the event occurred in ISO8601 format. + /// + public required DateTime CreatedAt + { + get + { + if (!this.Properties.TryGetValue("created_at", out JsonElement element)) + throw new ArgumentOutOfRangeException("created_at", "Missing required argument"); + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions); + } + set + { + this.Properties["created_at"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + public required Data Data + { + get + { + if (!this.Properties.TryGetValue("data", out JsonElement element)) + throw new ArgumentOutOfRangeException("data", "Missing required argument"); + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions) + ?? throw new ArgumentNullException("data"); + } + set + { + this.Properties["data"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + public required Request Request + { + get + { + if (!this.Properties.TryGetValue("request", out JsonElement element)) + throw new ArgumentOutOfRangeException("request", "Missing required argument"); + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions) + ?? throw new ArgumentNullException("request"); + } + set + { + this.Properties["request"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + public JsonElement Type + { + get + { + if (!this.Properties.TryGetValue("type", out JsonElement element)) + throw new ArgumentOutOfRangeException("type", "Missing required argument"); + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions); + } + set + { + this.Properties["type"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + public override void Validate() + { + _ = this.ID; + _ = this.CreatedAt; + this.Data.Validate(); + this.Request.Validate(); + } + + public UploadPreTransformErrorEvent() + { + this.Type = JsonSerializer.Deserialize("\"upload.pre-transform.error\""); + } + +#pragma warning disable CS8618 + [SetsRequiredMembers] + UploadPreTransformErrorEvent(Dictionary properties) + { + Properties = properties; + } +#pragma warning restore CS8618 + + public static UploadPreTransformErrorEvent FromRawUnchecked( + Dictionary properties + ) + { + return new(properties); + } +} diff --git a/src/Imagekit/Models/Webhooks/UploadPreTransformErrorEventProperties/Data.cs b/src/Imagekit/Models/Webhooks/UploadPreTransformErrorEventProperties/Data.cs new file mode 100644 index 00000000..76be65b6 --- /dev/null +++ b/src/Imagekit/Models/Webhooks/UploadPreTransformErrorEventProperties/Data.cs @@ -0,0 +1,102 @@ +using System; +using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; +using System.Text.Json; +using System.Text.Json.Serialization; +using DataProperties = Imagekit.Models.Webhooks.UploadPreTransformErrorEventProperties.DataProperties; + +namespace Imagekit.Models.Webhooks.UploadPreTransformErrorEventProperties; + +[JsonConverter(typeof(ModelConverter))] +public sealed record class Data : ModelBase, IFromRaw +{ + /// + /// Name of the file. + /// + public required string Name + { + get + { + if (!this.Properties.TryGetValue("name", out JsonElement element)) + throw new ArgumentOutOfRangeException("name", "Missing required argument"); + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions) + ?? throw new ArgumentNullException("name"); + } + set + { + this.Properties["name"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + /// + /// Path of the file. + /// + public required string Path + { + get + { + if (!this.Properties.TryGetValue("path", out JsonElement element)) + throw new ArgumentOutOfRangeException("path", "Missing required argument"); + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions) + ?? throw new ArgumentNullException("path"); + } + set + { + this.Properties["path"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + public required DataProperties::Transformation Transformation + { + get + { + if (!this.Properties.TryGetValue("transformation", out JsonElement element)) + throw new ArgumentOutOfRangeException( + "transformation", + "Missing required argument" + ); + + return JsonSerializer.Deserialize( + element, + ModelBase.SerializerOptions + ) ?? throw new ArgumentNullException("transformation"); + } + set + { + this.Properties["transformation"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + public override void Validate() + { + _ = this.Name; + _ = this.Path; + this.Transformation.Validate(); + } + + public Data() { } + +#pragma warning disable CS8618 + [SetsRequiredMembers] + Data(Dictionary properties) + { + Properties = properties; + } +#pragma warning restore CS8618 + + public static Data FromRawUnchecked(Dictionary properties) + { + return new(properties); + } +} diff --git a/src/Imagekit/Models/Webhooks/UploadPreTransformErrorEventProperties/DataProperties/Transformation.cs b/src/Imagekit/Models/Webhooks/UploadPreTransformErrorEventProperties/DataProperties/Transformation.cs new file mode 100644 index 00000000..db92626f --- /dev/null +++ b/src/Imagekit/Models/Webhooks/UploadPreTransformErrorEventProperties/DataProperties/Transformation.cs @@ -0,0 +1,58 @@ +using System; +using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; +using System.Text.Json; +using System.Text.Json.Serialization; +using Imagekit.Models.Webhooks.UploadPreTransformErrorEventProperties.DataProperties.TransformationProperties; + +namespace Imagekit.Models.Webhooks.UploadPreTransformErrorEventProperties.DataProperties; + +[JsonConverter(typeof(ModelConverter))] +public sealed record class Transformation : ModelBase, IFromRaw +{ + public required Error Error + { + get + { + if (!this.Properties.TryGetValue("error", out JsonElement element)) + throw new ArgumentOutOfRangeException("error", "Missing required argument"); + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions) + ?? throw new ArgumentNullException("error"); + } + set + { + this.Properties["error"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + public override void Validate() + { + this.Error.Validate(); + } + + public Transformation() { } + +#pragma warning disable CS8618 + [SetsRequiredMembers] + Transformation(Dictionary properties) + { + Properties = properties; + } +#pragma warning restore CS8618 + + public static Transformation FromRawUnchecked(Dictionary properties) + { + return new(properties); + } + + [SetsRequiredMembers] + public Transformation(Error error) + : this() + { + this.Error = error; + } +} diff --git a/src/Imagekit/Models/Webhooks/UploadPreTransformErrorEventProperties/DataProperties/TransformationProperties/Error.cs b/src/Imagekit/Models/Webhooks/UploadPreTransformErrorEventProperties/DataProperties/TransformationProperties/Error.cs new file mode 100644 index 00000000..1ff05383 --- /dev/null +++ b/src/Imagekit/Models/Webhooks/UploadPreTransformErrorEventProperties/DataProperties/TransformationProperties/Error.cs @@ -0,0 +1,60 @@ +using System; +using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; +using System.Text.Json; +using System.Text.Json.Serialization; + +namespace Imagekit.Models.Webhooks.UploadPreTransformErrorEventProperties.DataProperties.TransformationProperties; + +[JsonConverter(typeof(ModelConverter))] +public sealed record class Error : ModelBase, IFromRaw +{ + /// + /// Reason for the pre-transformation failure. + /// + public required string Reason + { + get + { + if (!this.Properties.TryGetValue("reason", out JsonElement element)) + throw new ArgumentOutOfRangeException("reason", "Missing required argument"); + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions) + ?? throw new ArgumentNullException("reason"); + } + set + { + this.Properties["reason"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + public override void Validate() + { + _ = this.Reason; + } + + public Error() { } + +#pragma warning disable CS8618 + [SetsRequiredMembers] + Error(Dictionary properties) + { + Properties = properties; + } +#pragma warning restore CS8618 + + public static Error FromRawUnchecked(Dictionary properties) + { + return new(properties); + } + + [SetsRequiredMembers] + public Error(string reason) + : this() + { + this.Reason = reason; + } +} diff --git a/src/Imagekit/Models/Webhooks/UploadPreTransformErrorEventProperties/Request.cs b/src/Imagekit/Models/Webhooks/UploadPreTransformErrorEventProperties/Request.cs new file mode 100644 index 00000000..78a656e2 --- /dev/null +++ b/src/Imagekit/Models/Webhooks/UploadPreTransformErrorEventProperties/Request.cs @@ -0,0 +1,79 @@ +using System; +using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; +using System.Text.Json; +using System.Text.Json.Serialization; + +namespace Imagekit.Models.Webhooks.UploadPreTransformErrorEventProperties; + +[JsonConverter(typeof(ModelConverter))] +public sealed record class Request : ModelBase, IFromRaw +{ + /// + /// The requested pre-transformation string. + /// + public required string Transformation + { + get + { + if (!this.Properties.TryGetValue("transformation", out JsonElement element)) + throw new ArgumentOutOfRangeException( + "transformation", + "Missing required argument" + ); + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions) + ?? throw new ArgumentNullException("transformation"); + } + set + { + this.Properties["transformation"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + /// + /// Unique identifier for the originating request. + /// + public required string XRequestID + { + get + { + if (!this.Properties.TryGetValue("x_request_id", out JsonElement element)) + throw new ArgumentOutOfRangeException("x_request_id", "Missing required argument"); + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions) + ?? throw new ArgumentNullException("x_request_id"); + } + set + { + this.Properties["x_request_id"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + public override void Validate() + { + _ = this.Transformation; + _ = this.XRequestID; + } + + public Request() { } + +#pragma warning disable CS8618 + [SetsRequiredMembers] + Request(Dictionary properties) + { + Properties = properties; + } +#pragma warning restore CS8618 + + public static Request FromRawUnchecked(Dictionary properties) + { + return new(properties); + } +} diff --git a/src/Imagekit/Models/Webhooks/UploadPreTransformSuccessEvent.cs b/src/Imagekit/Models/Webhooks/UploadPreTransformSuccessEvent.cs new file mode 100644 index 00000000..11b65760 --- /dev/null +++ b/src/Imagekit/Models/Webhooks/UploadPreTransformSuccessEvent.cs @@ -0,0 +1,149 @@ +using System; +using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; +using System.Text.Json; +using System.Text.Json.Serialization; +using Imagekit.Models.Webhooks.UploadPreTransformSuccessEventProperties; + +namespace Imagekit.Models.Webhooks; + +/// +/// Triggered when a pre-transformation completes successfully. The file has been +/// processed with the requested transformation and is now available in the Media +/// Library. +/// +[JsonConverter(typeof(ModelConverter))] +public sealed record class UploadPreTransformSuccessEvent + : ModelBase, + IFromRaw +{ + /// + /// Unique identifier for the event. + /// + public required string ID + { + get + { + if (!this.Properties.TryGetValue("id", out JsonElement element)) + throw new ArgumentOutOfRangeException("id", "Missing required argument"); + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions) + ?? throw new ArgumentNullException("id"); + } + set + { + this.Properties["id"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + /// + /// Timestamp of when the event occurred in ISO8601 format. + /// + public required DateTime CreatedAt + { + get + { + if (!this.Properties.TryGetValue("created_at", out JsonElement element)) + throw new ArgumentOutOfRangeException("created_at", "Missing required argument"); + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions); + } + set + { + this.Properties["created_at"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + /// + /// Object containing details of a successful upload. + /// + public required Data Data + { + get + { + if (!this.Properties.TryGetValue("data", out JsonElement element)) + throw new ArgumentOutOfRangeException("data", "Missing required argument"); + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions) + ?? throw new ArgumentNullException("data"); + } + set + { + this.Properties["data"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + public required Request Request + { + get + { + if (!this.Properties.TryGetValue("request", out JsonElement element)) + throw new ArgumentOutOfRangeException("request", "Missing required argument"); + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions) + ?? throw new ArgumentNullException("request"); + } + set + { + this.Properties["request"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + public JsonElement Type + { + get + { + if (!this.Properties.TryGetValue("type", out JsonElement element)) + throw new ArgumentOutOfRangeException("type", "Missing required argument"); + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions); + } + set + { + this.Properties["type"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + public override void Validate() + { + _ = this.ID; + _ = this.CreatedAt; + this.Data.Validate(); + this.Request.Validate(); + } + + public UploadPreTransformSuccessEvent() + { + this.Type = JsonSerializer.Deserialize("\"upload.pre-transform.success\""); + } + +#pragma warning disable CS8618 + [SetsRequiredMembers] + UploadPreTransformSuccessEvent(Dictionary properties) + { + Properties = properties; + } +#pragma warning restore CS8618 + + public static UploadPreTransformSuccessEvent FromRawUnchecked( + Dictionary properties + ) + { + return new(properties); + } +} diff --git a/src/Imagekit/Models/Webhooks/UploadPreTransformSuccessEventProperties/Data.cs b/src/Imagekit/Models/Webhooks/UploadPreTransformSuccessEventProperties/Data.cs new file mode 100644 index 00000000..52c1dc77 --- /dev/null +++ b/src/Imagekit/Models/Webhooks/UploadPreTransformSuccessEventProperties/Data.cs @@ -0,0 +1,613 @@ +using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; +using System.Text.Json; +using System.Text.Json.Serialization; +using Imagekit.Models.Files; +using Imagekit.Models.Webhooks.UploadPreTransformSuccessEventProperties.DataProperties; + +namespace Imagekit.Models.Webhooks.UploadPreTransformSuccessEventProperties; + +/// +/// Object containing details of a successful upload. +/// +[JsonConverter(typeof(ModelConverter))] +public sealed record class Data : ModelBase, IFromRaw +{ + /// + /// An array of tags assigned to the uploaded file by auto tagging. + /// + public List? AITags + { + get + { + if (!this.Properties.TryGetValue("AITags", out JsonElement element)) + return null; + + return JsonSerializer.Deserialize?>(element, ModelBase.SerializerOptions); + } + set + { + this.Properties["AITags"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + /// + /// The audio codec used in the video (only for video). + /// + public string? AudioCodec + { + get + { + if (!this.Properties.TryGetValue("audioCodec", out JsonElement element)) + return null; + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions); + } + set + { + this.Properties["audioCodec"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + /// + /// The bit rate of the video in kbps (only for video). + /// + public long? BitRate + { + get + { + if (!this.Properties.TryGetValue("bitRate", out JsonElement element)) + return null; + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions); + } + set + { + this.Properties["bitRate"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + /// + /// Value of custom coordinates associated with the image in the format `x,y,width,height`. + /// If `customCoordinates` are not defined, then it is `null`. Send `customCoordinates` + /// in `responseFields` in API request to get the value of this field. + /// + public string? CustomCoordinates + { + get + { + if (!this.Properties.TryGetValue("customCoordinates", out JsonElement element)) + return null; + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions); + } + set + { + this.Properties["customCoordinates"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + /// + /// A key-value data associated with the asset. Use `responseField` in API request + /// to get `customMetadata` in the upload API response. Before setting any custom + /// metadata on an asset, you have to create the field using custom metadata + /// fields API. Send `customMetadata` in `responseFields` in API request to get + /// the value of this field. + /// + public Dictionary? CustomMetadata + { + get + { + if (!this.Properties.TryGetValue("customMetadata", out JsonElement element)) + return null; + + return JsonSerializer.Deserialize?>( + element, + ModelBase.SerializerOptions + ); + } + set + { + this.Properties["customMetadata"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + /// + /// Optional text to describe the contents of the file. Can be set by the user + /// or the ai-auto-description extension. + /// + public string? Description + { + get + { + if (!this.Properties.TryGetValue("description", out JsonElement element)) + return null; + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions); + } + set + { + this.Properties["description"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + /// + /// The duration of the video in seconds (only for video). + /// + public long? Duration + { + get + { + if (!this.Properties.TryGetValue("duration", out JsonElement element)) + return null; + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions); + } + set + { + this.Properties["duration"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + /// + /// Consolidated embedded metadata associated with the file. It includes exif, + /// iptc, and xmp data. Send `embeddedMetadata` in `responseFields` in API request + /// to get embeddedMetadata in the upload API response. + /// + public Dictionary? EmbeddedMetadata + { + get + { + if (!this.Properties.TryGetValue("embeddedMetadata", out JsonElement element)) + return null; + + return JsonSerializer.Deserialize?>( + element, + ModelBase.SerializerOptions + ); + } + set + { + this.Properties["embeddedMetadata"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + /// + /// Extension names with their processing status at the time of completion of + /// the request. It could have one of the following status values: + /// + /// `success`: The extension has been successfully applied. `failed`: The extension + /// has failed and will not be retried. `pending`: The extension will finish processing + /// in some time. On completion, the final status (success / failed) will be sent + /// to the `webhookUrl` provided. + /// + /// If no extension was requested, then this parameter is not returned. + /// + public ExtensionStatus? ExtensionStatus + { + get + { + if (!this.Properties.TryGetValue("extensionStatus", out JsonElement element)) + return null; + + return JsonSerializer.Deserialize( + element, + ModelBase.SerializerOptions + ); + } + set + { + this.Properties["extensionStatus"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + /// + /// Unique fileId. Store this fileld in your database, as this will be used to + /// perform update action on this file. + /// + public string? FileID + { + get + { + if (!this.Properties.TryGetValue("fileId", out JsonElement element)) + return null; + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions); + } + set + { + this.Properties["fileId"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + /// + /// The relative path of the file in the media library e.g. `/marketing-assets/new-banner.jpg`. + /// + public string? FilePath + { + get + { + if (!this.Properties.TryGetValue("filePath", out JsonElement element)) + return null; + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions); + } + set + { + this.Properties["filePath"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + /// + /// Type of the uploaded file. Possible values are `image`, `non-image`. + /// + public string? FileType + { + get + { + if (!this.Properties.TryGetValue("fileType", out JsonElement element)) + return null; + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions); + } + set + { + this.Properties["fileType"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + /// + /// Height of the image in pixels (Only for images) + /// + public double? Height + { + get + { + if (!this.Properties.TryGetValue("height", out JsonElement element)) + return null; + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions); + } + set + { + this.Properties["height"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + /// + /// Is the file marked as private. It can be either `true` or `false`. Send `isPrivateFile` + /// in `responseFields` in API request to get the value of this field. + /// + public bool? IsPrivateFile + { + get + { + if (!this.Properties.TryGetValue("isPrivateFile", out JsonElement element)) + return null; + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions); + } + set + { + this.Properties["isPrivateFile"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + /// + /// Is the file published or in draft state. It can be either `true` or `false`. + /// Send `isPublished` in `responseFields` in API request to get the value of + /// this field. + /// + public bool? IsPublished + { + get + { + if (!this.Properties.TryGetValue("isPublished", out JsonElement element)) + return null; + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions); + } + set + { + this.Properties["isPublished"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + /// + /// Legacy metadata. Send `metadata` in `responseFields` in API request to get + /// metadata in the upload API response. + /// + public Metadata? Metadata + { + get + { + if (!this.Properties.TryGetValue("metadata", out JsonElement element)) + return null; + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions); + } + set + { + this.Properties["metadata"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + /// + /// Name of the asset. + /// + public string? Name + { + get + { + if (!this.Properties.TryGetValue("name", out JsonElement element)) + return null; + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions); + } + set + { + this.Properties["name"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + /// + /// Size of the image file in Bytes. + /// + public double? Size + { + get + { + if (!this.Properties.TryGetValue("size", out JsonElement element)) + return null; + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions); + } + set + { + this.Properties["size"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + /// + /// The array of tags associated with the asset. If no tags are set, it will + /// be `null`. Send `tags` in `responseFields` in API request to get the value + /// of this field. + /// + public List? Tags + { + get + { + if (!this.Properties.TryGetValue("tags", out JsonElement element)) + return null; + + return JsonSerializer.Deserialize?>(element, ModelBase.SerializerOptions); + } + set + { + this.Properties["tags"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + /// + /// In the case of an image, a small thumbnail URL. + /// + public string? ThumbnailURL + { + get + { + if (!this.Properties.TryGetValue("thumbnailUrl", out JsonElement element)) + return null; + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions); + } + set + { + this.Properties["thumbnailUrl"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + /// + /// A publicly accessible URL of the file. + /// + public string? URL + { + get + { + if (!this.Properties.TryGetValue("url", out JsonElement element)) + return null; + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions); + } + set + { + this.Properties["url"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + /// + /// An object containing the file or file version's `id` (versionId) and `name`. + /// + public VersionInfo? VersionInfo + { + get + { + if (!this.Properties.TryGetValue("versionInfo", out JsonElement element)) + return null; + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions); + } + set + { + this.Properties["versionInfo"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + /// + /// The video codec used in the video (only for video). + /// + public string? VideoCodec + { + get + { + if (!this.Properties.TryGetValue("videoCodec", out JsonElement element)) + return null; + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions); + } + set + { + this.Properties["videoCodec"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + /// + /// Width of the image in pixels (Only for Images) + /// + public double? Width + { + get + { + if (!this.Properties.TryGetValue("width", out JsonElement element)) + return null; + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions); + } + set + { + this.Properties["width"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + public override void Validate() + { + foreach (var item in this.AITags ?? []) + { + item.Validate(); + } + _ = this.AudioCodec; + _ = this.BitRate; + _ = this.CustomCoordinates; + if (this.CustomMetadata != null) + { + foreach (var item in this.CustomMetadata.Values) + { + _ = item; + } + } + _ = this.Description; + _ = this.Duration; + if (this.EmbeddedMetadata != null) + { + foreach (var item in this.EmbeddedMetadata.Values) + { + _ = item; + } + } + this.ExtensionStatus?.Validate(); + _ = this.FileID; + _ = this.FilePath; + _ = this.FileType; + _ = this.Height; + _ = this.IsPrivateFile; + _ = this.IsPublished; + this.Metadata?.Validate(); + _ = this.Name; + _ = this.Size; + foreach (var item in this.Tags ?? []) + { + _ = item; + } + _ = this.ThumbnailURL; + _ = this.URL; + this.VersionInfo?.Validate(); + _ = this.VideoCodec; + _ = this.Width; + } + + public Data() { } + +#pragma warning disable CS8618 + [SetsRequiredMembers] + Data(Dictionary properties) + { + Properties = properties; + } +#pragma warning restore CS8618 + + public static Data FromRawUnchecked(Dictionary properties) + { + return new(properties); + } +} diff --git a/src/Imagekit/Models/Webhooks/UploadPreTransformSuccessEventProperties/DataProperties/AITag.cs b/src/Imagekit/Models/Webhooks/UploadPreTransformSuccessEventProperties/DataProperties/AITag.cs new file mode 100644 index 00000000..3c5ac201 --- /dev/null +++ b/src/Imagekit/Models/Webhooks/UploadPreTransformSuccessEventProperties/DataProperties/AITag.cs @@ -0,0 +1,96 @@ +using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; +using System.Text.Json; +using System.Text.Json.Serialization; + +namespace Imagekit.Models.Webhooks.UploadPreTransformSuccessEventProperties.DataProperties; + +[JsonConverter(typeof(ModelConverter))] +public sealed record class AITag : ModelBase, IFromRaw +{ + /// + /// Confidence score of the tag. + /// + public double? Confidence + { + get + { + if (!this.Properties.TryGetValue("confidence", out JsonElement element)) + return null; + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions); + } + set + { + this.Properties["confidence"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + /// + /// Name of the tag. + /// + public string? Name + { + get + { + if (!this.Properties.TryGetValue("name", out JsonElement element)) + return null; + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions); + } + set + { + this.Properties["name"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + /// + /// Array of `AITags` associated with the image. If no `AITags` are set, it will + /// be null. These tags can be added using the `google-auto-tagging` or `aws-auto-tagging` extensions. + /// + public string? Source + { + get + { + if (!this.Properties.TryGetValue("source", out JsonElement element)) + return null; + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions); + } + set + { + this.Properties["source"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + public override void Validate() + { + _ = this.Confidence; + _ = this.Name; + _ = this.Source; + } + + public AITag() { } + +#pragma warning disable CS8618 + [SetsRequiredMembers] + AITag(Dictionary properties) + { + Properties = properties; + } +#pragma warning restore CS8618 + + public static AITag FromRawUnchecked(Dictionary properties) + { + return new(properties); + } +} diff --git a/src/Imagekit/Models/Webhooks/UploadPreTransformSuccessEventProperties/DataProperties/ExtensionStatus.cs b/src/Imagekit/Models/Webhooks/UploadPreTransformSuccessEventProperties/DataProperties/ExtensionStatus.cs new file mode 100644 index 00000000..f144ed8f --- /dev/null +++ b/src/Imagekit/Models/Webhooks/UploadPreTransformSuccessEventProperties/DataProperties/ExtensionStatus.cs @@ -0,0 +1,129 @@ +using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; +using System.Text.Json; +using System.Text.Json.Serialization; +using Imagekit.Models.Webhooks.UploadPreTransformSuccessEventProperties.DataProperties.ExtensionStatusProperties; + +namespace Imagekit.Models.Webhooks.UploadPreTransformSuccessEventProperties.DataProperties; + +/// +/// Extension names with their processing status at the time of completion of the +/// request. It could have one of the following status values: +/// +/// `success`: The extension has been successfully applied. `failed`: The extension +/// has failed and will not be retried. `pending`: The extension will finish processing +/// in some time. On completion, the final status (success / failed) will be sent +/// to the `webhookUrl` provided. +/// +/// If no extension was requested, then this parameter is not returned. +/// +[JsonConverter(typeof(ModelConverter))] +public sealed record class ExtensionStatus : ModelBase, IFromRaw +{ + public ApiEnum? AIAutoDescription + { + get + { + if (!this.Properties.TryGetValue("ai-auto-description", out JsonElement element)) + return null; + + return JsonSerializer.Deserialize?>( + element, + ModelBase.SerializerOptions + ); + } + set + { + this.Properties["ai-auto-description"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + public ApiEnum? AwsAutoTagging + { + get + { + if (!this.Properties.TryGetValue("aws-auto-tagging", out JsonElement element)) + return null; + + return JsonSerializer.Deserialize?>( + element, + ModelBase.SerializerOptions + ); + } + set + { + this.Properties["aws-auto-tagging"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + public ApiEnum? GoogleAutoTagging + { + get + { + if (!this.Properties.TryGetValue("google-auto-tagging", out JsonElement element)) + return null; + + return JsonSerializer.Deserialize?>( + element, + ModelBase.SerializerOptions + ); + } + set + { + this.Properties["google-auto-tagging"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + public ApiEnum? RemoveBg + { + get + { + if (!this.Properties.TryGetValue("remove-bg", out JsonElement element)) + return null; + + return JsonSerializer.Deserialize?>( + element, + ModelBase.SerializerOptions + ); + } + set + { + this.Properties["remove-bg"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + public override void Validate() + { + this.AIAutoDescription?.Validate(); + this.AwsAutoTagging?.Validate(); + this.GoogleAutoTagging?.Validate(); + this.RemoveBg?.Validate(); + } + + public ExtensionStatus() { } + +#pragma warning disable CS8618 + [SetsRequiredMembers] + ExtensionStatus(Dictionary properties) + { + Properties = properties; + } +#pragma warning restore CS8618 + + public static ExtensionStatus FromRawUnchecked(Dictionary properties) + { + return new(properties); + } +} diff --git a/src/Imagekit/Models/Webhooks/UploadPreTransformSuccessEventProperties/DataProperties/ExtensionStatusProperties/AIAutoDescription.cs b/src/Imagekit/Models/Webhooks/UploadPreTransformSuccessEventProperties/DataProperties/ExtensionStatusProperties/AIAutoDescription.cs new file mode 100644 index 00000000..9ea84518 --- /dev/null +++ b/src/Imagekit/Models/Webhooks/UploadPreTransformSuccessEventProperties/DataProperties/ExtensionStatusProperties/AIAutoDescription.cs @@ -0,0 +1,50 @@ +using System; +using System.Text.Json; +using System.Text.Json.Serialization; + +namespace Imagekit.Models.Webhooks.UploadPreTransformSuccessEventProperties.DataProperties.ExtensionStatusProperties; + +[JsonConverter(typeof(AIAutoDescriptionConverter))] +public enum AIAutoDescription +{ + Success, + Pending, + Failed, +} + +sealed class AIAutoDescriptionConverter : JsonConverter +{ + public override AIAutoDescription Read( + ref Utf8JsonReader reader, + Type typeToConvert, + JsonSerializerOptions options + ) + { + return JsonSerializer.Deserialize(ref reader, options) switch + { + "success" => AIAutoDescription.Success, + "pending" => AIAutoDescription.Pending, + "failed" => AIAutoDescription.Failed, + _ => (AIAutoDescription)(-1), + }; + } + + public override void Write( + Utf8JsonWriter writer, + AIAutoDescription value, + JsonSerializerOptions options + ) + { + JsonSerializer.Serialize( + writer, + value switch + { + AIAutoDescription.Success => "success", + AIAutoDescription.Pending => "pending", + AIAutoDescription.Failed => "failed", + _ => throw new ArgumentOutOfRangeException(nameof(value)), + }, + options + ); + } +} diff --git a/src/Imagekit/Models/Webhooks/UploadPreTransformSuccessEventProperties/DataProperties/ExtensionStatusProperties/AwsAutoTagging.cs b/src/Imagekit/Models/Webhooks/UploadPreTransformSuccessEventProperties/DataProperties/ExtensionStatusProperties/AwsAutoTagging.cs new file mode 100644 index 00000000..829c2741 --- /dev/null +++ b/src/Imagekit/Models/Webhooks/UploadPreTransformSuccessEventProperties/DataProperties/ExtensionStatusProperties/AwsAutoTagging.cs @@ -0,0 +1,50 @@ +using System; +using System.Text.Json; +using System.Text.Json.Serialization; + +namespace Imagekit.Models.Webhooks.UploadPreTransformSuccessEventProperties.DataProperties.ExtensionStatusProperties; + +[JsonConverter(typeof(AwsAutoTaggingConverter))] +public enum AwsAutoTagging +{ + Success, + Pending, + Failed, +} + +sealed class AwsAutoTaggingConverter : JsonConverter +{ + public override AwsAutoTagging Read( + ref Utf8JsonReader reader, + Type typeToConvert, + JsonSerializerOptions options + ) + { + return JsonSerializer.Deserialize(ref reader, options) switch + { + "success" => AwsAutoTagging.Success, + "pending" => AwsAutoTagging.Pending, + "failed" => AwsAutoTagging.Failed, + _ => (AwsAutoTagging)(-1), + }; + } + + public override void Write( + Utf8JsonWriter writer, + AwsAutoTagging value, + JsonSerializerOptions options + ) + { + JsonSerializer.Serialize( + writer, + value switch + { + AwsAutoTagging.Success => "success", + AwsAutoTagging.Pending => "pending", + AwsAutoTagging.Failed => "failed", + _ => throw new ArgumentOutOfRangeException(nameof(value)), + }, + options + ); + } +} diff --git a/src/Imagekit/Models/Webhooks/UploadPreTransformSuccessEventProperties/DataProperties/ExtensionStatusProperties/GoogleAutoTagging.cs b/src/Imagekit/Models/Webhooks/UploadPreTransformSuccessEventProperties/DataProperties/ExtensionStatusProperties/GoogleAutoTagging.cs new file mode 100644 index 00000000..ef9ecd16 --- /dev/null +++ b/src/Imagekit/Models/Webhooks/UploadPreTransformSuccessEventProperties/DataProperties/ExtensionStatusProperties/GoogleAutoTagging.cs @@ -0,0 +1,50 @@ +using System; +using System.Text.Json; +using System.Text.Json.Serialization; + +namespace Imagekit.Models.Webhooks.UploadPreTransformSuccessEventProperties.DataProperties.ExtensionStatusProperties; + +[JsonConverter(typeof(GoogleAutoTaggingConverter))] +public enum GoogleAutoTagging +{ + Success, + Pending, + Failed, +} + +sealed class GoogleAutoTaggingConverter : JsonConverter +{ + public override GoogleAutoTagging Read( + ref Utf8JsonReader reader, + Type typeToConvert, + JsonSerializerOptions options + ) + { + return JsonSerializer.Deserialize(ref reader, options) switch + { + "success" => GoogleAutoTagging.Success, + "pending" => GoogleAutoTagging.Pending, + "failed" => GoogleAutoTagging.Failed, + _ => (GoogleAutoTagging)(-1), + }; + } + + public override void Write( + Utf8JsonWriter writer, + GoogleAutoTagging value, + JsonSerializerOptions options + ) + { + JsonSerializer.Serialize( + writer, + value switch + { + GoogleAutoTagging.Success => "success", + GoogleAutoTagging.Pending => "pending", + GoogleAutoTagging.Failed => "failed", + _ => throw new ArgumentOutOfRangeException(nameof(value)), + }, + options + ); + } +} diff --git a/src/Imagekit/Models/Webhooks/UploadPreTransformSuccessEventProperties/DataProperties/ExtensionStatusProperties/RemoveBg.cs b/src/Imagekit/Models/Webhooks/UploadPreTransformSuccessEventProperties/DataProperties/ExtensionStatusProperties/RemoveBg.cs new file mode 100644 index 00000000..98156421 --- /dev/null +++ b/src/Imagekit/Models/Webhooks/UploadPreTransformSuccessEventProperties/DataProperties/ExtensionStatusProperties/RemoveBg.cs @@ -0,0 +1,46 @@ +using System; +using System.Text.Json; +using System.Text.Json.Serialization; + +namespace Imagekit.Models.Webhooks.UploadPreTransformSuccessEventProperties.DataProperties.ExtensionStatusProperties; + +[JsonConverter(typeof(RemoveBgConverter))] +public enum RemoveBg +{ + Success, + Pending, + Failed, +} + +sealed class RemoveBgConverter : JsonConverter +{ + public override RemoveBg Read( + ref Utf8JsonReader reader, + Type typeToConvert, + JsonSerializerOptions options + ) + { + return JsonSerializer.Deserialize(ref reader, options) switch + { + "success" => RemoveBg.Success, + "pending" => RemoveBg.Pending, + "failed" => RemoveBg.Failed, + _ => (RemoveBg)(-1), + }; + } + + public override void Write(Utf8JsonWriter writer, RemoveBg value, JsonSerializerOptions options) + { + JsonSerializer.Serialize( + writer, + value switch + { + RemoveBg.Success => "success", + RemoveBg.Pending => "pending", + RemoveBg.Failed => "failed", + _ => throw new ArgumentOutOfRangeException(nameof(value)), + }, + options + ); + } +} diff --git a/src/Imagekit/Models/Webhooks/UploadPreTransformSuccessEventProperties/DataProperties/VersionInfo.cs b/src/Imagekit/Models/Webhooks/UploadPreTransformSuccessEventProperties/DataProperties/VersionInfo.cs new file mode 100644 index 00000000..ebc97415 --- /dev/null +++ b/src/Imagekit/Models/Webhooks/UploadPreTransformSuccessEventProperties/DataProperties/VersionInfo.cs @@ -0,0 +1,76 @@ +using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; +using System.Text.Json; +using System.Text.Json.Serialization; + +namespace Imagekit.Models.Webhooks.UploadPreTransformSuccessEventProperties.DataProperties; + +/// +/// An object containing the file or file version's `id` (versionId) and `name`. +/// +[JsonConverter(typeof(ModelConverter))] +public sealed record class VersionInfo : ModelBase, IFromRaw +{ + /// + /// Unique identifier of the file version. + /// + public string? ID + { + get + { + if (!this.Properties.TryGetValue("id", out JsonElement element)) + return null; + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions); + } + set + { + this.Properties["id"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + /// + /// Name of the file version. + /// + public string? Name + { + get + { + if (!this.Properties.TryGetValue("name", out JsonElement element)) + return null; + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions); + } + set + { + this.Properties["name"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + public override void Validate() + { + _ = this.ID; + _ = this.Name; + } + + public VersionInfo() { } + +#pragma warning disable CS8618 + [SetsRequiredMembers] + VersionInfo(Dictionary properties) + { + Properties = properties; + } +#pragma warning restore CS8618 + + public static VersionInfo FromRawUnchecked(Dictionary properties) + { + return new(properties); + } +} diff --git a/src/Imagekit/Models/Webhooks/UploadPreTransformSuccessEventProperties/Request.cs b/src/Imagekit/Models/Webhooks/UploadPreTransformSuccessEventProperties/Request.cs new file mode 100644 index 00000000..848061a5 --- /dev/null +++ b/src/Imagekit/Models/Webhooks/UploadPreTransformSuccessEventProperties/Request.cs @@ -0,0 +1,79 @@ +using System; +using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; +using System.Text.Json; +using System.Text.Json.Serialization; + +namespace Imagekit.Models.Webhooks.UploadPreTransformSuccessEventProperties; + +[JsonConverter(typeof(ModelConverter))] +public sealed record class Request : ModelBase, IFromRaw +{ + /// + /// The requested pre-transformation string. + /// + public required string Transformation + { + get + { + if (!this.Properties.TryGetValue("transformation", out JsonElement element)) + throw new ArgumentOutOfRangeException( + "transformation", + "Missing required argument" + ); + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions) + ?? throw new ArgumentNullException("transformation"); + } + set + { + this.Properties["transformation"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + /// + /// Unique identifier for the originating request. + /// + public required string XRequestID + { + get + { + if (!this.Properties.TryGetValue("x_request_id", out JsonElement element)) + throw new ArgumentOutOfRangeException("x_request_id", "Missing required argument"); + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions) + ?? throw new ArgumentNullException("x_request_id"); + } + set + { + this.Properties["x_request_id"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + public override void Validate() + { + _ = this.Transformation; + _ = this.XRequestID; + } + + public Request() { } + +#pragma warning disable CS8618 + [SetsRequiredMembers] + Request(Dictionary properties) + { + Properties = properties; + } +#pragma warning restore CS8618 + + public static Request FromRawUnchecked(Dictionary properties) + { + return new(properties); + } +} diff --git a/src/Imagekit/Models/Webhooks/VideoTransformationAcceptedEvent.cs b/src/Imagekit/Models/Webhooks/VideoTransformationAcceptedEvent.cs new file mode 100644 index 00000000..e3dc0196 --- /dev/null +++ b/src/Imagekit/Models/Webhooks/VideoTransformationAcceptedEvent.cs @@ -0,0 +1,149 @@ +using System; +using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; +using System.Text.Json; +using System.Text.Json.Serialization; +using Imagekit.Models.Webhooks.VideoTransformationAcceptedEventProperties; + +namespace Imagekit.Models.Webhooks; + +/// +/// Triggered when a new video transformation request is accepted for processing. +/// This event confirms that ImageKit has received and queued your transformation +/// request. Use this for debugging and tracking transformation lifecycle. +/// +[JsonConverter(typeof(ModelConverter))] +public sealed record class VideoTransformationAcceptedEvent + : ModelBase, + IFromRaw +{ + /// + /// Unique identifier for the event. + /// + public required string ID + { + get + { + if (!this.Properties.TryGetValue("id", out JsonElement element)) + throw new ArgumentOutOfRangeException("id", "Missing required argument"); + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions) + ?? throw new ArgumentNullException("id"); + } + set + { + this.Properties["id"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + /// + /// Timestamp when the event was created in ISO8601 format. + /// + public required DateTime CreatedAt + { + get + { + if (!this.Properties.TryGetValue("created_at", out JsonElement element)) + throw new ArgumentOutOfRangeException("created_at", "Missing required argument"); + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions); + } + set + { + this.Properties["created_at"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + public required Data Data + { + get + { + if (!this.Properties.TryGetValue("data", out JsonElement element)) + throw new ArgumentOutOfRangeException("data", "Missing required argument"); + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions) + ?? throw new ArgumentNullException("data"); + } + set + { + this.Properties["data"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + /// + /// Information about the original request that triggered the video transformation. + /// + public required Request Request + { + get + { + if (!this.Properties.TryGetValue("request", out JsonElement element)) + throw new ArgumentOutOfRangeException("request", "Missing required argument"); + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions) + ?? throw new ArgumentNullException("request"); + } + set + { + this.Properties["request"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + public JsonElement Type + { + get + { + if (!this.Properties.TryGetValue("type", out JsonElement element)) + throw new ArgumentOutOfRangeException("type", "Missing required argument"); + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions); + } + set + { + this.Properties["type"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + public override void Validate() + { + _ = this.ID; + _ = this.CreatedAt; + this.Data.Validate(); + this.Request.Validate(); + } + + public VideoTransformationAcceptedEvent() + { + this.Type = JsonSerializer.Deserialize("\"video.transformation.accepted\""); + } + +#pragma warning disable CS8618 + [SetsRequiredMembers] + VideoTransformationAcceptedEvent(Dictionary properties) + { + Properties = properties; + } +#pragma warning restore CS8618 + + public static VideoTransformationAcceptedEvent FromRawUnchecked( + Dictionary properties + ) + { + return new(properties); + } +} diff --git a/src/Imagekit/Models/Webhooks/VideoTransformationAcceptedEventProperties/Data.cs b/src/Imagekit/Models/Webhooks/VideoTransformationAcceptedEventProperties/Data.cs new file mode 100644 index 00000000..d28eb91a --- /dev/null +++ b/src/Imagekit/Models/Webhooks/VideoTransformationAcceptedEventProperties/Data.cs @@ -0,0 +1,84 @@ +using System; +using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; +using System.Text.Json; +using System.Text.Json.Serialization; +using DataProperties = Imagekit.Models.Webhooks.VideoTransformationAcceptedEventProperties.DataProperties; + +namespace Imagekit.Models.Webhooks.VideoTransformationAcceptedEventProperties; + +[JsonConverter(typeof(ModelConverter))] +public sealed record class Data : ModelBase, IFromRaw +{ + /// + /// Information about the source video asset being transformed. + /// + public required DataProperties::Asset Asset + { + get + { + if (!this.Properties.TryGetValue("asset", out JsonElement element)) + throw new ArgumentOutOfRangeException("asset", "Missing required argument"); + + return JsonSerializer.Deserialize( + element, + ModelBase.SerializerOptions + ) ?? throw new ArgumentNullException("asset"); + } + set + { + this.Properties["asset"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + /// + /// Base information about a video transformation request. + /// + public required DataProperties::Transformation Transformation + { + get + { + if (!this.Properties.TryGetValue("transformation", out JsonElement element)) + throw new ArgumentOutOfRangeException( + "transformation", + "Missing required argument" + ); + + return JsonSerializer.Deserialize( + element, + ModelBase.SerializerOptions + ) ?? throw new ArgumentNullException("transformation"); + } + set + { + this.Properties["transformation"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + public override void Validate() + { + this.Asset.Validate(); + this.Transformation.Validate(); + } + + public Data() { } + +#pragma warning disable CS8618 + [SetsRequiredMembers] + Data(Dictionary properties) + { + Properties = properties; + } +#pragma warning restore CS8618 + + public static Data FromRawUnchecked(Dictionary properties) + { + return new(properties); + } +} diff --git a/src/Imagekit/Models/Webhooks/VideoTransformationAcceptedEventProperties/DataProperties/Asset.cs b/src/Imagekit/Models/Webhooks/VideoTransformationAcceptedEventProperties/DataProperties/Asset.cs new file mode 100644 index 00000000..f54723b5 --- /dev/null +++ b/src/Imagekit/Models/Webhooks/VideoTransformationAcceptedEventProperties/DataProperties/Asset.cs @@ -0,0 +1,63 @@ +using System; +using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; +using System.Text.Json; +using System.Text.Json.Serialization; + +namespace Imagekit.Models.Webhooks.VideoTransformationAcceptedEventProperties.DataProperties; + +/// +/// Information about the source video asset being transformed. +/// +[JsonConverter(typeof(ModelConverter))] +public sealed record class Asset : ModelBase, IFromRaw +{ + /// + /// URL to download or access the source video file. + /// + public required string URL + { + get + { + if (!this.Properties.TryGetValue("url", out JsonElement element)) + throw new ArgumentOutOfRangeException("url", "Missing required argument"); + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions) + ?? throw new ArgumentNullException("url"); + } + set + { + this.Properties["url"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + public override void Validate() + { + _ = this.URL; + } + + public Asset() { } + +#pragma warning disable CS8618 + [SetsRequiredMembers] + Asset(Dictionary properties) + { + Properties = properties; + } +#pragma warning restore CS8618 + + public static Asset FromRawUnchecked(Dictionary properties) + { + return new(properties); + } + + [SetsRequiredMembers] + public Asset(string url) + : this() + { + this.URL = url; + } +} diff --git a/src/Imagekit/Models/Webhooks/VideoTransformationAcceptedEventProperties/DataProperties/Transformation.cs b/src/Imagekit/Models/Webhooks/VideoTransformationAcceptedEventProperties/DataProperties/Transformation.cs new file mode 100644 index 00000000..24e72bab --- /dev/null +++ b/src/Imagekit/Models/Webhooks/VideoTransformationAcceptedEventProperties/DataProperties/Transformation.cs @@ -0,0 +1,93 @@ +using System; +using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; +using System.Text.Json; +using System.Text.Json.Serialization; +using TransformationProperties = Imagekit.Models.Webhooks.VideoTransformationAcceptedEventProperties.DataProperties.TransformationProperties; + +namespace Imagekit.Models.Webhooks.VideoTransformationAcceptedEventProperties.DataProperties; + +/// +/// Base information about a video transformation request. +/// +[JsonConverter(typeof(ModelConverter))] +public sealed record class Transformation : ModelBase, IFromRaw +{ + /// + /// Type of video transformation: - `video-transformation`: Standard video processing + /// (resize, format conversion, etc.) - `gif-to-video`: Convert animated GIF to + /// video format - `video-thumbnail`: Generate thumbnail image from video + /// + public required ApiEnum Type + { + get + { + if (!this.Properties.TryGetValue("type", out JsonElement element)) + throw new ArgumentOutOfRangeException("type", "Missing required argument"); + + return JsonSerializer.Deserialize>( + element, + ModelBase.SerializerOptions + ); + } + set + { + this.Properties["type"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + /// + /// Configuration options for video transformations. + /// + public TransformationProperties::Options? Options + { + get + { + if (!this.Properties.TryGetValue("options", out JsonElement element)) + return null; + + return JsonSerializer.Deserialize( + element, + ModelBase.SerializerOptions + ); + } + set + { + this.Properties["options"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + public override void Validate() + { + this.Type.Validate(); + this.Options?.Validate(); + } + + public Transformation() { } + +#pragma warning disable CS8618 + [SetsRequiredMembers] + Transformation(Dictionary properties) + { + Properties = properties; + } +#pragma warning restore CS8618 + + public static Transformation FromRawUnchecked(Dictionary properties) + { + return new(properties); + } + + [SetsRequiredMembers] + public Transformation(ApiEnum type) + : this() + { + this.Type = type; + } +} diff --git a/src/Imagekit/Models/Webhooks/VideoTransformationAcceptedEventProperties/DataProperties/TransformationProperties/Options.cs b/src/Imagekit/Models/Webhooks/VideoTransformationAcceptedEventProperties/DataProperties/TransformationProperties/Options.cs new file mode 100644 index 00000000..e841bd7a --- /dev/null +++ b/src/Imagekit/Models/Webhooks/VideoTransformationAcceptedEventProperties/DataProperties/TransformationProperties/Options.cs @@ -0,0 +1,202 @@ +using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; +using System.Text.Json; +using System.Text.Json.Serialization; +using Imagekit.Models.Webhooks.VideoTransformationAcceptedEventProperties.DataProperties.TransformationProperties.OptionsProperties; + +namespace Imagekit.Models.Webhooks.VideoTransformationAcceptedEventProperties.DataProperties.TransformationProperties; + +/// +/// Configuration options for video transformations. +/// +[JsonConverter(typeof(ModelConverter))] +public sealed record class Options : ModelBase, IFromRaw +{ + /// + /// Audio codec used for encoding (aac or opus). + /// + public ApiEnum? AudioCodec + { + get + { + if (!this.Properties.TryGetValue("audio_codec", out JsonElement element)) + return null; + + return JsonSerializer.Deserialize?>( + element, + ModelBase.SerializerOptions + ); + } + set + { + this.Properties["audio_codec"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + /// + /// Whether to automatically rotate the video based on metadata. + /// + public bool? AutoRotate + { + get + { + if (!this.Properties.TryGetValue("auto_rotate", out JsonElement element)) + return null; + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions); + } + set + { + this.Properties["auto_rotate"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + /// + /// Output format for the transformed video or thumbnail. + /// + public ApiEnum? Format + { + get + { + if (!this.Properties.TryGetValue("format", out JsonElement element)) + return null; + + return JsonSerializer.Deserialize?>( + element, + ModelBase.SerializerOptions + ); + } + set + { + this.Properties["format"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + /// + /// Quality setting for the output video. + /// + public long? Quality + { + get + { + if (!this.Properties.TryGetValue("quality", out JsonElement element)) + return null; + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions); + } + set + { + this.Properties["quality"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + /// + /// Streaming protocol for adaptive bitrate streaming. + /// + public ApiEnum? StreamProtocol + { + get + { + if (!this.Properties.TryGetValue("stream_protocol", out JsonElement element)) + return null; + + return JsonSerializer.Deserialize?>( + element, + ModelBase.SerializerOptions + ); + } + set + { + this.Properties["stream_protocol"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + /// + /// Array of quality representations for adaptive bitrate streaming. + /// + public List? Variants + { + get + { + if (!this.Properties.TryGetValue("variants", out JsonElement element)) + return null; + + return JsonSerializer.Deserialize?>(element, ModelBase.SerializerOptions); + } + set + { + this.Properties["variants"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + /// + /// Video codec used for encoding (h264, vp9, or av1). + /// + public ApiEnum? VideoCodec + { + get + { + if (!this.Properties.TryGetValue("video_codec", out JsonElement element)) + return null; + + return JsonSerializer.Deserialize?>( + element, + ModelBase.SerializerOptions + ); + } + set + { + this.Properties["video_codec"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + public override void Validate() + { + this.AudioCodec?.Validate(); + _ = this.AutoRotate; + this.Format?.Validate(); + _ = this.Quality; + this.StreamProtocol?.Validate(); + foreach (var item in this.Variants ?? []) + { + _ = item; + } + this.VideoCodec?.Validate(); + } + + public Options() { } + +#pragma warning disable CS8618 + [SetsRequiredMembers] + Options(Dictionary properties) + { + Properties = properties; + } +#pragma warning restore CS8618 + + public static Options FromRawUnchecked(Dictionary properties) + { + return new(properties); + } +} diff --git a/src/Imagekit/Models/Webhooks/VideoTransformationAcceptedEventProperties/DataProperties/TransformationProperties/OptionsProperties/AudioCodec.cs b/src/Imagekit/Models/Webhooks/VideoTransformationAcceptedEventProperties/DataProperties/TransformationProperties/OptionsProperties/AudioCodec.cs new file mode 100644 index 00000000..c448b18b --- /dev/null +++ b/src/Imagekit/Models/Webhooks/VideoTransformationAcceptedEventProperties/DataProperties/TransformationProperties/OptionsProperties/AudioCodec.cs @@ -0,0 +1,50 @@ +using System.Text.Json; +using System.Text.Json.Serialization; +using System = System; + +namespace Imagekit.Models.Webhooks.VideoTransformationAcceptedEventProperties.DataProperties.TransformationProperties.OptionsProperties; + +/// +/// Audio codec used for encoding (aac or opus). +/// +[JsonConverter(typeof(AudioCodecConverter))] +public enum AudioCodec +{ + Aac, + Opus, +} + +sealed class AudioCodecConverter : JsonConverter +{ + public override AudioCodec Read( + ref Utf8JsonReader reader, + System::Type typeToConvert, + JsonSerializerOptions options + ) + { + return JsonSerializer.Deserialize(ref reader, options) switch + { + "aac" => AudioCodec.Aac, + "opus" => AudioCodec.Opus, + _ => (AudioCodec)(-1), + }; + } + + public override void Write( + Utf8JsonWriter writer, + AudioCodec value, + JsonSerializerOptions options + ) + { + JsonSerializer.Serialize( + writer, + value switch + { + AudioCodec.Aac => "aac", + AudioCodec.Opus => "opus", + _ => throw new System::ArgumentOutOfRangeException(nameof(value)), + }, + options + ); + } +} diff --git a/src/Imagekit/Models/Webhooks/VideoTransformationAcceptedEventProperties/DataProperties/TransformationProperties/OptionsProperties/Format.cs b/src/Imagekit/Models/Webhooks/VideoTransformationAcceptedEventProperties/DataProperties/TransformationProperties/OptionsProperties/Format.cs new file mode 100644 index 00000000..48a62714 --- /dev/null +++ b/src/Imagekit/Models/Webhooks/VideoTransformationAcceptedEventProperties/DataProperties/TransformationProperties/OptionsProperties/Format.cs @@ -0,0 +1,55 @@ +using System.Text.Json; +using System.Text.Json.Serialization; +using System = System; + +namespace Imagekit.Models.Webhooks.VideoTransformationAcceptedEventProperties.DataProperties.TransformationProperties.OptionsProperties; + +/// +/// Output format for the transformed video or thumbnail. +/// +[JsonConverter(typeof(FormatConverter))] +public enum Format +{ + MP4, + Webm, + Jpg, + Png, + Webp, +} + +sealed class FormatConverter : JsonConverter +{ + public override Format Read( + ref Utf8JsonReader reader, + System::Type typeToConvert, + JsonSerializerOptions options + ) + { + return JsonSerializer.Deserialize(ref reader, options) switch + { + "mp4" => Format.MP4, + "webm" => Format.Webm, + "jpg" => Format.Jpg, + "png" => Format.Png, + "webp" => Format.Webp, + _ => (Format)(-1), + }; + } + + public override void Write(Utf8JsonWriter writer, Format value, JsonSerializerOptions options) + { + JsonSerializer.Serialize( + writer, + value switch + { + Format.MP4 => "mp4", + Format.Webm => "webm", + Format.Jpg => "jpg", + Format.Png => "png", + Format.Webp => "webp", + _ => throw new System::ArgumentOutOfRangeException(nameof(value)), + }, + options + ); + } +} diff --git a/src/Imagekit/Models/Webhooks/VideoTransformationAcceptedEventProperties/DataProperties/TransformationProperties/OptionsProperties/StreamProtocol.cs b/src/Imagekit/Models/Webhooks/VideoTransformationAcceptedEventProperties/DataProperties/TransformationProperties/OptionsProperties/StreamProtocol.cs new file mode 100644 index 00000000..cee1bc53 --- /dev/null +++ b/src/Imagekit/Models/Webhooks/VideoTransformationAcceptedEventProperties/DataProperties/TransformationProperties/OptionsProperties/StreamProtocol.cs @@ -0,0 +1,50 @@ +using System.Text.Json; +using System.Text.Json.Serialization; +using System = System; + +namespace Imagekit.Models.Webhooks.VideoTransformationAcceptedEventProperties.DataProperties.TransformationProperties.OptionsProperties; + +/// +/// Streaming protocol for adaptive bitrate streaming. +/// +[JsonConverter(typeof(StreamProtocolConverter))] +public enum StreamProtocol +{ + Hls, + Dash, +} + +sealed class StreamProtocolConverter : JsonConverter +{ + public override StreamProtocol Read( + ref Utf8JsonReader reader, + System::Type typeToConvert, + JsonSerializerOptions options + ) + { + return JsonSerializer.Deserialize(ref reader, options) switch + { + "HLS" => StreamProtocol.Hls, + "DASH" => StreamProtocol.Dash, + _ => (StreamProtocol)(-1), + }; + } + + public override void Write( + Utf8JsonWriter writer, + StreamProtocol value, + JsonSerializerOptions options + ) + { + JsonSerializer.Serialize( + writer, + value switch + { + StreamProtocol.Hls => "HLS", + StreamProtocol.Dash => "DASH", + _ => throw new System::ArgumentOutOfRangeException(nameof(value)), + }, + options + ); + } +} diff --git a/src/Imagekit/Models/Webhooks/VideoTransformationAcceptedEventProperties/DataProperties/TransformationProperties/OptionsProperties/VideoCodec.cs b/src/Imagekit/Models/Webhooks/VideoTransformationAcceptedEventProperties/DataProperties/TransformationProperties/OptionsProperties/VideoCodec.cs new file mode 100644 index 00000000..1016e491 --- /dev/null +++ b/src/Imagekit/Models/Webhooks/VideoTransformationAcceptedEventProperties/DataProperties/TransformationProperties/OptionsProperties/VideoCodec.cs @@ -0,0 +1,53 @@ +using System.Text.Json; +using System.Text.Json.Serialization; +using System = System; + +namespace Imagekit.Models.Webhooks.VideoTransformationAcceptedEventProperties.DataProperties.TransformationProperties.OptionsProperties; + +/// +/// Video codec used for encoding (h264, vp9, or av1). +/// +[JsonConverter(typeof(VideoCodecConverter))] +public enum VideoCodec +{ + H264, + Vp9, + Av1, +} + +sealed class VideoCodecConverter : JsonConverter +{ + public override VideoCodec Read( + ref Utf8JsonReader reader, + System::Type typeToConvert, + JsonSerializerOptions options + ) + { + return JsonSerializer.Deserialize(ref reader, options) switch + { + "h264" => VideoCodec.H264, + "vp9" => VideoCodec.Vp9, + "av1" => VideoCodec.Av1, + _ => (VideoCodec)(-1), + }; + } + + public override void Write( + Utf8JsonWriter writer, + VideoCodec value, + JsonSerializerOptions options + ) + { + JsonSerializer.Serialize( + writer, + value switch + { + VideoCodec.H264 => "h264", + VideoCodec.Vp9 => "vp9", + VideoCodec.Av1 => "av1", + _ => throw new System::ArgumentOutOfRangeException(nameof(value)), + }, + options + ); + } +} diff --git a/src/Imagekit/Models/Webhooks/VideoTransformationAcceptedEventProperties/DataProperties/TransformationProperties/Type.cs b/src/Imagekit/Models/Webhooks/VideoTransformationAcceptedEventProperties/DataProperties/TransformationProperties/Type.cs new file mode 100644 index 00000000..90f9cee2 --- /dev/null +++ b/src/Imagekit/Models/Webhooks/VideoTransformationAcceptedEventProperties/DataProperties/TransformationProperties/Type.cs @@ -0,0 +1,51 @@ +using System.Text.Json; +using System.Text.Json.Serialization; +using System = System; + +namespace Imagekit.Models.Webhooks.VideoTransformationAcceptedEventProperties.DataProperties.TransformationProperties; + +/// +/// Type of video transformation: - `video-transformation`: Standard video processing +/// (resize, format conversion, etc.) - `gif-to-video`: Convert animated GIF to video +/// format - `video-thumbnail`: Generate thumbnail image from video +/// +[JsonConverter(typeof(TypeConverter))] +public enum Type +{ + VideoTransformation, + GifToVideo, + VideoThumbnail, +} + +sealed class TypeConverter : JsonConverter +{ + public override Type Read( + ref Utf8JsonReader reader, + System::Type typeToConvert, + JsonSerializerOptions options + ) + { + return JsonSerializer.Deserialize(ref reader, options) switch + { + "video-transformation" => TransformationProperties.Type.VideoTransformation, + "gif-to-video" => TransformationProperties.Type.GifToVideo, + "video-thumbnail" => TransformationProperties.Type.VideoThumbnail, + _ => (Type)(-1), + }; + } + + public override void Write(Utf8JsonWriter writer, Type value, JsonSerializerOptions options) + { + JsonSerializer.Serialize( + writer, + value switch + { + TransformationProperties.Type.VideoTransformation => "video-transformation", + TransformationProperties.Type.GifToVideo => "gif-to-video", + TransformationProperties.Type.VideoThumbnail => "video-thumbnail", + _ => throw new System::ArgumentOutOfRangeException(nameof(value)), + }, + options + ); + } +} diff --git a/src/Imagekit/Models/Webhooks/VideoTransformationAcceptedEventProperties/Request.cs b/src/Imagekit/Models/Webhooks/VideoTransformationAcceptedEventProperties/Request.cs new file mode 100644 index 00000000..28c0f652 --- /dev/null +++ b/src/Imagekit/Models/Webhooks/VideoTransformationAcceptedEventProperties/Request.cs @@ -0,0 +1,101 @@ +using System; +using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; +using System.Text.Json; +using System.Text.Json.Serialization; + +namespace Imagekit.Models.Webhooks.VideoTransformationAcceptedEventProperties; + +/// +/// Information about the original request that triggered the video transformation. +/// +[JsonConverter(typeof(ModelConverter))] +public sealed record class Request : ModelBase, IFromRaw +{ + /// + /// Full URL of the transformation request that was submitted. + /// + public required string URL + { + get + { + if (!this.Properties.TryGetValue("url", out JsonElement element)) + throw new ArgumentOutOfRangeException("url", "Missing required argument"); + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions) + ?? throw new ArgumentNullException("url"); + } + set + { + this.Properties["url"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + /// + /// Unique identifier for the originating transformation request. + /// + public required string XRequestID + { + get + { + if (!this.Properties.TryGetValue("x_request_id", out JsonElement element)) + throw new ArgumentOutOfRangeException("x_request_id", "Missing required argument"); + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions) + ?? throw new ArgumentNullException("x_request_id"); + } + set + { + this.Properties["x_request_id"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + /// + /// User-Agent header from the original request that triggered the transformation. + /// + public string? UserAgent + { + get + { + if (!this.Properties.TryGetValue("user_agent", out JsonElement element)) + return null; + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions); + } + set + { + this.Properties["user_agent"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + public override void Validate() + { + _ = this.URL; + _ = this.XRequestID; + _ = this.UserAgent; + } + + public Request() { } + +#pragma warning disable CS8618 + [SetsRequiredMembers] + Request(Dictionary properties) + { + Properties = properties; + } +#pragma warning restore CS8618 + + public static Request FromRawUnchecked(Dictionary properties) + { + return new(properties); + } +} diff --git a/src/Imagekit/Models/Webhooks/VideoTransformationErrorEvent.cs b/src/Imagekit/Models/Webhooks/VideoTransformationErrorEvent.cs new file mode 100644 index 00000000..f8e5a29c --- /dev/null +++ b/src/Imagekit/Models/Webhooks/VideoTransformationErrorEvent.cs @@ -0,0 +1,150 @@ +using System; +using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; +using System.Text.Json; +using System.Text.Json.Serialization; +using Imagekit.Models.Webhooks.VideoTransformationErrorEventProperties; + +namespace Imagekit.Models.Webhooks; + +/// +/// Triggered when an error occurs during video encoding. Listen to this webhook to +/// log error reasons and debug issues. Check your origin and URL endpoint settings +/// if the reason is related to download failure. For other errors, contact ImageKit +/// support. +/// +[JsonConverter(typeof(ModelConverter))] +public sealed record class VideoTransformationErrorEvent + : ModelBase, + IFromRaw +{ + /// + /// Unique identifier for the event. + /// + public required string ID + { + get + { + if (!this.Properties.TryGetValue("id", out JsonElement element)) + throw new ArgumentOutOfRangeException("id", "Missing required argument"); + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions) + ?? throw new ArgumentNullException("id"); + } + set + { + this.Properties["id"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + /// + /// Timestamp when the event was created in ISO8601 format. + /// + public required DateTime CreatedAt + { + get + { + if (!this.Properties.TryGetValue("created_at", out JsonElement element)) + throw new ArgumentOutOfRangeException("created_at", "Missing required argument"); + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions); + } + set + { + this.Properties["created_at"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + public required Data Data + { + get + { + if (!this.Properties.TryGetValue("data", out JsonElement element)) + throw new ArgumentOutOfRangeException("data", "Missing required argument"); + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions) + ?? throw new ArgumentNullException("data"); + } + set + { + this.Properties["data"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + /// + /// Information about the original request that triggered the video transformation. + /// + public required Request Request + { + get + { + if (!this.Properties.TryGetValue("request", out JsonElement element)) + throw new ArgumentOutOfRangeException("request", "Missing required argument"); + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions) + ?? throw new ArgumentNullException("request"); + } + set + { + this.Properties["request"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + public JsonElement Type + { + get + { + if (!this.Properties.TryGetValue("type", out JsonElement element)) + throw new ArgumentOutOfRangeException("type", "Missing required argument"); + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions); + } + set + { + this.Properties["type"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + public override void Validate() + { + _ = this.ID; + _ = this.CreatedAt; + this.Data.Validate(); + this.Request.Validate(); + } + + public VideoTransformationErrorEvent() + { + this.Type = JsonSerializer.Deserialize("\"video.transformation.error\""); + } + +#pragma warning disable CS8618 + [SetsRequiredMembers] + VideoTransformationErrorEvent(Dictionary properties) + { + Properties = properties; + } +#pragma warning restore CS8618 + + public static VideoTransformationErrorEvent FromRawUnchecked( + Dictionary properties + ) + { + return new(properties); + } +} diff --git a/src/Imagekit/Models/Webhooks/VideoTransformationErrorEventProperties/Data.cs b/src/Imagekit/Models/Webhooks/VideoTransformationErrorEventProperties/Data.cs new file mode 100644 index 00000000..92ae506e --- /dev/null +++ b/src/Imagekit/Models/Webhooks/VideoTransformationErrorEventProperties/Data.cs @@ -0,0 +1,81 @@ +using System; +using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; +using System.Text.Json; +using System.Text.Json.Serialization; +using DataProperties = Imagekit.Models.Webhooks.VideoTransformationErrorEventProperties.DataProperties; + +namespace Imagekit.Models.Webhooks.VideoTransformationErrorEventProperties; + +[JsonConverter(typeof(ModelConverter))] +public sealed record class Data : ModelBase, IFromRaw +{ + /// + /// Information about the source video asset being transformed. + /// + public required DataProperties::Asset Asset + { + get + { + if (!this.Properties.TryGetValue("asset", out JsonElement element)) + throw new ArgumentOutOfRangeException("asset", "Missing required argument"); + + return JsonSerializer.Deserialize( + element, + ModelBase.SerializerOptions + ) ?? throw new ArgumentNullException("asset"); + } + set + { + this.Properties["asset"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + public required DataProperties::Transformation Transformation + { + get + { + if (!this.Properties.TryGetValue("transformation", out JsonElement element)) + throw new ArgumentOutOfRangeException( + "transformation", + "Missing required argument" + ); + + return JsonSerializer.Deserialize( + element, + ModelBase.SerializerOptions + ) ?? throw new ArgumentNullException("transformation"); + } + set + { + this.Properties["transformation"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + public override void Validate() + { + this.Asset.Validate(); + this.Transformation.Validate(); + } + + public Data() { } + +#pragma warning disable CS8618 + [SetsRequiredMembers] + Data(Dictionary properties) + { + Properties = properties; + } +#pragma warning restore CS8618 + + public static Data FromRawUnchecked(Dictionary properties) + { + return new(properties); + } +} diff --git a/src/Imagekit/Models/Webhooks/VideoTransformationErrorEventProperties/DataProperties/Asset.cs b/src/Imagekit/Models/Webhooks/VideoTransformationErrorEventProperties/DataProperties/Asset.cs new file mode 100644 index 00000000..31f10dbe --- /dev/null +++ b/src/Imagekit/Models/Webhooks/VideoTransformationErrorEventProperties/DataProperties/Asset.cs @@ -0,0 +1,63 @@ +using System; +using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; +using System.Text.Json; +using System.Text.Json.Serialization; + +namespace Imagekit.Models.Webhooks.VideoTransformationErrorEventProperties.DataProperties; + +/// +/// Information about the source video asset being transformed. +/// +[JsonConverter(typeof(ModelConverter))] +public sealed record class Asset : ModelBase, IFromRaw +{ + /// + /// URL to download or access the source video file. + /// + public required string URL + { + get + { + if (!this.Properties.TryGetValue("url", out JsonElement element)) + throw new ArgumentOutOfRangeException("url", "Missing required argument"); + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions) + ?? throw new ArgumentNullException("url"); + } + set + { + this.Properties["url"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + public override void Validate() + { + _ = this.URL; + } + + public Asset() { } + +#pragma warning disable CS8618 + [SetsRequiredMembers] + Asset(Dictionary properties) + { + Properties = properties; + } +#pragma warning restore CS8618 + + public static Asset FromRawUnchecked(Dictionary properties) + { + return new(properties); + } + + [SetsRequiredMembers] + public Asset(string url) + : this() + { + this.URL = url; + } +} diff --git a/src/Imagekit/Models/Webhooks/VideoTransformationErrorEventProperties/DataProperties/Transformation.cs b/src/Imagekit/Models/Webhooks/VideoTransformationErrorEventProperties/DataProperties/Transformation.cs new file mode 100644 index 00000000..99f6feee --- /dev/null +++ b/src/Imagekit/Models/Webhooks/VideoTransformationErrorEventProperties/DataProperties/Transformation.cs @@ -0,0 +1,115 @@ +using System; +using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; +using System.Text.Json; +using System.Text.Json.Serialization; +using TransformationProperties = Imagekit.Models.Webhooks.VideoTransformationErrorEventProperties.DataProperties.TransformationProperties; + +namespace Imagekit.Models.Webhooks.VideoTransformationErrorEventProperties.DataProperties; + +[JsonConverter(typeof(ModelConverter))] +public sealed record class Transformation : ModelBase, IFromRaw +{ + /// + /// Type of video transformation: - `video-transformation`: Standard video processing + /// (resize, format conversion, etc.) - `gif-to-video`: Convert animated GIF to + /// video format - `video-thumbnail`: Generate thumbnail image from video + /// + public required ApiEnum Type + { + get + { + if (!this.Properties.TryGetValue("type", out JsonElement element)) + throw new ArgumentOutOfRangeException("type", "Missing required argument"); + + return JsonSerializer.Deserialize>( + element, + ModelBase.SerializerOptions + ); + } + set + { + this.Properties["type"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + /// + /// Details about the transformation error. + /// + public TransformationProperties::Error? Error + { + get + { + if (!this.Properties.TryGetValue("error", out JsonElement element)) + return null; + + return JsonSerializer.Deserialize( + element, + ModelBase.SerializerOptions + ); + } + set + { + this.Properties["error"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + /// + /// Configuration options for video transformations. + /// + public TransformationProperties::Options? Options + { + get + { + if (!this.Properties.TryGetValue("options", out JsonElement element)) + return null; + + return JsonSerializer.Deserialize( + element, + ModelBase.SerializerOptions + ); + } + set + { + this.Properties["options"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + public override void Validate() + { + this.Type.Validate(); + this.Error?.Validate(); + this.Options?.Validate(); + } + + public Transformation() { } + +#pragma warning disable CS8618 + [SetsRequiredMembers] + Transformation(Dictionary properties) + { + Properties = properties; + } +#pragma warning restore CS8618 + + public static Transformation FromRawUnchecked(Dictionary properties) + { + return new(properties); + } + + [SetsRequiredMembers] + public Transformation(ApiEnum type) + : this() + { + this.Type = type; + } +} diff --git a/src/Imagekit/Models/Webhooks/VideoTransformationErrorEventProperties/DataProperties/TransformationProperties/Error.cs b/src/Imagekit/Models/Webhooks/VideoTransformationErrorEventProperties/DataProperties/TransformationProperties/Error.cs new file mode 100644 index 00000000..9b2dbb8d --- /dev/null +++ b/src/Imagekit/Models/Webhooks/VideoTransformationErrorEventProperties/DataProperties/TransformationProperties/Error.cs @@ -0,0 +1,71 @@ +using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; +using System.Text.Json; +using System.Text.Json.Serialization; +using Imagekit.Models.Webhooks.VideoTransformationErrorEventProperties.DataProperties.TransformationProperties.ErrorProperties; +using System = System; + +namespace Imagekit.Models.Webhooks.VideoTransformationErrorEventProperties.DataProperties.TransformationProperties; + +/// +/// Details about the transformation error. +/// +[JsonConverter(typeof(ModelConverter))] +public sealed record class Error : ModelBase, IFromRaw +{ + /// + /// Specific reason for the transformation failure: - `encoding_failed`: Error + /// during video encoding process - `download_failed`: Could not download source + /// video - `internal_server_error`: Unexpected server error + /// + public required ApiEnum Reason + { + get + { + if (!this.Properties.TryGetValue("reason", out JsonElement element)) + throw new System::ArgumentOutOfRangeException( + "reason", + "Missing required argument" + ); + + return JsonSerializer.Deserialize>( + element, + ModelBase.SerializerOptions + ); + } + set + { + this.Properties["reason"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + public override void Validate() + { + this.Reason.Validate(); + } + + public Error() { } + +#pragma warning disable CS8618 + [SetsRequiredMembers] + Error(Dictionary properties) + { + Properties = properties; + } +#pragma warning restore CS8618 + + public static Error FromRawUnchecked(Dictionary properties) + { + return new(properties); + } + + [SetsRequiredMembers] + public Error(ApiEnum reason) + : this() + { + this.Reason = reason; + } +} diff --git a/src/Imagekit/Models/Webhooks/VideoTransformationErrorEventProperties/DataProperties/TransformationProperties/ErrorProperties/Reason.cs b/src/Imagekit/Models/Webhooks/VideoTransformationErrorEventProperties/DataProperties/TransformationProperties/ErrorProperties/Reason.cs new file mode 100644 index 00000000..f0995426 --- /dev/null +++ b/src/Imagekit/Models/Webhooks/VideoTransformationErrorEventProperties/DataProperties/TransformationProperties/ErrorProperties/Reason.cs @@ -0,0 +1,51 @@ +using System.Text.Json; +using System.Text.Json.Serialization; +using System = System; + +namespace Imagekit.Models.Webhooks.VideoTransformationErrorEventProperties.DataProperties.TransformationProperties.ErrorProperties; + +/// +/// Specific reason for the transformation failure: - `encoding_failed`: Error during +/// video encoding process - `download_failed`: Could not download source video - +/// `internal_server_error`: Unexpected server error +/// +[JsonConverter(typeof(ReasonConverter))] +public enum Reason +{ + EncodingFailed, + DownloadFailed, + InternalServerError, +} + +sealed class ReasonConverter : JsonConverter +{ + public override Reason Read( + ref Utf8JsonReader reader, + System::Type typeToConvert, + JsonSerializerOptions options + ) + { + return JsonSerializer.Deserialize(ref reader, options) switch + { + "encoding_failed" => Reason.EncodingFailed, + "download_failed" => Reason.DownloadFailed, + "internal_server_error" => Reason.InternalServerError, + _ => (Reason)(-1), + }; + } + + public override void Write(Utf8JsonWriter writer, Reason value, JsonSerializerOptions options) + { + JsonSerializer.Serialize( + writer, + value switch + { + Reason.EncodingFailed => "encoding_failed", + Reason.DownloadFailed => "download_failed", + Reason.InternalServerError => "internal_server_error", + _ => throw new System::ArgumentOutOfRangeException(nameof(value)), + }, + options + ); + } +} diff --git a/src/Imagekit/Models/Webhooks/VideoTransformationErrorEventProperties/DataProperties/TransformationProperties/Options.cs b/src/Imagekit/Models/Webhooks/VideoTransformationErrorEventProperties/DataProperties/TransformationProperties/Options.cs new file mode 100644 index 00000000..7b11a0cb --- /dev/null +++ b/src/Imagekit/Models/Webhooks/VideoTransformationErrorEventProperties/DataProperties/TransformationProperties/Options.cs @@ -0,0 +1,202 @@ +using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; +using System.Text.Json; +using System.Text.Json.Serialization; +using Imagekit.Models.Webhooks.VideoTransformationErrorEventProperties.DataProperties.TransformationProperties.OptionsProperties; + +namespace Imagekit.Models.Webhooks.VideoTransformationErrorEventProperties.DataProperties.TransformationProperties; + +/// +/// Configuration options for video transformations. +/// +[JsonConverter(typeof(ModelConverter))] +public sealed record class Options : ModelBase, IFromRaw +{ + /// + /// Audio codec used for encoding (aac or opus). + /// + public ApiEnum? AudioCodec + { + get + { + if (!this.Properties.TryGetValue("audio_codec", out JsonElement element)) + return null; + + return JsonSerializer.Deserialize?>( + element, + ModelBase.SerializerOptions + ); + } + set + { + this.Properties["audio_codec"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + /// + /// Whether to automatically rotate the video based on metadata. + /// + public bool? AutoRotate + { + get + { + if (!this.Properties.TryGetValue("auto_rotate", out JsonElement element)) + return null; + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions); + } + set + { + this.Properties["auto_rotate"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + /// + /// Output format for the transformed video or thumbnail. + /// + public ApiEnum? Format + { + get + { + if (!this.Properties.TryGetValue("format", out JsonElement element)) + return null; + + return JsonSerializer.Deserialize?>( + element, + ModelBase.SerializerOptions + ); + } + set + { + this.Properties["format"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + /// + /// Quality setting for the output video. + /// + public long? Quality + { + get + { + if (!this.Properties.TryGetValue("quality", out JsonElement element)) + return null; + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions); + } + set + { + this.Properties["quality"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + /// + /// Streaming protocol for adaptive bitrate streaming. + /// + public ApiEnum? StreamProtocol + { + get + { + if (!this.Properties.TryGetValue("stream_protocol", out JsonElement element)) + return null; + + return JsonSerializer.Deserialize?>( + element, + ModelBase.SerializerOptions + ); + } + set + { + this.Properties["stream_protocol"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + /// + /// Array of quality representations for adaptive bitrate streaming. + /// + public List? Variants + { + get + { + if (!this.Properties.TryGetValue("variants", out JsonElement element)) + return null; + + return JsonSerializer.Deserialize?>(element, ModelBase.SerializerOptions); + } + set + { + this.Properties["variants"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + /// + /// Video codec used for encoding (h264, vp9, or av1). + /// + public ApiEnum? VideoCodec + { + get + { + if (!this.Properties.TryGetValue("video_codec", out JsonElement element)) + return null; + + return JsonSerializer.Deserialize?>( + element, + ModelBase.SerializerOptions + ); + } + set + { + this.Properties["video_codec"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + public override void Validate() + { + this.AudioCodec?.Validate(); + _ = this.AutoRotate; + this.Format?.Validate(); + _ = this.Quality; + this.StreamProtocol?.Validate(); + foreach (var item in this.Variants ?? []) + { + _ = item; + } + this.VideoCodec?.Validate(); + } + + public Options() { } + +#pragma warning disable CS8618 + [SetsRequiredMembers] + Options(Dictionary properties) + { + Properties = properties; + } +#pragma warning restore CS8618 + + public static Options FromRawUnchecked(Dictionary properties) + { + return new(properties); + } +} diff --git a/src/Imagekit/Models/Webhooks/VideoTransformationErrorEventProperties/DataProperties/TransformationProperties/OptionsProperties/AudioCodec.cs b/src/Imagekit/Models/Webhooks/VideoTransformationErrorEventProperties/DataProperties/TransformationProperties/OptionsProperties/AudioCodec.cs new file mode 100644 index 00000000..03cfe515 --- /dev/null +++ b/src/Imagekit/Models/Webhooks/VideoTransformationErrorEventProperties/DataProperties/TransformationProperties/OptionsProperties/AudioCodec.cs @@ -0,0 +1,50 @@ +using System.Text.Json; +using System.Text.Json.Serialization; +using System = System; + +namespace Imagekit.Models.Webhooks.VideoTransformationErrorEventProperties.DataProperties.TransformationProperties.OptionsProperties; + +/// +/// Audio codec used for encoding (aac or opus). +/// +[JsonConverter(typeof(AudioCodecConverter))] +public enum AudioCodec +{ + Aac, + Opus, +} + +sealed class AudioCodecConverter : JsonConverter +{ + public override AudioCodec Read( + ref Utf8JsonReader reader, + System::Type typeToConvert, + JsonSerializerOptions options + ) + { + return JsonSerializer.Deserialize(ref reader, options) switch + { + "aac" => AudioCodec.Aac, + "opus" => AudioCodec.Opus, + _ => (AudioCodec)(-1), + }; + } + + public override void Write( + Utf8JsonWriter writer, + AudioCodec value, + JsonSerializerOptions options + ) + { + JsonSerializer.Serialize( + writer, + value switch + { + AudioCodec.Aac => "aac", + AudioCodec.Opus => "opus", + _ => throw new System::ArgumentOutOfRangeException(nameof(value)), + }, + options + ); + } +} diff --git a/src/Imagekit/Models/Webhooks/VideoTransformationErrorEventProperties/DataProperties/TransformationProperties/OptionsProperties/Format.cs b/src/Imagekit/Models/Webhooks/VideoTransformationErrorEventProperties/DataProperties/TransformationProperties/OptionsProperties/Format.cs new file mode 100644 index 00000000..0955e08d --- /dev/null +++ b/src/Imagekit/Models/Webhooks/VideoTransformationErrorEventProperties/DataProperties/TransformationProperties/OptionsProperties/Format.cs @@ -0,0 +1,55 @@ +using System.Text.Json; +using System.Text.Json.Serialization; +using System = System; + +namespace Imagekit.Models.Webhooks.VideoTransformationErrorEventProperties.DataProperties.TransformationProperties.OptionsProperties; + +/// +/// Output format for the transformed video or thumbnail. +/// +[JsonConverter(typeof(FormatConverter))] +public enum Format +{ + MP4, + Webm, + Jpg, + Png, + Webp, +} + +sealed class FormatConverter : JsonConverter +{ + public override Format Read( + ref Utf8JsonReader reader, + System::Type typeToConvert, + JsonSerializerOptions options + ) + { + return JsonSerializer.Deserialize(ref reader, options) switch + { + "mp4" => Format.MP4, + "webm" => Format.Webm, + "jpg" => Format.Jpg, + "png" => Format.Png, + "webp" => Format.Webp, + _ => (Format)(-1), + }; + } + + public override void Write(Utf8JsonWriter writer, Format value, JsonSerializerOptions options) + { + JsonSerializer.Serialize( + writer, + value switch + { + Format.MP4 => "mp4", + Format.Webm => "webm", + Format.Jpg => "jpg", + Format.Png => "png", + Format.Webp => "webp", + _ => throw new System::ArgumentOutOfRangeException(nameof(value)), + }, + options + ); + } +} diff --git a/src/Imagekit/Models/Webhooks/VideoTransformationErrorEventProperties/DataProperties/TransformationProperties/OptionsProperties/StreamProtocol.cs b/src/Imagekit/Models/Webhooks/VideoTransformationErrorEventProperties/DataProperties/TransformationProperties/OptionsProperties/StreamProtocol.cs new file mode 100644 index 00000000..53822ce7 --- /dev/null +++ b/src/Imagekit/Models/Webhooks/VideoTransformationErrorEventProperties/DataProperties/TransformationProperties/OptionsProperties/StreamProtocol.cs @@ -0,0 +1,50 @@ +using System.Text.Json; +using System.Text.Json.Serialization; +using System = System; + +namespace Imagekit.Models.Webhooks.VideoTransformationErrorEventProperties.DataProperties.TransformationProperties.OptionsProperties; + +/// +/// Streaming protocol for adaptive bitrate streaming. +/// +[JsonConverter(typeof(StreamProtocolConverter))] +public enum StreamProtocol +{ + Hls, + Dash, +} + +sealed class StreamProtocolConverter : JsonConverter +{ + public override StreamProtocol Read( + ref Utf8JsonReader reader, + System::Type typeToConvert, + JsonSerializerOptions options + ) + { + return JsonSerializer.Deserialize(ref reader, options) switch + { + "HLS" => StreamProtocol.Hls, + "DASH" => StreamProtocol.Dash, + _ => (StreamProtocol)(-1), + }; + } + + public override void Write( + Utf8JsonWriter writer, + StreamProtocol value, + JsonSerializerOptions options + ) + { + JsonSerializer.Serialize( + writer, + value switch + { + StreamProtocol.Hls => "HLS", + StreamProtocol.Dash => "DASH", + _ => throw new System::ArgumentOutOfRangeException(nameof(value)), + }, + options + ); + } +} diff --git a/src/Imagekit/Models/Webhooks/VideoTransformationErrorEventProperties/DataProperties/TransformationProperties/OptionsProperties/VideoCodec.cs b/src/Imagekit/Models/Webhooks/VideoTransformationErrorEventProperties/DataProperties/TransformationProperties/OptionsProperties/VideoCodec.cs new file mode 100644 index 00000000..f6d33a3e --- /dev/null +++ b/src/Imagekit/Models/Webhooks/VideoTransformationErrorEventProperties/DataProperties/TransformationProperties/OptionsProperties/VideoCodec.cs @@ -0,0 +1,53 @@ +using System.Text.Json; +using System.Text.Json.Serialization; +using System = System; + +namespace Imagekit.Models.Webhooks.VideoTransformationErrorEventProperties.DataProperties.TransformationProperties.OptionsProperties; + +/// +/// Video codec used for encoding (h264, vp9, or av1). +/// +[JsonConverter(typeof(VideoCodecConverter))] +public enum VideoCodec +{ + H264, + Vp9, + Av1, +} + +sealed class VideoCodecConverter : JsonConverter +{ + public override VideoCodec Read( + ref Utf8JsonReader reader, + System::Type typeToConvert, + JsonSerializerOptions options + ) + { + return JsonSerializer.Deserialize(ref reader, options) switch + { + "h264" => VideoCodec.H264, + "vp9" => VideoCodec.Vp9, + "av1" => VideoCodec.Av1, + _ => (VideoCodec)(-1), + }; + } + + public override void Write( + Utf8JsonWriter writer, + VideoCodec value, + JsonSerializerOptions options + ) + { + JsonSerializer.Serialize( + writer, + value switch + { + VideoCodec.H264 => "h264", + VideoCodec.Vp9 => "vp9", + VideoCodec.Av1 => "av1", + _ => throw new System::ArgumentOutOfRangeException(nameof(value)), + }, + options + ); + } +} diff --git a/src/Imagekit/Models/Webhooks/VideoTransformationErrorEventProperties/DataProperties/TransformationProperties/Type.cs b/src/Imagekit/Models/Webhooks/VideoTransformationErrorEventProperties/DataProperties/TransformationProperties/Type.cs new file mode 100644 index 00000000..8823f849 --- /dev/null +++ b/src/Imagekit/Models/Webhooks/VideoTransformationErrorEventProperties/DataProperties/TransformationProperties/Type.cs @@ -0,0 +1,51 @@ +using System.Text.Json; +using System.Text.Json.Serialization; +using System = System; + +namespace Imagekit.Models.Webhooks.VideoTransformationErrorEventProperties.DataProperties.TransformationProperties; + +/// +/// Type of video transformation: - `video-transformation`: Standard video processing +/// (resize, format conversion, etc.) - `gif-to-video`: Convert animated GIF to video +/// format - `video-thumbnail`: Generate thumbnail image from video +/// +[JsonConverter(typeof(TypeConverter))] +public enum Type +{ + VideoTransformation, + GifToVideo, + VideoThumbnail, +} + +sealed class TypeConverter : JsonConverter +{ + public override Type Read( + ref Utf8JsonReader reader, + System::Type typeToConvert, + JsonSerializerOptions options + ) + { + return JsonSerializer.Deserialize(ref reader, options) switch + { + "video-transformation" => TransformationProperties.Type.VideoTransformation, + "gif-to-video" => TransformationProperties.Type.GifToVideo, + "video-thumbnail" => TransformationProperties.Type.VideoThumbnail, + _ => (Type)(-1), + }; + } + + public override void Write(Utf8JsonWriter writer, Type value, JsonSerializerOptions options) + { + JsonSerializer.Serialize( + writer, + value switch + { + TransformationProperties.Type.VideoTransformation => "video-transformation", + TransformationProperties.Type.GifToVideo => "gif-to-video", + TransformationProperties.Type.VideoThumbnail => "video-thumbnail", + _ => throw new System::ArgumentOutOfRangeException(nameof(value)), + }, + options + ); + } +} diff --git a/src/Imagekit/Models/Webhooks/VideoTransformationErrorEventProperties/Request.cs b/src/Imagekit/Models/Webhooks/VideoTransformationErrorEventProperties/Request.cs new file mode 100644 index 00000000..74ac3484 --- /dev/null +++ b/src/Imagekit/Models/Webhooks/VideoTransformationErrorEventProperties/Request.cs @@ -0,0 +1,101 @@ +using System; +using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; +using System.Text.Json; +using System.Text.Json.Serialization; + +namespace Imagekit.Models.Webhooks.VideoTransformationErrorEventProperties; + +/// +/// Information about the original request that triggered the video transformation. +/// +[JsonConverter(typeof(ModelConverter))] +public sealed record class Request : ModelBase, IFromRaw +{ + /// + /// Full URL of the transformation request that was submitted. + /// + public required string URL + { + get + { + if (!this.Properties.TryGetValue("url", out JsonElement element)) + throw new ArgumentOutOfRangeException("url", "Missing required argument"); + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions) + ?? throw new ArgumentNullException("url"); + } + set + { + this.Properties["url"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + /// + /// Unique identifier for the originating transformation request. + /// + public required string XRequestID + { + get + { + if (!this.Properties.TryGetValue("x_request_id", out JsonElement element)) + throw new ArgumentOutOfRangeException("x_request_id", "Missing required argument"); + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions) + ?? throw new ArgumentNullException("x_request_id"); + } + set + { + this.Properties["x_request_id"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + /// + /// User-Agent header from the original request that triggered the transformation. + /// + public string? UserAgent + { + get + { + if (!this.Properties.TryGetValue("user_agent", out JsonElement element)) + return null; + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions); + } + set + { + this.Properties["user_agent"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + public override void Validate() + { + _ = this.URL; + _ = this.XRequestID; + _ = this.UserAgent; + } + + public Request() { } + +#pragma warning disable CS8618 + [SetsRequiredMembers] + Request(Dictionary properties) + { + Properties = properties; + } +#pragma warning restore CS8618 + + public static Request FromRawUnchecked(Dictionary properties) + { + return new(properties); + } +} diff --git a/src/Imagekit/Models/Webhooks/VideoTransformationReadyEvent.cs b/src/Imagekit/Models/Webhooks/VideoTransformationReadyEvent.cs new file mode 100644 index 00000000..ebd61c2f --- /dev/null +++ b/src/Imagekit/Models/Webhooks/VideoTransformationReadyEvent.cs @@ -0,0 +1,172 @@ +using System; +using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; +using System.Text.Json; +using System.Text.Json.Serialization; +using Imagekit.Models.Webhooks.VideoTransformationReadyEventProperties; + +namespace Imagekit.Models.Webhooks; + +/// +/// Triggered when video encoding is finished and the transformed resource is ready +/// to be served. This is the key event to listen for - update your database or CMS +/// flags when you receive this so your application can start showing the transformed +/// video to users. +/// +[JsonConverter(typeof(ModelConverter))] +public sealed record class VideoTransformationReadyEvent + : ModelBase, + IFromRaw +{ + /// + /// Unique identifier for the event. + /// + public required string ID + { + get + { + if (!this.Properties.TryGetValue("id", out JsonElement element)) + throw new ArgumentOutOfRangeException("id", "Missing required argument"); + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions) + ?? throw new ArgumentNullException("id"); + } + set + { + this.Properties["id"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + /// + /// Timestamp when the event was created in ISO8601 format. + /// + public required DateTime CreatedAt + { + get + { + if (!this.Properties.TryGetValue("created_at", out JsonElement element)) + throw new ArgumentOutOfRangeException("created_at", "Missing required argument"); + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions); + } + set + { + this.Properties["created_at"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + public required Data Data + { + get + { + if (!this.Properties.TryGetValue("data", out JsonElement element)) + throw new ArgumentOutOfRangeException("data", "Missing required argument"); + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions) + ?? throw new ArgumentNullException("data"); + } + set + { + this.Properties["data"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + /// + /// Information about the original request that triggered the video transformation. + /// + public required Request Request + { + get + { + if (!this.Properties.TryGetValue("request", out JsonElement element)) + throw new ArgumentOutOfRangeException("request", "Missing required argument"); + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions) + ?? throw new ArgumentNullException("request"); + } + set + { + this.Properties["request"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + public JsonElement Type + { + get + { + if (!this.Properties.TryGetValue("type", out JsonElement element)) + throw new ArgumentOutOfRangeException("type", "Missing required argument"); + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions); + } + set + { + this.Properties["type"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + /// + /// Performance metrics for the transformation process. + /// + public Timings? Timings + { + get + { + if (!this.Properties.TryGetValue("timings", out JsonElement element)) + return null; + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions); + } + set + { + this.Properties["timings"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + public override void Validate() + { + _ = this.ID; + _ = this.CreatedAt; + this.Data.Validate(); + this.Request.Validate(); + this.Timings?.Validate(); + } + + public VideoTransformationReadyEvent() + { + this.Type = JsonSerializer.Deserialize("\"video.transformation.ready\""); + } + +#pragma warning disable CS8618 + [SetsRequiredMembers] + VideoTransformationReadyEvent(Dictionary properties) + { + Properties = properties; + } +#pragma warning restore CS8618 + + public static VideoTransformationReadyEvent FromRawUnchecked( + Dictionary properties + ) + { + return new(properties); + } +} diff --git a/src/Imagekit/Models/Webhooks/VideoTransformationReadyEventProperties/Data.cs b/src/Imagekit/Models/Webhooks/VideoTransformationReadyEventProperties/Data.cs new file mode 100644 index 00000000..1dd96038 --- /dev/null +++ b/src/Imagekit/Models/Webhooks/VideoTransformationReadyEventProperties/Data.cs @@ -0,0 +1,81 @@ +using System; +using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; +using System.Text.Json; +using System.Text.Json.Serialization; +using DataProperties = Imagekit.Models.Webhooks.VideoTransformationReadyEventProperties.DataProperties; + +namespace Imagekit.Models.Webhooks.VideoTransformationReadyEventProperties; + +[JsonConverter(typeof(ModelConverter))] +public sealed record class Data : ModelBase, IFromRaw +{ + /// + /// Information about the source video asset being transformed. + /// + public required DataProperties::Asset Asset + { + get + { + if (!this.Properties.TryGetValue("asset", out JsonElement element)) + throw new ArgumentOutOfRangeException("asset", "Missing required argument"); + + return JsonSerializer.Deserialize( + element, + ModelBase.SerializerOptions + ) ?? throw new ArgumentNullException("asset"); + } + set + { + this.Properties["asset"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + public required DataProperties::Transformation Transformation + { + get + { + if (!this.Properties.TryGetValue("transformation", out JsonElement element)) + throw new ArgumentOutOfRangeException( + "transformation", + "Missing required argument" + ); + + return JsonSerializer.Deserialize( + element, + ModelBase.SerializerOptions + ) ?? throw new ArgumentNullException("transformation"); + } + set + { + this.Properties["transformation"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + public override void Validate() + { + this.Asset.Validate(); + this.Transformation.Validate(); + } + + public Data() { } + +#pragma warning disable CS8618 + [SetsRequiredMembers] + Data(Dictionary properties) + { + Properties = properties; + } +#pragma warning restore CS8618 + + public static Data FromRawUnchecked(Dictionary properties) + { + return new(properties); + } +} diff --git a/src/Imagekit/Models/Webhooks/VideoTransformationReadyEventProperties/DataProperties/Asset.cs b/src/Imagekit/Models/Webhooks/VideoTransformationReadyEventProperties/DataProperties/Asset.cs new file mode 100644 index 00000000..0859135a --- /dev/null +++ b/src/Imagekit/Models/Webhooks/VideoTransformationReadyEventProperties/DataProperties/Asset.cs @@ -0,0 +1,63 @@ +using System; +using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; +using System.Text.Json; +using System.Text.Json.Serialization; + +namespace Imagekit.Models.Webhooks.VideoTransformationReadyEventProperties.DataProperties; + +/// +/// Information about the source video asset being transformed. +/// +[JsonConverter(typeof(ModelConverter))] +public sealed record class Asset : ModelBase, IFromRaw +{ + /// + /// URL to download or access the source video file. + /// + public required string URL + { + get + { + if (!this.Properties.TryGetValue("url", out JsonElement element)) + throw new ArgumentOutOfRangeException("url", "Missing required argument"); + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions) + ?? throw new ArgumentNullException("url"); + } + set + { + this.Properties["url"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + public override void Validate() + { + _ = this.URL; + } + + public Asset() { } + +#pragma warning disable CS8618 + [SetsRequiredMembers] + Asset(Dictionary properties) + { + Properties = properties; + } +#pragma warning restore CS8618 + + public static Asset FromRawUnchecked(Dictionary properties) + { + return new(properties); + } + + [SetsRequiredMembers] + public Asset(string url) + : this() + { + this.URL = url; + } +} diff --git a/src/Imagekit/Models/Webhooks/VideoTransformationReadyEventProperties/DataProperties/Transformation.cs b/src/Imagekit/Models/Webhooks/VideoTransformationReadyEventProperties/DataProperties/Transformation.cs new file mode 100644 index 00000000..3c0c8315 --- /dev/null +++ b/src/Imagekit/Models/Webhooks/VideoTransformationReadyEventProperties/DataProperties/Transformation.cs @@ -0,0 +1,115 @@ +using System; +using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; +using System.Text.Json; +using System.Text.Json.Serialization; +using TransformationProperties = Imagekit.Models.Webhooks.VideoTransformationReadyEventProperties.DataProperties.TransformationProperties; + +namespace Imagekit.Models.Webhooks.VideoTransformationReadyEventProperties.DataProperties; + +[JsonConverter(typeof(ModelConverter))] +public sealed record class Transformation : ModelBase, IFromRaw +{ + /// + /// Type of video transformation: - `video-transformation`: Standard video processing + /// (resize, format conversion, etc.) - `gif-to-video`: Convert animated GIF to + /// video format - `video-thumbnail`: Generate thumbnail image from video + /// + public required ApiEnum Type + { + get + { + if (!this.Properties.TryGetValue("type", out JsonElement element)) + throw new ArgumentOutOfRangeException("type", "Missing required argument"); + + return JsonSerializer.Deserialize>( + element, + ModelBase.SerializerOptions + ); + } + set + { + this.Properties["type"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + /// + /// Configuration options for video transformations. + /// + public TransformationProperties::Options? Options + { + get + { + if (!this.Properties.TryGetValue("options", out JsonElement element)) + return null; + + return JsonSerializer.Deserialize( + element, + ModelBase.SerializerOptions + ); + } + set + { + this.Properties["options"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + /// + /// Information about the transformed output video. + /// + public TransformationProperties::Output? Output + { + get + { + if (!this.Properties.TryGetValue("output", out JsonElement element)) + return null; + + return JsonSerializer.Deserialize( + element, + ModelBase.SerializerOptions + ); + } + set + { + this.Properties["output"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + public override void Validate() + { + this.Type.Validate(); + this.Options?.Validate(); + this.Output?.Validate(); + } + + public Transformation() { } + +#pragma warning disable CS8618 + [SetsRequiredMembers] + Transformation(Dictionary properties) + { + Properties = properties; + } +#pragma warning restore CS8618 + + public static Transformation FromRawUnchecked(Dictionary properties) + { + return new(properties); + } + + [SetsRequiredMembers] + public Transformation(ApiEnum type) + : this() + { + this.Type = type; + } +} diff --git a/src/Imagekit/Models/Webhooks/VideoTransformationReadyEventProperties/DataProperties/TransformationProperties/Options.cs b/src/Imagekit/Models/Webhooks/VideoTransformationReadyEventProperties/DataProperties/TransformationProperties/Options.cs new file mode 100644 index 00000000..232195b8 --- /dev/null +++ b/src/Imagekit/Models/Webhooks/VideoTransformationReadyEventProperties/DataProperties/TransformationProperties/Options.cs @@ -0,0 +1,202 @@ +using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; +using System.Text.Json; +using System.Text.Json.Serialization; +using Imagekit.Models.Webhooks.VideoTransformationReadyEventProperties.DataProperties.TransformationProperties.OptionsProperties; + +namespace Imagekit.Models.Webhooks.VideoTransformationReadyEventProperties.DataProperties.TransformationProperties; + +/// +/// Configuration options for video transformations. +/// +[JsonConverter(typeof(ModelConverter))] +public sealed record class Options : ModelBase, IFromRaw +{ + /// + /// Audio codec used for encoding (aac or opus). + /// + public ApiEnum? AudioCodec + { + get + { + if (!this.Properties.TryGetValue("audio_codec", out JsonElement element)) + return null; + + return JsonSerializer.Deserialize?>( + element, + ModelBase.SerializerOptions + ); + } + set + { + this.Properties["audio_codec"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + /// + /// Whether to automatically rotate the video based on metadata. + /// + public bool? AutoRotate + { + get + { + if (!this.Properties.TryGetValue("auto_rotate", out JsonElement element)) + return null; + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions); + } + set + { + this.Properties["auto_rotate"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + /// + /// Output format for the transformed video or thumbnail. + /// + public ApiEnum? Format + { + get + { + if (!this.Properties.TryGetValue("format", out JsonElement element)) + return null; + + return JsonSerializer.Deserialize?>( + element, + ModelBase.SerializerOptions + ); + } + set + { + this.Properties["format"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + /// + /// Quality setting for the output video. + /// + public long? Quality + { + get + { + if (!this.Properties.TryGetValue("quality", out JsonElement element)) + return null; + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions); + } + set + { + this.Properties["quality"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + /// + /// Streaming protocol for adaptive bitrate streaming. + /// + public ApiEnum? StreamProtocol + { + get + { + if (!this.Properties.TryGetValue("stream_protocol", out JsonElement element)) + return null; + + return JsonSerializer.Deserialize?>( + element, + ModelBase.SerializerOptions + ); + } + set + { + this.Properties["stream_protocol"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + /// + /// Array of quality representations for adaptive bitrate streaming. + /// + public List? Variants + { + get + { + if (!this.Properties.TryGetValue("variants", out JsonElement element)) + return null; + + return JsonSerializer.Deserialize?>(element, ModelBase.SerializerOptions); + } + set + { + this.Properties["variants"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + /// + /// Video codec used for encoding (h264, vp9, or av1). + /// + public ApiEnum? VideoCodec + { + get + { + if (!this.Properties.TryGetValue("video_codec", out JsonElement element)) + return null; + + return JsonSerializer.Deserialize?>( + element, + ModelBase.SerializerOptions + ); + } + set + { + this.Properties["video_codec"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + public override void Validate() + { + this.AudioCodec?.Validate(); + _ = this.AutoRotate; + this.Format?.Validate(); + _ = this.Quality; + this.StreamProtocol?.Validate(); + foreach (var item in this.Variants ?? []) + { + _ = item; + } + this.VideoCodec?.Validate(); + } + + public Options() { } + +#pragma warning disable CS8618 + [SetsRequiredMembers] + Options(Dictionary properties) + { + Properties = properties; + } +#pragma warning restore CS8618 + + public static Options FromRawUnchecked(Dictionary properties) + { + return new(properties); + } +} diff --git a/src/Imagekit/Models/Webhooks/VideoTransformationReadyEventProperties/DataProperties/TransformationProperties/OptionsProperties/AudioCodec.cs b/src/Imagekit/Models/Webhooks/VideoTransformationReadyEventProperties/DataProperties/TransformationProperties/OptionsProperties/AudioCodec.cs new file mode 100644 index 00000000..b81c797b --- /dev/null +++ b/src/Imagekit/Models/Webhooks/VideoTransformationReadyEventProperties/DataProperties/TransformationProperties/OptionsProperties/AudioCodec.cs @@ -0,0 +1,50 @@ +using System.Text.Json; +using System.Text.Json.Serialization; +using System = System; + +namespace Imagekit.Models.Webhooks.VideoTransformationReadyEventProperties.DataProperties.TransformationProperties.OptionsProperties; + +/// +/// Audio codec used for encoding (aac or opus). +/// +[JsonConverter(typeof(AudioCodecConverter))] +public enum AudioCodec +{ + Aac, + Opus, +} + +sealed class AudioCodecConverter : JsonConverter +{ + public override AudioCodec Read( + ref Utf8JsonReader reader, + System::Type typeToConvert, + JsonSerializerOptions options + ) + { + return JsonSerializer.Deserialize(ref reader, options) switch + { + "aac" => AudioCodec.Aac, + "opus" => AudioCodec.Opus, + _ => (AudioCodec)(-1), + }; + } + + public override void Write( + Utf8JsonWriter writer, + AudioCodec value, + JsonSerializerOptions options + ) + { + JsonSerializer.Serialize( + writer, + value switch + { + AudioCodec.Aac => "aac", + AudioCodec.Opus => "opus", + _ => throw new System::ArgumentOutOfRangeException(nameof(value)), + }, + options + ); + } +} diff --git a/src/Imagekit/Models/Webhooks/VideoTransformationReadyEventProperties/DataProperties/TransformationProperties/OptionsProperties/Format.cs b/src/Imagekit/Models/Webhooks/VideoTransformationReadyEventProperties/DataProperties/TransformationProperties/OptionsProperties/Format.cs new file mode 100644 index 00000000..3bb8aace --- /dev/null +++ b/src/Imagekit/Models/Webhooks/VideoTransformationReadyEventProperties/DataProperties/TransformationProperties/OptionsProperties/Format.cs @@ -0,0 +1,55 @@ +using System.Text.Json; +using System.Text.Json.Serialization; +using System = System; + +namespace Imagekit.Models.Webhooks.VideoTransformationReadyEventProperties.DataProperties.TransformationProperties.OptionsProperties; + +/// +/// Output format for the transformed video or thumbnail. +/// +[JsonConverter(typeof(FormatConverter))] +public enum Format +{ + MP4, + Webm, + Jpg, + Png, + Webp, +} + +sealed class FormatConverter : JsonConverter +{ + public override Format Read( + ref Utf8JsonReader reader, + System::Type typeToConvert, + JsonSerializerOptions options + ) + { + return JsonSerializer.Deserialize(ref reader, options) switch + { + "mp4" => Format.MP4, + "webm" => Format.Webm, + "jpg" => Format.Jpg, + "png" => Format.Png, + "webp" => Format.Webp, + _ => (Format)(-1), + }; + } + + public override void Write(Utf8JsonWriter writer, Format value, JsonSerializerOptions options) + { + JsonSerializer.Serialize( + writer, + value switch + { + Format.MP4 => "mp4", + Format.Webm => "webm", + Format.Jpg => "jpg", + Format.Png => "png", + Format.Webp => "webp", + _ => throw new System::ArgumentOutOfRangeException(nameof(value)), + }, + options + ); + } +} diff --git a/src/Imagekit/Models/Webhooks/VideoTransformationReadyEventProperties/DataProperties/TransformationProperties/OptionsProperties/StreamProtocol.cs b/src/Imagekit/Models/Webhooks/VideoTransformationReadyEventProperties/DataProperties/TransformationProperties/OptionsProperties/StreamProtocol.cs new file mode 100644 index 00000000..e2492fe8 --- /dev/null +++ b/src/Imagekit/Models/Webhooks/VideoTransformationReadyEventProperties/DataProperties/TransformationProperties/OptionsProperties/StreamProtocol.cs @@ -0,0 +1,50 @@ +using System.Text.Json; +using System.Text.Json.Serialization; +using System = System; + +namespace Imagekit.Models.Webhooks.VideoTransformationReadyEventProperties.DataProperties.TransformationProperties.OptionsProperties; + +/// +/// Streaming protocol for adaptive bitrate streaming. +/// +[JsonConverter(typeof(StreamProtocolConverter))] +public enum StreamProtocol +{ + Hls, + Dash, +} + +sealed class StreamProtocolConverter : JsonConverter +{ + public override StreamProtocol Read( + ref Utf8JsonReader reader, + System::Type typeToConvert, + JsonSerializerOptions options + ) + { + return JsonSerializer.Deserialize(ref reader, options) switch + { + "HLS" => StreamProtocol.Hls, + "DASH" => StreamProtocol.Dash, + _ => (StreamProtocol)(-1), + }; + } + + public override void Write( + Utf8JsonWriter writer, + StreamProtocol value, + JsonSerializerOptions options + ) + { + JsonSerializer.Serialize( + writer, + value switch + { + StreamProtocol.Hls => "HLS", + StreamProtocol.Dash => "DASH", + _ => throw new System::ArgumentOutOfRangeException(nameof(value)), + }, + options + ); + } +} diff --git a/src/Imagekit/Models/Webhooks/VideoTransformationReadyEventProperties/DataProperties/TransformationProperties/OptionsProperties/VideoCodec.cs b/src/Imagekit/Models/Webhooks/VideoTransformationReadyEventProperties/DataProperties/TransformationProperties/OptionsProperties/VideoCodec.cs new file mode 100644 index 00000000..0baacb16 --- /dev/null +++ b/src/Imagekit/Models/Webhooks/VideoTransformationReadyEventProperties/DataProperties/TransformationProperties/OptionsProperties/VideoCodec.cs @@ -0,0 +1,53 @@ +using System.Text.Json; +using System.Text.Json.Serialization; +using System = System; + +namespace Imagekit.Models.Webhooks.VideoTransformationReadyEventProperties.DataProperties.TransformationProperties.OptionsProperties; + +/// +/// Video codec used for encoding (h264, vp9, or av1). +/// +[JsonConverter(typeof(VideoCodecConverter))] +public enum VideoCodec +{ + H264, + Vp9, + Av1, +} + +sealed class VideoCodecConverter : JsonConverter +{ + public override VideoCodec Read( + ref Utf8JsonReader reader, + System::Type typeToConvert, + JsonSerializerOptions options + ) + { + return JsonSerializer.Deserialize(ref reader, options) switch + { + "h264" => VideoCodec.H264, + "vp9" => VideoCodec.Vp9, + "av1" => VideoCodec.Av1, + _ => (VideoCodec)(-1), + }; + } + + public override void Write( + Utf8JsonWriter writer, + VideoCodec value, + JsonSerializerOptions options + ) + { + JsonSerializer.Serialize( + writer, + value switch + { + VideoCodec.H264 => "h264", + VideoCodec.Vp9 => "vp9", + VideoCodec.Av1 => "av1", + _ => throw new System::ArgumentOutOfRangeException(nameof(value)), + }, + options + ); + } +} diff --git a/src/Imagekit/Models/Webhooks/VideoTransformationReadyEventProperties/DataProperties/TransformationProperties/Output.cs b/src/Imagekit/Models/Webhooks/VideoTransformationReadyEventProperties/DataProperties/TransformationProperties/Output.cs new file mode 100644 index 00000000..ddcbfa27 --- /dev/null +++ b/src/Imagekit/Models/Webhooks/VideoTransformationReadyEventProperties/DataProperties/TransformationProperties/Output.cs @@ -0,0 +1,86 @@ +using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; +using System.Text.Json; +using System.Text.Json.Serialization; +using Imagekit.Models.Webhooks.VideoTransformationReadyEventProperties.DataProperties.TransformationProperties.OutputProperties; +using System = System; + +namespace Imagekit.Models.Webhooks.VideoTransformationReadyEventProperties.DataProperties.TransformationProperties; + +/// +/// Information about the transformed output video. +/// +[JsonConverter(typeof(ModelConverter))] +public sealed record class Output : ModelBase, IFromRaw +{ + /// + /// URL to access the transformed video. + /// + public required string URL + { + get + { + if (!this.Properties.TryGetValue("url", out JsonElement element)) + throw new System::ArgumentOutOfRangeException("url", "Missing required argument"); + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions) + ?? throw new System::ArgumentNullException("url"); + } + set + { + this.Properties["url"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + /// + /// Metadata of the output video file. + /// + public VideoMetadata? VideoMetadata + { + get + { + if (!this.Properties.TryGetValue("video_metadata", out JsonElement element)) + return null; + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions); + } + set + { + this.Properties["video_metadata"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + public override void Validate() + { + _ = this.URL; + this.VideoMetadata?.Validate(); + } + + public Output() { } + +#pragma warning disable CS8618 + [SetsRequiredMembers] + Output(Dictionary properties) + { + Properties = properties; + } +#pragma warning restore CS8618 + + public static Output FromRawUnchecked(Dictionary properties) + { + return new(properties); + } + + [SetsRequiredMembers] + public Output(string url) + : this() + { + this.URL = url; + } +} diff --git a/src/Imagekit/Models/Webhooks/VideoTransformationReadyEventProperties/DataProperties/TransformationProperties/OutputProperties/VideoMetadata.cs b/src/Imagekit/Models/Webhooks/VideoTransformationReadyEventProperties/DataProperties/TransformationProperties/OutputProperties/VideoMetadata.cs new file mode 100644 index 00000000..60f5f015 --- /dev/null +++ b/src/Imagekit/Models/Webhooks/VideoTransformationReadyEventProperties/DataProperties/TransformationProperties/OutputProperties/VideoMetadata.cs @@ -0,0 +1,121 @@ +using System; +using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; +using System.Text.Json; +using System.Text.Json.Serialization; + +namespace Imagekit.Models.Webhooks.VideoTransformationReadyEventProperties.DataProperties.TransformationProperties.OutputProperties; + +/// +/// Metadata of the output video file. +/// +[JsonConverter(typeof(ModelConverter))] +public sealed record class VideoMetadata : ModelBase, IFromRaw +{ + /// + /// Bitrate of the output video in bits per second. + /// + public required long Bitrate + { + get + { + if (!this.Properties.TryGetValue("bitrate", out JsonElement element)) + throw new ArgumentOutOfRangeException("bitrate", "Missing required argument"); + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions); + } + set + { + this.Properties["bitrate"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + /// + /// Duration of the output video in seconds. + /// + public required double Duration + { + get + { + if (!this.Properties.TryGetValue("duration", out JsonElement element)) + throw new ArgumentOutOfRangeException("duration", "Missing required argument"); + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions); + } + set + { + this.Properties["duration"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + /// + /// Height of the output video in pixels. + /// + public required long Height + { + get + { + if (!this.Properties.TryGetValue("height", out JsonElement element)) + throw new ArgumentOutOfRangeException("height", "Missing required argument"); + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions); + } + set + { + this.Properties["height"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + /// + /// Width of the output video in pixels. + /// + public required long Width + { + get + { + if (!this.Properties.TryGetValue("width", out JsonElement element)) + throw new ArgumentOutOfRangeException("width", "Missing required argument"); + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions); + } + set + { + this.Properties["width"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + public override void Validate() + { + _ = this.Bitrate; + _ = this.Duration; + _ = this.Height; + _ = this.Width; + } + + public VideoMetadata() { } + +#pragma warning disable CS8618 + [SetsRequiredMembers] + VideoMetadata(Dictionary properties) + { + Properties = properties; + } +#pragma warning restore CS8618 + + public static VideoMetadata FromRawUnchecked(Dictionary properties) + { + return new(properties); + } +} diff --git a/src/Imagekit/Models/Webhooks/VideoTransformationReadyEventProperties/DataProperties/TransformationProperties/Type.cs b/src/Imagekit/Models/Webhooks/VideoTransformationReadyEventProperties/DataProperties/TransformationProperties/Type.cs new file mode 100644 index 00000000..dc9c5729 --- /dev/null +++ b/src/Imagekit/Models/Webhooks/VideoTransformationReadyEventProperties/DataProperties/TransformationProperties/Type.cs @@ -0,0 +1,51 @@ +using System.Text.Json; +using System.Text.Json.Serialization; +using System = System; + +namespace Imagekit.Models.Webhooks.VideoTransformationReadyEventProperties.DataProperties.TransformationProperties; + +/// +/// Type of video transformation: - `video-transformation`: Standard video processing +/// (resize, format conversion, etc.) - `gif-to-video`: Convert animated GIF to video +/// format - `video-thumbnail`: Generate thumbnail image from video +/// +[JsonConverter(typeof(TypeConverter))] +public enum Type +{ + VideoTransformation, + GifToVideo, + VideoThumbnail, +} + +sealed class TypeConverter : JsonConverter +{ + public override Type Read( + ref Utf8JsonReader reader, + System::Type typeToConvert, + JsonSerializerOptions options + ) + { + return JsonSerializer.Deserialize(ref reader, options) switch + { + "video-transformation" => TransformationProperties.Type.VideoTransformation, + "gif-to-video" => TransformationProperties.Type.GifToVideo, + "video-thumbnail" => TransformationProperties.Type.VideoThumbnail, + _ => (Type)(-1), + }; + } + + public override void Write(Utf8JsonWriter writer, Type value, JsonSerializerOptions options) + { + JsonSerializer.Serialize( + writer, + value switch + { + TransformationProperties.Type.VideoTransformation => "video-transformation", + TransformationProperties.Type.GifToVideo => "gif-to-video", + TransformationProperties.Type.VideoThumbnail => "video-thumbnail", + _ => throw new System::ArgumentOutOfRangeException(nameof(value)), + }, + options + ); + } +} diff --git a/src/Imagekit/Models/Webhooks/VideoTransformationReadyEventProperties/Request.cs b/src/Imagekit/Models/Webhooks/VideoTransformationReadyEventProperties/Request.cs new file mode 100644 index 00000000..2de96a55 --- /dev/null +++ b/src/Imagekit/Models/Webhooks/VideoTransformationReadyEventProperties/Request.cs @@ -0,0 +1,101 @@ +using System; +using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; +using System.Text.Json; +using System.Text.Json.Serialization; + +namespace Imagekit.Models.Webhooks.VideoTransformationReadyEventProperties; + +/// +/// Information about the original request that triggered the video transformation. +/// +[JsonConverter(typeof(ModelConverter))] +public sealed record class Request : ModelBase, IFromRaw +{ + /// + /// Full URL of the transformation request that was submitted. + /// + public required string URL + { + get + { + if (!this.Properties.TryGetValue("url", out JsonElement element)) + throw new ArgumentOutOfRangeException("url", "Missing required argument"); + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions) + ?? throw new ArgumentNullException("url"); + } + set + { + this.Properties["url"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + /// + /// Unique identifier for the originating transformation request. + /// + public required string XRequestID + { + get + { + if (!this.Properties.TryGetValue("x_request_id", out JsonElement element)) + throw new ArgumentOutOfRangeException("x_request_id", "Missing required argument"); + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions) + ?? throw new ArgumentNullException("x_request_id"); + } + set + { + this.Properties["x_request_id"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + /// + /// User-Agent header from the original request that triggered the transformation. + /// + public string? UserAgent + { + get + { + if (!this.Properties.TryGetValue("user_agent", out JsonElement element)) + return null; + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions); + } + set + { + this.Properties["user_agent"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + public override void Validate() + { + _ = this.URL; + _ = this.XRequestID; + _ = this.UserAgent; + } + + public Request() { } + +#pragma warning disable CS8618 + [SetsRequiredMembers] + Request(Dictionary properties) + { + Properties = properties; + } +#pragma warning restore CS8618 + + public static Request FromRawUnchecked(Dictionary properties) + { + return new(properties); + } +} diff --git a/src/Imagekit/Models/Webhooks/VideoTransformationReadyEventProperties/Timings.cs b/src/Imagekit/Models/Webhooks/VideoTransformationReadyEventProperties/Timings.cs new file mode 100644 index 00000000..3f5cedd3 --- /dev/null +++ b/src/Imagekit/Models/Webhooks/VideoTransformationReadyEventProperties/Timings.cs @@ -0,0 +1,77 @@ +using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; +using System.Text.Json; +using System.Text.Json.Serialization; + +namespace Imagekit.Models.Webhooks.VideoTransformationReadyEventProperties; + +/// +/// Performance metrics for the transformation process. +/// +[JsonConverter(typeof(ModelConverter))] +public sealed record class Timings : ModelBase, IFromRaw +{ + /// + /// Time spent downloading the source video from your origin or media library, + /// in milliseconds. + /// + public long? DownloadDuration + { + get + { + if (!this.Properties.TryGetValue("download_duration", out JsonElement element)) + return null; + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions); + } + set + { + this.Properties["download_duration"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + /// + /// Time spent encoding the video, in milliseconds. + /// + public long? EncodingDuration + { + get + { + if (!this.Properties.TryGetValue("encoding_duration", out JsonElement element)) + return null; + + return JsonSerializer.Deserialize(element, ModelBase.SerializerOptions); + } + set + { + this.Properties["encoding_duration"] = JsonSerializer.SerializeToElement( + value, + ModelBase.SerializerOptions + ); + } + } + + public override void Validate() + { + _ = this.DownloadDuration; + _ = this.EncodingDuration; + } + + public Timings() { } + +#pragma warning disable CS8618 + [SetsRequiredMembers] + Timings(Dictionary properties) + { + Properties = properties; + } +#pragma warning restore CS8618 + + public static Timings FromRawUnchecked(Dictionary properties) + { + return new(properties); + } +} diff --git a/src/Imagekit/ParamsBase.cs b/src/Imagekit/ParamsBase.cs new file mode 100644 index 00000000..2f20430a --- /dev/null +++ b/src/Imagekit/ParamsBase.cs @@ -0,0 +1,164 @@ +using System; +using System.Collections.Generic; +using System.Collections.Specialized; +using System.Linq; +using System.Net.Http; +using System.Text; +using System.Text.Json; +using Web = System.Web; + +namespace Imagekit; + +public abstract record class ParamsBase +{ + public Dictionary QueryProperties { get; set; } = []; + + public Dictionary HeaderProperties { get; set; } = []; + + public abstract Uri Url(IImageKitClient client); + + protected static void AddQueryElementToCollection( + NameValueCollection collection, + string key, + JsonElement element + ) + { + switch (element.ValueKind) + { + case JsonValueKind.Undefined: + case JsonValueKind.Null: + collection.Add(key, ""); + break; + case JsonValueKind.String: + case JsonValueKind.Number: + collection.Add(key, element.ToString()); + break; + case JsonValueKind.True: + collection.Add(key, "true"); + break; + case JsonValueKind.False: + collection.Add(key, "false"); + break; + case JsonValueKind.Object: + foreach (var item in element.EnumerateObject()) + { + AddQueryElementToCollection( + collection, + string.Format("{0}[{1}]", key, item.Name), + item.Value + ); + } + break; + case JsonValueKind.Array: + collection.Add( + key, + string.Join( + ",", + Enumerable.Select( + element.EnumerateArray(), + x => + x.ValueKind switch + { + JsonValueKind.Null => "", + JsonValueKind.True => "true", + JsonValueKind.False => "false", + _ => x.GetString(), + } + ) + ) + ); + break; + } + } + + protected static void AddHeaderElementToRequest( + HttpRequestMessage request, + string key, + JsonElement element + ) + { + switch (element.ValueKind) + { + case JsonValueKind.Undefined: + case JsonValueKind.Null: + request.Headers.Add(key, ""); + break; + case JsonValueKind.String: + case JsonValueKind.Number: + request.Headers.Add(key, element.ToString()); + break; + case JsonValueKind.True: + request.Headers.Add(key, "true"); + break; + case JsonValueKind.False: + request.Headers.Add(key, "false"); + break; + case JsonValueKind.Object: + foreach (var item in element.EnumerateObject()) + { + AddHeaderElementToRequest( + request, + string.Format("{0}.{1}", key, item.Name), + item.Value + ); + } + break; + case JsonValueKind.Array: + foreach (var item in element.EnumerateArray()) + { + request.Headers.Add( + key, + item.ValueKind switch + { + JsonValueKind.Null => "", + JsonValueKind.True => "true", + JsonValueKind.False => "false", + _ => item.GetString(), + } + ); + } + break; + } + } + + protected string QueryString(IImageKitClient client) + { + NameValueCollection collection = []; + foreach (var item in this.QueryProperties) + { + ParamsBase.AddQueryElementToCollection(collection, item.Key, item.Value); + } + StringBuilder sb = new(); + bool first = true; + foreach (var key in collection.AllKeys) + { + foreach (var value in collection.GetValues(key) ?? []) + { + if (!first) + { + sb.Append('&'); + } + first = false; + sb.Append(Web::HttpUtility.UrlEncode(key)); + sb.Append('='); + sb.Append(Web::HttpUtility.UrlEncode(value)); + } + } + return sb.ToString(); + } + + protected static void AddDefaultHeaders(HttpRequestMessage request, IImageKitClient client) + { + request.Headers.Add( + "Authorization", + string.Format( + "Basic {0}", + Convert.ToBase64String( + Encoding + .GetEncoding("ISO-8859-1") + .GetBytes(string.Format("{0}:{1}", client.PrivateAPIKey, client.Password)) + ) + ) + ); + } +} diff --git a/src/Imagekit/Services/Accounts/AccountService.cs b/src/Imagekit/Services/Accounts/AccountService.cs new file mode 100644 index 00000000..b50326fe --- /dev/null +++ b/src/Imagekit/Services/Accounts/AccountService.cs @@ -0,0 +1,34 @@ +using System; +using Imagekit.Services.Accounts.Origins; +using Imagekit.Services.Accounts.URLEndpoints; +using Imagekit.Services.Accounts.Usage; + +namespace Imagekit.Services.Accounts; + +public sealed class AccountService : IAccountService +{ + public AccountService(IImageKitClient client) + { + _usage = new(() => new UsageService(client)); + _origins = new(() => new OriginService(client)); + _urlEndpoints = new(() => new URLEndpointService(client)); + } + + readonly Lazy _usage; + public IUsageService Usage + { + get { return _usage.Value; } + } + + readonly Lazy _origins; + public IOriginService Origins + { + get { return _origins.Value; } + } + + readonly Lazy _urlEndpoints; + public IURLEndpointService URLEndpoints + { + get { return _urlEndpoints.Value; } + } +} diff --git a/src/Imagekit/Services/Accounts/IAccountService.cs b/src/Imagekit/Services/Accounts/IAccountService.cs new file mode 100644 index 00000000..918c2e42 --- /dev/null +++ b/src/Imagekit/Services/Accounts/IAccountService.cs @@ -0,0 +1,14 @@ +using Imagekit.Services.Accounts.Origins; +using Imagekit.Services.Accounts.URLEndpoints; +using Imagekit.Services.Accounts.Usage; + +namespace Imagekit.Services.Accounts; + +public interface IAccountService +{ + IUsageService Usage { get; } + + IOriginService Origins { get; } + + IURLEndpointService URLEndpoints { get; } +} diff --git a/src/Imagekit/Services/Accounts/Origins/IOriginService.cs b/src/Imagekit/Services/Accounts/Origins/IOriginService.cs new file mode 100644 index 00000000..4882a4b8 --- /dev/null +++ b/src/Imagekit/Services/Accounts/Origins/IOriginService.cs @@ -0,0 +1,39 @@ +using System.Collections.Generic; +using System.Threading.Tasks; +using Imagekit.Models.Accounts.Origins; + +namespace Imagekit.Services.Accounts.Origins; + +public interface IOriginService +{ + /// + /// **Note:** This API is currently in beta. Creates a new origin and returns + /// the origin object. + /// + Task Create(OriginCreateParams parameters); + + /// + /// **Note:** This API is currently in beta. Updates the origin identified + /// by `id` and returns the updated origin object. + /// + Task Update(OriginUpdateParams parameters); + + /// + /// **Note:** This API is currently in beta. Returns an array of all configured + /// origins for the current account. + /// + Task> List(OriginListParams? parameters = null); + + /// + /// **Note:** This API is currently in beta. Permanently removes the origin + /// identified by `id`. If the origin is in use by any URL‑endpoints, the API + /// will return an error. + /// + Task Delete(OriginDeleteParams parameters); + + /// + /// **Note:** This API is currently in beta. Retrieves the origin identified + /// by `id`. + /// + Task Get(OriginGetParams parameters); +} diff --git a/src/Imagekit/Services/Accounts/Origins/OriginService.cs b/src/Imagekit/Services/Accounts/Origins/OriginService.cs new file mode 100644 index 00000000..336b1f97 --- /dev/null +++ b/src/Imagekit/Services/Accounts/Origins/OriginService.cs @@ -0,0 +1,126 @@ +using System; +using System.Collections.Generic; +using System.Net.Http; +using System.Text.Json; +using System.Threading.Tasks; +using Imagekit.Models.Accounts.Origins; + +namespace Imagekit.Services.Accounts.Origins; + +public sealed class OriginService : IOriginService +{ + readonly IImageKitClient _client; + + public OriginService(IImageKitClient client) + { + _client = client; + } + + public async Task Create(OriginCreateParams parameters) + { + using HttpRequestMessage request = new(HttpMethod.Post, parameters.Url(this._client)) + { + Content = parameters.BodyContent(), + }; + parameters.AddHeadersToRequest(request, this._client); + using HttpResponseMessage response = await this + ._client.HttpClient.SendAsync(request, HttpCompletionOption.ResponseHeadersRead) + .ConfigureAwait(false); + if (!response.IsSuccessStatusCode) + { + throw new HttpException( + response.StatusCode, + await response.Content.ReadAsStringAsync().ConfigureAwait(false) + ); + } + + return JsonSerializer.Deserialize( + await response.Content.ReadAsStreamAsync().ConfigureAwait(false), + ModelBase.SerializerOptions + ) ?? throw new NullReferenceException(); + } + + public async Task Update(OriginUpdateParams parameters) + { + using HttpRequestMessage request = new(HttpMethod.Put, parameters.Url(this._client)) + { + Content = parameters.BodyContent(), + }; + parameters.AddHeadersToRequest(request, this._client); + using HttpResponseMessage response = await this + ._client.HttpClient.SendAsync(request, HttpCompletionOption.ResponseHeadersRead) + .ConfigureAwait(false); + if (!response.IsSuccessStatusCode) + { + throw new HttpException( + response.StatusCode, + await response.Content.ReadAsStringAsync().ConfigureAwait(false) + ); + } + + return JsonSerializer.Deserialize( + await response.Content.ReadAsStreamAsync().ConfigureAwait(false), + ModelBase.SerializerOptions + ) ?? throw new NullReferenceException(); + } + + public async Task> List(OriginListParams? parameters = null) + { + parameters ??= new(); + + using HttpRequestMessage request = new(HttpMethod.Get, parameters.Url(this._client)); + parameters.AddHeadersToRequest(request, this._client); + using HttpResponseMessage response = await this + ._client.HttpClient.SendAsync(request, HttpCompletionOption.ResponseHeadersRead) + .ConfigureAwait(false); + if (!response.IsSuccessStatusCode) + { + throw new HttpException( + response.StatusCode, + await response.Content.ReadAsStringAsync().ConfigureAwait(false) + ); + } + + return JsonSerializer.Deserialize>( + await response.Content.ReadAsStreamAsync().ConfigureAwait(false), + ModelBase.SerializerOptions + ) ?? throw new NullReferenceException(); + } + + public async Task Delete(OriginDeleteParams parameters) + { + using HttpRequestMessage request = new(HttpMethod.Delete, parameters.Url(this._client)); + parameters.AddHeadersToRequest(request, this._client); + using HttpResponseMessage response = await this + ._client.HttpClient.SendAsync(request, HttpCompletionOption.ResponseHeadersRead) + .ConfigureAwait(false); + if (!response.IsSuccessStatusCode) + { + throw new HttpException( + response.StatusCode, + await response.Content.ReadAsStringAsync().ConfigureAwait(false) + ); + } + } + + public async Task Get(OriginGetParams parameters) + { + using HttpRequestMessage request = new(HttpMethod.Get, parameters.Url(this._client)); + parameters.AddHeadersToRequest(request, this._client); + using HttpResponseMessage response = await this + ._client.HttpClient.SendAsync(request, HttpCompletionOption.ResponseHeadersRead) + .ConfigureAwait(false); + if (!response.IsSuccessStatusCode) + { + throw new HttpException( + response.StatusCode, + await response.Content.ReadAsStringAsync().ConfigureAwait(false) + ); + } + + return JsonSerializer.Deserialize( + await response.Content.ReadAsStreamAsync().ConfigureAwait(false), + ModelBase.SerializerOptions + ) ?? throw new NullReferenceException(); + } +} diff --git a/src/Imagekit/Services/Accounts/URLEndpoints/IURLEndpointService.cs b/src/Imagekit/Services/Accounts/URLEndpoints/IURLEndpointService.cs new file mode 100644 index 00000000..dbf0dd4c --- /dev/null +++ b/src/Imagekit/Services/Accounts/URLEndpoints/IURLEndpointService.cs @@ -0,0 +1,40 @@ +using System.Collections.Generic; +using System.Threading.Tasks; +using Imagekit.Models.Accounts.URLEndpoints; + +namespace Imagekit.Services.Accounts.URLEndpoints; + +public interface IURLEndpointService +{ + /// + /// **Note:** This API is currently in beta. Creates a new URL‑endpoint and + /// returns the resulting object. + /// + Task Create(URLEndpointCreateParams parameters); + + /// + /// **Note:** This API is currently in beta. Updates the URL‑endpoint identified + /// by `id` and returns the updated object. + /// + Task Update(URLEndpointUpdateParams parameters); + + /// + /// **Note:** This API is currently in beta. Returns an array of all URL‑endpoints + /// configured including the default URL-endpoint generated by ImageKit during + /// account creation. + /// + Task> List(URLEndpointListParams? parameters = null); + + /// + /// **Note:** This API is currently in beta. Deletes the URL‑endpoint identified + /// by `id`. You cannot delete the default URL‑endpoint created by ImageKit during + /// account creation. + /// + Task Delete(URLEndpointDeleteParams parameters); + + /// + /// **Note:** This API is currently in beta. Retrieves the URL‑endpoint identified + /// by `id`. + /// + Task Get(URLEndpointGetParams parameters); +} diff --git a/src/Imagekit/Services/Accounts/URLEndpoints/URLEndpointService.cs b/src/Imagekit/Services/Accounts/URLEndpoints/URLEndpointService.cs new file mode 100644 index 00000000..319410cb --- /dev/null +++ b/src/Imagekit/Services/Accounts/URLEndpoints/URLEndpointService.cs @@ -0,0 +1,126 @@ +using System; +using System.Collections.Generic; +using System.Net.Http; +using System.Text.Json; +using System.Threading.Tasks; +using Imagekit.Models.Accounts.URLEndpoints; + +namespace Imagekit.Services.Accounts.URLEndpoints; + +public sealed class URLEndpointService : IURLEndpointService +{ + readonly IImageKitClient _client; + + public URLEndpointService(IImageKitClient client) + { + _client = client; + } + + public async Task Create(URLEndpointCreateParams parameters) + { + using HttpRequestMessage request = new(HttpMethod.Post, parameters.Url(this._client)) + { + Content = parameters.BodyContent(), + }; + parameters.AddHeadersToRequest(request, this._client); + using HttpResponseMessage response = await this + ._client.HttpClient.SendAsync(request, HttpCompletionOption.ResponseHeadersRead) + .ConfigureAwait(false); + if (!response.IsSuccessStatusCode) + { + throw new HttpException( + response.StatusCode, + await response.Content.ReadAsStringAsync().ConfigureAwait(false) + ); + } + + return JsonSerializer.Deserialize( + await response.Content.ReadAsStreamAsync().ConfigureAwait(false), + ModelBase.SerializerOptions + ) ?? throw new NullReferenceException(); + } + + public async Task Update(URLEndpointUpdateParams parameters) + { + using HttpRequestMessage request = new(HttpMethod.Put, parameters.Url(this._client)) + { + Content = parameters.BodyContent(), + }; + parameters.AddHeadersToRequest(request, this._client); + using HttpResponseMessage response = await this + ._client.HttpClient.SendAsync(request, HttpCompletionOption.ResponseHeadersRead) + .ConfigureAwait(false); + if (!response.IsSuccessStatusCode) + { + throw new HttpException( + response.StatusCode, + await response.Content.ReadAsStringAsync().ConfigureAwait(false) + ); + } + + return JsonSerializer.Deserialize( + await response.Content.ReadAsStreamAsync().ConfigureAwait(false), + ModelBase.SerializerOptions + ) ?? throw new NullReferenceException(); + } + + public async Task> List(URLEndpointListParams? parameters = null) + { + parameters ??= new(); + + using HttpRequestMessage request = new(HttpMethod.Get, parameters.Url(this._client)); + parameters.AddHeadersToRequest(request, this._client); + using HttpResponseMessage response = await this + ._client.HttpClient.SendAsync(request, HttpCompletionOption.ResponseHeadersRead) + .ConfigureAwait(false); + if (!response.IsSuccessStatusCode) + { + throw new HttpException( + response.StatusCode, + await response.Content.ReadAsStringAsync().ConfigureAwait(false) + ); + } + + return JsonSerializer.Deserialize>( + await response.Content.ReadAsStreamAsync().ConfigureAwait(false), + ModelBase.SerializerOptions + ) ?? throw new NullReferenceException(); + } + + public async Task Delete(URLEndpointDeleteParams parameters) + { + using HttpRequestMessage request = new(HttpMethod.Delete, parameters.Url(this._client)); + parameters.AddHeadersToRequest(request, this._client); + using HttpResponseMessage response = await this + ._client.HttpClient.SendAsync(request, HttpCompletionOption.ResponseHeadersRead) + .ConfigureAwait(false); + if (!response.IsSuccessStatusCode) + { + throw new HttpException( + response.StatusCode, + await response.Content.ReadAsStringAsync().ConfigureAwait(false) + ); + } + } + + public async Task Get(URLEndpointGetParams parameters) + { + using HttpRequestMessage request = new(HttpMethod.Get, parameters.Url(this._client)); + parameters.AddHeadersToRequest(request, this._client); + using HttpResponseMessage response = await this + ._client.HttpClient.SendAsync(request, HttpCompletionOption.ResponseHeadersRead) + .ConfigureAwait(false); + if (!response.IsSuccessStatusCode) + { + throw new HttpException( + response.StatusCode, + await response.Content.ReadAsStringAsync().ConfigureAwait(false) + ); + } + + return JsonSerializer.Deserialize( + await response.Content.ReadAsStreamAsync().ConfigureAwait(false), + ModelBase.SerializerOptions + ) ?? throw new NullReferenceException(); + } +} diff --git a/src/Imagekit/Services/Accounts/Usage/IUsageService.cs b/src/Imagekit/Services/Accounts/Usage/IUsageService.cs new file mode 100644 index 00000000..ce3d7bec --- /dev/null +++ b/src/Imagekit/Services/Accounts/Usage/IUsageService.cs @@ -0,0 +1,15 @@ +using System.Threading.Tasks; +using Imagekit.Models.Accounts.Usage; + +namespace Imagekit.Services.Accounts.Usage; + +public interface IUsageService +{ + /// + /// Get the account usage information between two dates. Note that the API response + /// includes data from the start date while excluding data from the end date. + /// In other words, the data covers the period starting from the specified start + /// date up to, but not including, the end date. + /// + Task Get(UsageGetParams parameters); +} diff --git a/src/Imagekit/Services/Accounts/Usage/UsageService.cs b/src/Imagekit/Services/Accounts/Usage/UsageService.cs new file mode 100644 index 00000000..7e95271c --- /dev/null +++ b/src/Imagekit/Services/Accounts/Usage/UsageService.cs @@ -0,0 +1,38 @@ +using System; +using System.Net.Http; +using System.Text.Json; +using System.Threading.Tasks; +using Imagekit.Models.Accounts.Usage; + +namespace Imagekit.Services.Accounts.Usage; + +public sealed class UsageService : IUsageService +{ + readonly IImageKitClient _client; + + public UsageService(IImageKitClient client) + { + _client = client; + } + + public async Task Get(UsageGetParams parameters) + { + using HttpRequestMessage request = new(HttpMethod.Get, parameters.Url(this._client)); + parameters.AddHeadersToRequest(request, this._client); + using HttpResponseMessage response = await this + ._client.HttpClient.SendAsync(request, HttpCompletionOption.ResponseHeadersRead) + .ConfigureAwait(false); + if (!response.IsSuccessStatusCode) + { + throw new HttpException( + response.StatusCode, + await response.Content.ReadAsStringAsync().ConfigureAwait(false) + ); + } + + return JsonSerializer.Deserialize( + await response.Content.ReadAsStreamAsync().ConfigureAwait(false), + ModelBase.SerializerOptions + ) ?? throw new NullReferenceException(); + } +} diff --git a/src/Imagekit/Services/Assets/AssetService.cs b/src/Imagekit/Services/Assets/AssetService.cs new file mode 100644 index 00000000..7f54faac --- /dev/null +++ b/src/Imagekit/Services/Assets/AssetService.cs @@ -0,0 +1,41 @@ +using System; +using System.Collections.Generic; +using System.Net.Http; +using System.Text.Json; +using System.Threading.Tasks; +using Imagekit.Models.Assets; + +namespace Imagekit.Services.Assets; + +public sealed class AssetService : IAssetService +{ + readonly IImageKitClient _client; + + public AssetService(IImageKitClient client) + { + _client = client; + } + + public async Task> List(AssetListParams? parameters = null) + { + parameters ??= new(); + + using HttpRequestMessage request = new(HttpMethod.Get, parameters.Url(this._client)); + parameters.AddHeadersToRequest(request, this._client); + using HttpResponseMessage response = await this + ._client.HttpClient.SendAsync(request, HttpCompletionOption.ResponseHeadersRead) + .ConfigureAwait(false); + if (!response.IsSuccessStatusCode) + { + throw new HttpException( + response.StatusCode, + await response.Content.ReadAsStringAsync().ConfigureAwait(false) + ); + } + + return JsonSerializer.Deserialize>( + await response.Content.ReadAsStreamAsync().ConfigureAwait(false), + ModelBase.SerializerOptions + ) ?? throw new NullReferenceException(); + } +} diff --git a/src/Imagekit/Services/Assets/IAssetService.cs b/src/Imagekit/Services/Assets/IAssetService.cs new file mode 100644 index 00000000..0ee9f37c --- /dev/null +++ b/src/Imagekit/Services/Assets/IAssetService.cs @@ -0,0 +1,16 @@ +using System.Collections.Generic; +using System.Threading.Tasks; +using Imagekit.Models.Assets; + +namespace Imagekit.Services.Assets; + +public interface IAssetService +{ + /// + /// This API can list all the uploaded files and folders in your ImageKit.io + /// media library. In addition, you can fine-tune your query by specifying various + /// filters by generating a query string in a Lucene-like syntax and provide + /// this generated string as the value of the `searchQuery`. + /// + Task> List(AssetListParams? parameters = null); +} diff --git a/src/Imagekit/Services/Beta/BetaService.cs b/src/Imagekit/Services/Beta/BetaService.cs new file mode 100644 index 00000000..b6c9e2a1 --- /dev/null +++ b/src/Imagekit/Services/Beta/BetaService.cs @@ -0,0 +1,18 @@ +using System; +using Imagekit.Services.Beta.V2; + +namespace Imagekit.Services.Beta; + +public sealed class BetaService : IBetaService +{ + public BetaService(IImageKitClient client) + { + _v2 = new(() => new V2Service(client)); + } + + readonly Lazy _v2; + public IV2Service V2 + { + get { return _v2.Value; } + } +} diff --git a/src/Imagekit/Services/Beta/IBetaService.cs b/src/Imagekit/Services/Beta/IBetaService.cs new file mode 100644 index 00000000..65bd9f62 --- /dev/null +++ b/src/Imagekit/Services/Beta/IBetaService.cs @@ -0,0 +1,8 @@ +using Imagekit.Services.Beta.V2; + +namespace Imagekit.Services.Beta; + +public interface IBetaService +{ + IV2Service V2 { get; } +} diff --git a/src/Imagekit/Services/Beta/V2/Files/FileService.cs b/src/Imagekit/Services/Beta/V2/Files/FileService.cs new file mode 100644 index 00000000..cdc7fef3 --- /dev/null +++ b/src/Imagekit/Services/Beta/V2/Files/FileService.cs @@ -0,0 +1,41 @@ +using System; +using System.Net.Http; +using System.Text.Json; +using System.Threading.Tasks; +using Imagekit.Models.Beta.V2.Files; + +namespace Imagekit.Services.Beta.V2.Files; + +public sealed class FileService : IFileService +{ + readonly IImageKitClient _client; + + public FileService(IImageKitClient client) + { + _client = client; + } + + public async Task Upload(FileUploadParams parameters) + { + using HttpRequestMessage request = new(HttpMethod.Post, parameters.Url(this._client)) + { + Content = parameters.BodyContent(), + }; + parameters.AddHeadersToRequest(request, this._client); + using HttpResponseMessage response = await this + ._client.HttpClient.SendAsync(request, HttpCompletionOption.ResponseHeadersRead) + .ConfigureAwait(false); + if (!response.IsSuccessStatusCode) + { + throw new HttpException( + response.StatusCode, + await response.Content.ReadAsStringAsync().ConfigureAwait(false) + ); + } + + return JsonSerializer.Deserialize( + await response.Content.ReadAsStreamAsync().ConfigureAwait(false), + ModelBase.SerializerOptions + ) ?? throw new NullReferenceException(); + } +} diff --git a/src/Imagekit/Services/Beta/V2/Files/IFileService.cs b/src/Imagekit/Services/Beta/V2/Files/IFileService.cs new file mode 100644 index 00000000..7e4a65f2 --- /dev/null +++ b/src/Imagekit/Services/Beta/V2/Files/IFileService.cs @@ -0,0 +1,33 @@ +using System.Threading.Tasks; +using Imagekit.Models.Beta.V2.Files; + +namespace Imagekit.Services.Beta.V2.Files; + +public interface IFileService +{ + /// + /// The V2 API enhances security by verifying the entire payload using JWT. This + /// API is in beta. + /// + /// ImageKit.io allows you to upload files directly from both the server and client + /// sides. For server-side uploads, private API key authentication is used. For + /// client-side uploads, generate a one-time `token` from your secure backend + /// using private API. [Learn more](/docs/api-reference/upload-file/upload-file-v2#how-to-implement-secure-client-side-file-upload) + /// about how to implement secure client-side file upload. + /// + /// **File size limit** \ On the free plan, the maximum upload file sizes are + /// 20MB for images, audio, and raw files, and 100MB for videos. On the paid plan, + /// these limits increase to 40MB for images, audio, and raw files, and 2GB for + /// videos. These limits can be further increased with higher-tier plans. + /// + /// **Version limit** \ A file can have a maximum of 100 versions. + /// + /// **Demo applications** + /// + /// - A full-fledged [upload widget using Uppy](https://github.com/imagekit-samples/uppy-uploader), + /// supporting file selections from local storage, URL, Dropbox, Google Drive, + /// Instagram, and more. - [Quick start guides](/docs/quick-start-guides) for + /// various frameworks and technologies. + /// + Task Upload(FileUploadParams parameters); +} diff --git a/src/Imagekit/Services/Beta/V2/IV2Service.cs b/src/Imagekit/Services/Beta/V2/IV2Service.cs new file mode 100644 index 00000000..13609839 --- /dev/null +++ b/src/Imagekit/Services/Beta/V2/IV2Service.cs @@ -0,0 +1,8 @@ +using Imagekit.Services.Beta.V2.Files; + +namespace Imagekit.Services.Beta.V2; + +public interface IV2Service +{ + IFileService Files { get; } +} diff --git a/src/Imagekit/Services/Beta/V2/V2Service.cs b/src/Imagekit/Services/Beta/V2/V2Service.cs new file mode 100644 index 00000000..e966651e --- /dev/null +++ b/src/Imagekit/Services/Beta/V2/V2Service.cs @@ -0,0 +1,18 @@ +using System; +using Imagekit.Services.Beta.V2.Files; + +namespace Imagekit.Services.Beta.V2; + +public sealed class V2Service : IV2Service +{ + public V2Service(IImageKitClient client) + { + _files = new(() => new FileService(client)); + } + + readonly Lazy _files; + public IFileService Files + { + get { return _files.Value; } + } +} diff --git a/src/Imagekit/Services/Cache/CacheService.cs b/src/Imagekit/Services/Cache/CacheService.cs new file mode 100644 index 00000000..35ad5f64 --- /dev/null +++ b/src/Imagekit/Services/Cache/CacheService.cs @@ -0,0 +1,18 @@ +using System; +using Imagekit.Services.Cache.Invalidation; + +namespace Imagekit.Services.Cache; + +public sealed class CacheService : ICacheService +{ + public CacheService(IImageKitClient client) + { + _invalidation = new(() => new InvalidationService(client)); + } + + readonly Lazy _invalidation; + public IInvalidationService Invalidation + { + get { return _invalidation.Value; } + } +} diff --git a/src/Imagekit/Services/Cache/ICacheService.cs b/src/Imagekit/Services/Cache/ICacheService.cs new file mode 100644 index 00000000..91882a67 --- /dev/null +++ b/src/Imagekit/Services/Cache/ICacheService.cs @@ -0,0 +1,8 @@ +using Imagekit.Services.Cache.Invalidation; + +namespace Imagekit.Services.Cache; + +public interface ICacheService +{ + IInvalidationService Invalidation { get; } +} diff --git a/src/Imagekit/Services/Cache/Invalidation/IInvalidationService.cs b/src/Imagekit/Services/Cache/Invalidation/IInvalidationService.cs new file mode 100644 index 00000000..1c2a20a6 --- /dev/null +++ b/src/Imagekit/Services/Cache/Invalidation/IInvalidationService.cs @@ -0,0 +1,19 @@ +using System.Threading.Tasks; +using Imagekit.Models.Cache.Invalidation; + +namespace Imagekit.Services.Cache.Invalidation; + +public interface IInvalidationService +{ + /// + /// This API will purge CDN cache and ImageKit.io's internal cache for a file. + /// Note: Purge cache is an asynchronous process and it may take some time to + /// reflect the changes. + /// + Task Create(InvalidationCreateParams parameters); + + /// + /// This API returns the status of a purge cache request. + /// + Task Get(InvalidationGetParams parameters); +} diff --git a/src/Imagekit/Services/Cache/Invalidation/InvalidationService.cs b/src/Imagekit/Services/Cache/Invalidation/InvalidationService.cs new file mode 100644 index 00000000..2513605a --- /dev/null +++ b/src/Imagekit/Services/Cache/Invalidation/InvalidationService.cs @@ -0,0 +1,62 @@ +using System; +using System.Net.Http; +using System.Text.Json; +using System.Threading.Tasks; +using Imagekit.Models.Cache.Invalidation; + +namespace Imagekit.Services.Cache.Invalidation; + +public sealed class InvalidationService : IInvalidationService +{ + readonly IImageKitClient _client; + + public InvalidationService(IImageKitClient client) + { + _client = client; + } + + public async Task Create(InvalidationCreateParams parameters) + { + using HttpRequestMessage request = new(HttpMethod.Post, parameters.Url(this._client)) + { + Content = parameters.BodyContent(), + }; + parameters.AddHeadersToRequest(request, this._client); + using HttpResponseMessage response = await this + ._client.HttpClient.SendAsync(request, HttpCompletionOption.ResponseHeadersRead) + .ConfigureAwait(false); + if (!response.IsSuccessStatusCode) + { + throw new HttpException( + response.StatusCode, + await response.Content.ReadAsStringAsync().ConfigureAwait(false) + ); + } + + return JsonSerializer.Deserialize( + await response.Content.ReadAsStreamAsync().ConfigureAwait(false), + ModelBase.SerializerOptions + ) ?? throw new NullReferenceException(); + } + + public async Task Get(InvalidationGetParams parameters) + { + using HttpRequestMessage request = new(HttpMethod.Get, parameters.Url(this._client)); + parameters.AddHeadersToRequest(request, this._client); + using HttpResponseMessage response = await this + ._client.HttpClient.SendAsync(request, HttpCompletionOption.ResponseHeadersRead) + .ConfigureAwait(false); + if (!response.IsSuccessStatusCode) + { + throw new HttpException( + response.StatusCode, + await response.Content.ReadAsStringAsync().ConfigureAwait(false) + ); + } + + return JsonSerializer.Deserialize( + await response.Content.ReadAsStreamAsync().ConfigureAwait(false), + ModelBase.SerializerOptions + ) ?? throw new NullReferenceException(); + } +} diff --git a/src/Imagekit/Services/CustomMetadataFields/CustomMetadataFieldService.cs b/src/Imagekit/Services/CustomMetadataFields/CustomMetadataFieldService.cs new file mode 100644 index 00000000..b293386d --- /dev/null +++ b/src/Imagekit/Services/CustomMetadataFields/CustomMetadataFieldService.cs @@ -0,0 +1,114 @@ +using System; +using System.Collections.Generic; +using System.Net.Http; +using System.Text.Json; +using System.Threading.Tasks; +using Imagekit.Models.CustomMetadataFields; + +namespace Imagekit.Services.CustomMetadataFields; + +public sealed class CustomMetadataFieldService : ICustomMetadataFieldService +{ + readonly IImageKitClient _client; + + public CustomMetadataFieldService(IImageKitClient client) + { + _client = client; + } + + public async Task Create(CustomMetadataFieldCreateParams parameters) + { + using HttpRequestMessage request = new(HttpMethod.Post, parameters.Url(this._client)) + { + Content = parameters.BodyContent(), + }; + parameters.AddHeadersToRequest(request, this._client); + using HttpResponseMessage response = await this + ._client.HttpClient.SendAsync(request, HttpCompletionOption.ResponseHeadersRead) + .ConfigureAwait(false); + if (!response.IsSuccessStatusCode) + { + throw new HttpException( + response.StatusCode, + await response.Content.ReadAsStringAsync().ConfigureAwait(false) + ); + } + + return JsonSerializer.Deserialize( + await response.Content.ReadAsStreamAsync().ConfigureAwait(false), + ModelBase.SerializerOptions + ) ?? throw new NullReferenceException(); + } + + public async Task Update(CustomMetadataFieldUpdateParams parameters) + { + using HttpRequestMessage request = new(HttpMethod.Patch, parameters.Url(this._client)) + { + Content = parameters.BodyContent(), + }; + parameters.AddHeadersToRequest(request, this._client); + using HttpResponseMessage response = await this + ._client.HttpClient.SendAsync(request, HttpCompletionOption.ResponseHeadersRead) + .ConfigureAwait(false); + if (!response.IsSuccessStatusCode) + { + throw new HttpException( + response.StatusCode, + await response.Content.ReadAsStringAsync().ConfigureAwait(false) + ); + } + + return JsonSerializer.Deserialize( + await response.Content.ReadAsStreamAsync().ConfigureAwait(false), + ModelBase.SerializerOptions + ) ?? throw new NullReferenceException(); + } + + public async Task> List( + CustomMetadataFieldListParams? parameters = null + ) + { + parameters ??= new(); + + using HttpRequestMessage request = new(HttpMethod.Get, parameters.Url(this._client)); + parameters.AddHeadersToRequest(request, this._client); + using HttpResponseMessage response = await this + ._client.HttpClient.SendAsync(request, HttpCompletionOption.ResponseHeadersRead) + .ConfigureAwait(false); + if (!response.IsSuccessStatusCode) + { + throw new HttpException( + response.StatusCode, + await response.Content.ReadAsStringAsync().ConfigureAwait(false) + ); + } + + return JsonSerializer.Deserialize>( + await response.Content.ReadAsStreamAsync().ConfigureAwait(false), + ModelBase.SerializerOptions + ) ?? throw new NullReferenceException(); + } + + public async Task Delete( + CustomMetadataFieldDeleteParams parameters + ) + { + using HttpRequestMessage request = new(HttpMethod.Delete, parameters.Url(this._client)); + parameters.AddHeadersToRequest(request, this._client); + using HttpResponseMessage response = await this + ._client.HttpClient.SendAsync(request, HttpCompletionOption.ResponseHeadersRead) + .ConfigureAwait(false); + if (!response.IsSuccessStatusCode) + { + throw new HttpException( + response.StatusCode, + await response.Content.ReadAsStringAsync().ConfigureAwait(false) + ); + } + + return JsonSerializer.Deserialize( + await response.Content.ReadAsStreamAsync().ConfigureAwait(false), + ModelBase.SerializerOptions + ) ?? throw new NullReferenceException(); + } +} diff --git a/src/Imagekit/Services/CustomMetadataFields/ICustomMetadataFieldService.cs b/src/Imagekit/Services/CustomMetadataFields/ICustomMetadataFieldService.cs new file mode 100644 index 00000000..1661789f --- /dev/null +++ b/src/Imagekit/Services/CustomMetadataFields/ICustomMetadataFieldService.cs @@ -0,0 +1,34 @@ +using System.Collections.Generic; +using System.Threading.Tasks; +using Imagekit.Models.CustomMetadataFields; + +namespace Imagekit.Services.CustomMetadataFields; + +public interface ICustomMetadataFieldService +{ + /// + /// This API creates a new custom metadata field. Once a custom metadata field + /// is created either through this API or using the dashboard UI, its value can + /// be set on the assets. The value of a field for an asset can be set using the + /// media library UI or programmatically through upload or update assets API. + /// + Task Create(CustomMetadataFieldCreateParams parameters); + + /// + /// This API updates the label or schema of an existing custom metadata field. + /// + Task Update(CustomMetadataFieldUpdateParams parameters); + + /// + /// This API returns the array of created custom metadata field objects. By default + /// the API returns only non deleted field objects, but you can include deleted + /// fields in the API response. + /// + Task> List(CustomMetadataFieldListParams? parameters = null); + + /// + /// This API deletes a custom metadata field. Even after deleting a custom metadata + /// field, you cannot create any new custom metadata field with the same name. + /// + Task Delete(CustomMetadataFieldDeleteParams parameters); +} diff --git a/src/Imagekit/Services/Files/Bulk/BulkService.cs b/src/Imagekit/Services/Files/Bulk/BulkService.cs new file mode 100644 index 00000000..a10d960d --- /dev/null +++ b/src/Imagekit/Services/Files/Bulk/BulkService.cs @@ -0,0 +1,113 @@ +using System; +using System.Net.Http; +using System.Text.Json; +using System.Threading.Tasks; +using Imagekit.Models.Files.Bulk; + +namespace Imagekit.Services.Files.Bulk; + +public sealed class BulkService : IBulkService +{ + readonly IImageKitClient _client; + + public BulkService(IImageKitClient client) + { + _client = client; + } + + public async Task Delete(BulkDeleteParams parameters) + { + using HttpRequestMessage request = new(HttpMethod.Post, parameters.Url(this._client)) + { + Content = parameters.BodyContent(), + }; + parameters.AddHeadersToRequest(request, this._client); + using HttpResponseMessage response = await this + ._client.HttpClient.SendAsync(request, HttpCompletionOption.ResponseHeadersRead) + .ConfigureAwait(false); + if (!response.IsSuccessStatusCode) + { + throw new HttpException( + response.StatusCode, + await response.Content.ReadAsStringAsync().ConfigureAwait(false) + ); + } + + return JsonSerializer.Deserialize( + await response.Content.ReadAsStreamAsync().ConfigureAwait(false), + ModelBase.SerializerOptions + ) ?? throw new NullReferenceException(); + } + + public async Task AddTags(BulkAddTagsParams parameters) + { + using HttpRequestMessage request = new(HttpMethod.Post, parameters.Url(this._client)) + { + Content = parameters.BodyContent(), + }; + parameters.AddHeadersToRequest(request, this._client); + using HttpResponseMessage response = await this + ._client.HttpClient.SendAsync(request, HttpCompletionOption.ResponseHeadersRead) + .ConfigureAwait(false); + if (!response.IsSuccessStatusCode) + { + throw new HttpException( + response.StatusCode, + await response.Content.ReadAsStringAsync().ConfigureAwait(false) + ); + } + + return JsonSerializer.Deserialize( + await response.Content.ReadAsStreamAsync().ConfigureAwait(false), + ModelBase.SerializerOptions + ) ?? throw new NullReferenceException(); + } + + public async Task RemoveAITags(BulkRemoveAITagsParams parameters) + { + using HttpRequestMessage request = new(HttpMethod.Post, parameters.Url(this._client)) + { + Content = parameters.BodyContent(), + }; + parameters.AddHeadersToRequest(request, this._client); + using HttpResponseMessage response = await this + ._client.HttpClient.SendAsync(request, HttpCompletionOption.ResponseHeadersRead) + .ConfigureAwait(false); + if (!response.IsSuccessStatusCode) + { + throw new HttpException( + response.StatusCode, + await response.Content.ReadAsStringAsync().ConfigureAwait(false) + ); + } + + return JsonSerializer.Deserialize( + await response.Content.ReadAsStreamAsync().ConfigureAwait(false), + ModelBase.SerializerOptions + ) ?? throw new NullReferenceException(); + } + + public async Task RemoveTags(BulkRemoveTagsParams parameters) + { + using HttpRequestMessage request = new(HttpMethod.Post, parameters.Url(this._client)) + { + Content = parameters.BodyContent(), + }; + parameters.AddHeadersToRequest(request, this._client); + using HttpResponseMessage response = await this + ._client.HttpClient.SendAsync(request, HttpCompletionOption.ResponseHeadersRead) + .ConfigureAwait(false); + if (!response.IsSuccessStatusCode) + { + throw new HttpException( + response.StatusCode, + await response.Content.ReadAsStringAsync().ConfigureAwait(false) + ); + } + + return JsonSerializer.Deserialize( + await response.Content.ReadAsStreamAsync().ConfigureAwait(false), + ModelBase.SerializerOptions + ) ?? throw new NullReferenceException(); + } +} diff --git a/src/Imagekit/Services/Files/Bulk/IBulkService.cs b/src/Imagekit/Services/Files/Bulk/IBulkService.cs new file mode 100644 index 00000000..da6626c9 --- /dev/null +++ b/src/Imagekit/Services/Files/Bulk/IBulkService.cs @@ -0,0 +1,36 @@ +using System.Threading.Tasks; +using Imagekit.Models.Files.Bulk; + +namespace Imagekit.Services.Files.Bulk; + +public interface IBulkService +{ + /// + /// This API deletes multiple files and all their file versions permanently. + /// + /// Note: If a file or specific transformation has been requested in the past, + /// then the response is cached. Deleting a file does not purge the cache. You + /// can purge the cache using purge cache API. + /// + /// A maximum of 100 files can be deleted at a time. + /// + Task Delete(BulkDeleteParams parameters); + + /// + /// This API adds tags to multiple files in bulk. A maximum of 50 files can be + /// specified at a time. + /// + Task AddTags(BulkAddTagsParams parameters); + + /// + /// This API removes AITags from multiple files in bulk. A maximum of 50 files + /// can be specified at a time. + /// + Task RemoveAITags(BulkRemoveAITagsParams parameters); + + /// + /// This API removes tags from multiple files in bulk. A maximum of 50 files can + /// be specified at a time. + /// + Task RemoveTags(BulkRemoveTagsParams parameters); +} diff --git a/src/Imagekit/Services/Files/FileService.cs b/src/Imagekit/Services/Files/FileService.cs new file mode 100644 index 00000000..7ec98b70 --- /dev/null +++ b/src/Imagekit/Services/Files/FileService.cs @@ -0,0 +1,198 @@ +using System; +using System.Net.Http; +using System.Text.Json; +using System.Threading.Tasks; +using Imagekit.Models.Files; +using Imagekit.Services.Files.Bulk; +using Imagekit.Services.Files.Metadata; +using Imagekit.Services.Files.Versions; + +namespace Imagekit.Services.Files; + +public sealed class FileService : IFileService +{ + readonly IImageKitClient _client; + + public FileService(IImageKitClient client) + { + _client = client; + _bulk = new(() => new BulkService(client)); + _versions = new(() => new VersionService(client)); + _metadata = new(() => new MetadataService(client)); + } + + readonly Lazy _bulk; + public IBulkService Bulk + { + get { return _bulk.Value; } + } + + readonly Lazy _versions; + public IVersionService Versions + { + get { return _versions.Value; } + } + + readonly Lazy _metadata; + public IMetadataService Metadata + { + get { return _metadata.Value; } + } + + public async Task Update(FileUpdateParams parameters) + { + using HttpRequestMessage request = new(HttpMethod.Patch, parameters.Url(this._client)) + { + Content = parameters.BodyContent(), + }; + parameters.AddHeadersToRequest(request, this._client); + using HttpResponseMessage response = await this + ._client.HttpClient.SendAsync(request, HttpCompletionOption.ResponseHeadersRead) + .ConfigureAwait(false); + if (!response.IsSuccessStatusCode) + { + throw new HttpException( + response.StatusCode, + await response.Content.ReadAsStringAsync().ConfigureAwait(false) + ); + } + + return JsonSerializer.Deserialize( + await response.Content.ReadAsStreamAsync().ConfigureAwait(false), + ModelBase.SerializerOptions + ) ?? throw new NullReferenceException(); + } + + public async Task Delete(FileDeleteParams parameters) + { + using HttpRequestMessage request = new(HttpMethod.Delete, parameters.Url(this._client)); + parameters.AddHeadersToRequest(request, this._client); + using HttpResponseMessage response = await this + ._client.HttpClient.SendAsync(request, HttpCompletionOption.ResponseHeadersRead) + .ConfigureAwait(false); + if (!response.IsSuccessStatusCode) + { + throw new HttpException( + response.StatusCode, + await response.Content.ReadAsStringAsync().ConfigureAwait(false) + ); + } + } + + public async Task Copy(FileCopyParams parameters) + { + using HttpRequestMessage request = new(HttpMethod.Post, parameters.Url(this._client)) + { + Content = parameters.BodyContent(), + }; + parameters.AddHeadersToRequest(request, this._client); + using HttpResponseMessage response = await this + ._client.HttpClient.SendAsync(request, HttpCompletionOption.ResponseHeadersRead) + .ConfigureAwait(false); + if (!response.IsSuccessStatusCode) + { + throw new HttpException( + response.StatusCode, + await response.Content.ReadAsStringAsync().ConfigureAwait(false) + ); + } + + return JsonSerializer.Deserialize( + await response.Content.ReadAsStreamAsync().ConfigureAwait(false), + ModelBase.SerializerOptions + ) ?? throw new NullReferenceException(); + } + + public async Task Get(FileGetParams parameters) + { + using HttpRequestMessage request = new(HttpMethod.Get, parameters.Url(this._client)); + parameters.AddHeadersToRequest(request, this._client); + using HttpResponseMessage response = await this + ._client.HttpClient.SendAsync(request, HttpCompletionOption.ResponseHeadersRead) + .ConfigureAwait(false); + if (!response.IsSuccessStatusCode) + { + throw new HttpException( + response.StatusCode, + await response.Content.ReadAsStringAsync().ConfigureAwait(false) + ); + } + + return JsonSerializer.Deserialize( + await response.Content.ReadAsStreamAsync().ConfigureAwait(false), + ModelBase.SerializerOptions + ) ?? throw new NullReferenceException(); + } + + public async Task Move(FileMoveParams parameters) + { + using HttpRequestMessage request = new(HttpMethod.Post, parameters.Url(this._client)) + { + Content = parameters.BodyContent(), + }; + parameters.AddHeadersToRequest(request, this._client); + using HttpResponseMessage response = await this + ._client.HttpClient.SendAsync(request, HttpCompletionOption.ResponseHeadersRead) + .ConfigureAwait(false); + if (!response.IsSuccessStatusCode) + { + throw new HttpException( + response.StatusCode, + await response.Content.ReadAsStringAsync().ConfigureAwait(false) + ); + } + + return JsonSerializer.Deserialize( + await response.Content.ReadAsStreamAsync().ConfigureAwait(false), + ModelBase.SerializerOptions + ) ?? throw new NullReferenceException(); + } + + public async Task Rename(FileRenameParams parameters) + { + using HttpRequestMessage request = new(HttpMethod.Put, parameters.Url(this._client)) + { + Content = parameters.BodyContent(), + }; + parameters.AddHeadersToRequest(request, this._client); + using HttpResponseMessage response = await this + ._client.HttpClient.SendAsync(request, HttpCompletionOption.ResponseHeadersRead) + .ConfigureAwait(false); + if (!response.IsSuccessStatusCode) + { + throw new HttpException( + response.StatusCode, + await response.Content.ReadAsStringAsync().ConfigureAwait(false) + ); + } + + return JsonSerializer.Deserialize( + await response.Content.ReadAsStreamAsync().ConfigureAwait(false), + ModelBase.SerializerOptions + ) ?? throw new NullReferenceException(); + } + + public async Task Upload(FileUploadParams parameters) + { + using HttpRequestMessage request = new(HttpMethod.Post, parameters.Url(this._client)) + { + Content = parameters.BodyContent(), + }; + parameters.AddHeadersToRequest(request, this._client); + using HttpResponseMessage response = await this + ._client.HttpClient.SendAsync(request, HttpCompletionOption.ResponseHeadersRead) + .ConfigureAwait(false); + if (!response.IsSuccessStatusCode) + { + throw new HttpException( + response.StatusCode, + await response.Content.ReadAsStringAsync().ConfigureAwait(false) + ); + } + + return JsonSerializer.Deserialize( + await response.Content.ReadAsStreamAsync().ConfigureAwait(false), + ModelBase.SerializerOptions + ) ?? throw new NullReferenceException(); + } +} diff --git a/src/Imagekit/Services/Files/IFileService.cs b/src/Imagekit/Services/Files/IFileService.cs new file mode 100644 index 00000000..183d998d --- /dev/null +++ b/src/Imagekit/Services/Files/IFileService.cs @@ -0,0 +1,91 @@ +using System.Threading.Tasks; +using Imagekit.Models.Files; +using Imagekit.Services.Files.Bulk; +using Imagekit.Services.Files.Metadata; +using Imagekit.Services.Files.Versions; + +namespace Imagekit.Services.Files; + +public interface IFileService +{ + IBulkService Bulk { get; } + + IVersionService Versions { get; } + + IMetadataService Metadata { get; } + + /// + /// This API updates the details or attributes of the current version of the + /// file. You can update `tags`, `customCoordinates`, `customMetadata`, publication + /// status, remove existing `AITags` and apply extensions using this API. + /// + Task Update(FileUpdateParams parameters); + + /// + /// This API deletes the file and all its file versions permanently. + /// + /// Note: If a file or specific transformation has been requested in the past, + /// then the response is cached. Deleting a file does not purge the cache. You + /// can purge the cache using purge cache API. + /// + Task Delete(FileDeleteParams parameters); + + /// + /// This will copy a file from one folder to another. + /// + /// Note: If any file at the destination has the same name as the source file, + /// then the source file and its versions (if `includeFileVersions` is set to + /// true) will be appended to the destination file version history. + /// + Task Copy(FileCopyParams parameters); + + /// + /// This API returns an object with details or attributes about the current version + /// of the file. + /// + Task Get(FileGetParams parameters); + + /// + /// This will move a file and all its versions from one folder to another. + /// + /// Note: If any file at the destination has the same name as the source file, + /// then the source file and its versions will be appended to the destination + /// file. + /// + Task Move(FileMoveParams parameters); + + /// + /// You can rename an already existing file in the media library using rename + /// file API. This operation would rename all file versions of the file. + /// + /// Note: The old URLs will stop working. The file/file version URLs cached on + /// CDN will continue to work unless a purge is requested. + /// + Task Rename(FileRenameParams parameters); + + /// + /// ImageKit.io allows you to upload files directly from both the server and client + /// sides. For server-side uploads, private API key authentication is used. For + /// client-side uploads, generate a one-time `token`, `signature`, and `expire` + /// from your secure backend using private API. [Learn more](/docs/api-reference/upload-file/upload-file#how-to-implement-client-side-file-upload) + /// about how to implement client-side file upload. + /// + /// The [V2 API](/docs/api-reference/upload-file/upload-file-v2) enhances security + /// by verifying the entire payload using JWT. + /// + /// **File size limit** \ On the free plan, the maximum upload file sizes are + /// 20MB for images, audio, and raw files and 100MB for videos. On the paid plan, + /// these limits increase to 40MB for images, audio, and raw files and 2GB for + /// videos. These limits can be further increased with higher-tier plans. + /// + /// **Version limit** \ A file can have a maximum of 100 versions. + /// + /// **Demo applications** + /// + /// - A full-fledged [upload widget using Uppy](https://github.com/imagekit-samples/uppy-uploader), + /// supporting file selections from local storage, URL, Dropbox, Google Drive, + /// Instagram, and more. - [Quick start guides](/docs/quick-start-guides) for + /// various frameworks and technologies. + /// + Task Upload(FileUploadParams parameters); +} diff --git a/src/Imagekit/Services/Files/Metadata/IMetadataService.cs b/src/Imagekit/Services/Files/Metadata/IMetadataService.cs new file mode 100644 index 00000000..2135c619 --- /dev/null +++ b/src/Imagekit/Services/Files/Metadata/IMetadataService.cs @@ -0,0 +1,23 @@ +using System.Threading.Tasks; +using Imagekit.Models.Files.Metadata; +using Files = Imagekit.Models.Files; + +namespace Imagekit.Services.Files.Metadata; + +public interface IMetadataService +{ + /// + /// You can programmatically get image EXIF, pHash, and other metadata for uploaded + /// files in the ImageKit.io media library using this API. + /// + /// You can also get the metadata in upload API response by passing `metadata` + /// in `responseFields` parameter. + /// + Task Get(MetadataGetParams parameters); + + /// + /// Get image EXIF, pHash, and other metadata from ImageKit.io powered remote + /// URL using this API. + /// + Task GetFromURL(MetadataGetFromURLParams parameters); +} diff --git a/src/Imagekit/Services/Files/Metadata/MetadataService.cs b/src/Imagekit/Services/Files/Metadata/MetadataService.cs new file mode 100644 index 00000000..46110365 --- /dev/null +++ b/src/Imagekit/Services/Files/Metadata/MetadataService.cs @@ -0,0 +1,60 @@ +using System; +using System.Net.Http; +using System.Text.Json; +using System.Threading.Tasks; +using Imagekit.Models.Files.Metadata; +using Files = Imagekit.Models.Files; + +namespace Imagekit.Services.Files.Metadata; + +public sealed class MetadataService : IMetadataService +{ + readonly IImageKitClient _client; + + public MetadataService(IImageKitClient client) + { + _client = client; + } + + public async Task Get(MetadataGetParams parameters) + { + using HttpRequestMessage request = new(HttpMethod.Get, parameters.Url(this._client)); + parameters.AddHeadersToRequest(request, this._client); + using HttpResponseMessage response = await this + ._client.HttpClient.SendAsync(request, HttpCompletionOption.ResponseHeadersRead) + .ConfigureAwait(false); + if (!response.IsSuccessStatusCode) + { + throw new HttpException( + response.StatusCode, + await response.Content.ReadAsStringAsync().ConfigureAwait(false) + ); + } + + return JsonSerializer.Deserialize( + await response.Content.ReadAsStreamAsync().ConfigureAwait(false), + ModelBase.SerializerOptions + ) ?? throw new NullReferenceException(); + } + + public async Task GetFromURL(MetadataGetFromURLParams parameters) + { + using HttpRequestMessage request = new(HttpMethod.Get, parameters.Url(this._client)); + parameters.AddHeadersToRequest(request, this._client); + using HttpResponseMessage response = await this + ._client.HttpClient.SendAsync(request, HttpCompletionOption.ResponseHeadersRead) + .ConfigureAwait(false); + if (!response.IsSuccessStatusCode) + { + throw new HttpException( + response.StatusCode, + await response.Content.ReadAsStringAsync().ConfigureAwait(false) + ); + } + + return JsonSerializer.Deserialize( + await response.Content.ReadAsStreamAsync().ConfigureAwait(false), + ModelBase.SerializerOptions + ) ?? throw new NullReferenceException(); + } +} diff --git a/src/Imagekit/Services/Files/Versions/IVersionService.cs b/src/Imagekit/Services/Files/Versions/IVersionService.cs new file mode 100644 index 00000000..8efbc71d --- /dev/null +++ b/src/Imagekit/Services/Files/Versions/IVersionService.cs @@ -0,0 +1,32 @@ +using System.Collections.Generic; +using System.Threading.Tasks; +using Imagekit.Models.Files; +using Imagekit.Models.Files.Versions; + +namespace Imagekit.Services.Files.Versions; + +public interface IVersionService +{ + /// + /// This API returns details of all versions of a file. + /// + Task> List(VersionListParams parameters); + + /// + /// This API deletes a non-current file version permanently. The API returns + /// an empty response. + /// + /// Note: If you want to delete all versions of a file, use the delete file API. + /// + Task Delete(VersionDeleteParams parameters); + + /// + /// This API returns an object with details or attributes of a file version. + /// + Task Get(VersionGetParams parameters); + + /// + /// This API restores a file version as the current file version. + /// + Task Restore(VersionRestoreParams parameters); +} diff --git a/src/Imagekit/Services/Files/Versions/VersionService.cs b/src/Imagekit/Services/Files/Versions/VersionService.cs new file mode 100644 index 00000000..e47cc714 --- /dev/null +++ b/src/Imagekit/Services/Files/Versions/VersionService.cs @@ -0,0 +1,103 @@ +using System; +using System.Collections.Generic; +using System.Net.Http; +using System.Text.Json; +using System.Threading.Tasks; +using Imagekit.Models.Files; +using Imagekit.Models.Files.Versions; + +namespace Imagekit.Services.Files.Versions; + +public sealed class VersionService : IVersionService +{ + readonly IImageKitClient _client; + + public VersionService(IImageKitClient client) + { + _client = client; + } + + public async Task> List(VersionListParams parameters) + { + using HttpRequestMessage request = new(HttpMethod.Get, parameters.Url(this._client)); + parameters.AddHeadersToRequest(request, this._client); + using HttpResponseMessage response = await this + ._client.HttpClient.SendAsync(request, HttpCompletionOption.ResponseHeadersRead) + .ConfigureAwait(false); + if (!response.IsSuccessStatusCode) + { + throw new HttpException( + response.StatusCode, + await response.Content.ReadAsStringAsync().ConfigureAwait(false) + ); + } + + return JsonSerializer.Deserialize>( + await response.Content.ReadAsStreamAsync().ConfigureAwait(false), + ModelBase.SerializerOptions + ) ?? throw new NullReferenceException(); + } + + public async Task Delete(VersionDeleteParams parameters) + { + using HttpRequestMessage request = new(HttpMethod.Delete, parameters.Url(this._client)); + parameters.AddHeadersToRequest(request, this._client); + using HttpResponseMessage response = await this + ._client.HttpClient.SendAsync(request, HttpCompletionOption.ResponseHeadersRead) + .ConfigureAwait(false); + if (!response.IsSuccessStatusCode) + { + throw new HttpException( + response.StatusCode, + await response.Content.ReadAsStringAsync().ConfigureAwait(false) + ); + } + + return JsonSerializer.Deserialize( + await response.Content.ReadAsStreamAsync().ConfigureAwait(false), + ModelBase.SerializerOptions + ) ?? throw new NullReferenceException(); + } + + public async Task Get(VersionGetParams parameters) + { + using HttpRequestMessage request = new(HttpMethod.Get, parameters.Url(this._client)); + parameters.AddHeadersToRequest(request, this._client); + using HttpResponseMessage response = await this + ._client.HttpClient.SendAsync(request, HttpCompletionOption.ResponseHeadersRead) + .ConfigureAwait(false); + if (!response.IsSuccessStatusCode) + { + throw new HttpException( + response.StatusCode, + await response.Content.ReadAsStringAsync().ConfigureAwait(false) + ); + } + + return JsonSerializer.Deserialize( + await response.Content.ReadAsStreamAsync().ConfigureAwait(false), + ModelBase.SerializerOptions + ) ?? throw new NullReferenceException(); + } + + public async Task Restore(VersionRestoreParams parameters) + { + using HttpRequestMessage request = new(HttpMethod.Put, parameters.Url(this._client)); + parameters.AddHeadersToRequest(request, this._client); + using HttpResponseMessage response = await this + ._client.HttpClient.SendAsync(request, HttpCompletionOption.ResponseHeadersRead) + .ConfigureAwait(false); + if (!response.IsSuccessStatusCode) + { + throw new HttpException( + response.StatusCode, + await response.Content.ReadAsStringAsync().ConfigureAwait(false) + ); + } + + return JsonSerializer.Deserialize( + await response.Content.ReadAsStreamAsync().ConfigureAwait(false), + ModelBase.SerializerOptions + ) ?? throw new NullReferenceException(); + } +} diff --git a/src/Imagekit/Services/Folders/FolderService.cs b/src/Imagekit/Services/Folders/FolderService.cs new file mode 100644 index 00000000..23f3bc3d --- /dev/null +++ b/src/Imagekit/Services/Folders/FolderService.cs @@ -0,0 +1,145 @@ +using System; +using System.Net.Http; +using System.Text.Json; +using System.Threading.Tasks; +using Imagekit.Models.Folders; +using Imagekit.Services.Folders.Job; + +namespace Imagekit.Services.Folders; + +public sealed class FolderService : IFolderService +{ + readonly IImageKitClient _client; + + public FolderService(IImageKitClient client) + { + _client = client; + _job = new(() => new JobService(client)); + } + + readonly Lazy _job; + public IJobService Job + { + get { return _job.Value; } + } + + public async Task Create(FolderCreateParams parameters) + { + using HttpRequestMessage request = new(HttpMethod.Post, parameters.Url(this._client)) + { + Content = parameters.BodyContent(), + }; + parameters.AddHeadersToRequest(request, this._client); + using HttpResponseMessage response = await this + ._client.HttpClient.SendAsync(request, HttpCompletionOption.ResponseHeadersRead) + .ConfigureAwait(false); + if (!response.IsSuccessStatusCode) + { + throw new HttpException( + response.StatusCode, + await response.Content.ReadAsStringAsync().ConfigureAwait(false) + ); + } + + return JsonSerializer.Deserialize( + await response.Content.ReadAsStreamAsync().ConfigureAwait(false), + ModelBase.SerializerOptions + ) ?? throw new NullReferenceException(); + } + + public async Task Delete(FolderDeleteParams parameters) + { + using HttpRequestMessage request = new(HttpMethod.Delete, parameters.Url(this._client)) + { + Content = parameters.BodyContent(), + }; + parameters.AddHeadersToRequest(request, this._client); + using HttpResponseMessage response = await this + ._client.HttpClient.SendAsync(request, HttpCompletionOption.ResponseHeadersRead) + .ConfigureAwait(false); + if (!response.IsSuccessStatusCode) + { + throw new HttpException( + response.StatusCode, + await response.Content.ReadAsStringAsync().ConfigureAwait(false) + ); + } + + return JsonSerializer.Deserialize( + await response.Content.ReadAsStreamAsync().ConfigureAwait(false), + ModelBase.SerializerOptions + ) ?? throw new NullReferenceException(); + } + + public async Task Copy(FolderCopyParams parameters) + { + using HttpRequestMessage request = new(HttpMethod.Post, parameters.Url(this._client)) + { + Content = parameters.BodyContent(), + }; + parameters.AddHeadersToRequest(request, this._client); + using HttpResponseMessage response = await this + ._client.HttpClient.SendAsync(request, HttpCompletionOption.ResponseHeadersRead) + .ConfigureAwait(false); + if (!response.IsSuccessStatusCode) + { + throw new HttpException( + response.StatusCode, + await response.Content.ReadAsStringAsync().ConfigureAwait(false) + ); + } + + return JsonSerializer.Deserialize( + await response.Content.ReadAsStreamAsync().ConfigureAwait(false), + ModelBase.SerializerOptions + ) ?? throw new NullReferenceException(); + } + + public async Task Move(FolderMoveParams parameters) + { + using HttpRequestMessage request = new(HttpMethod.Post, parameters.Url(this._client)) + { + Content = parameters.BodyContent(), + }; + parameters.AddHeadersToRequest(request, this._client); + using HttpResponseMessage response = await this + ._client.HttpClient.SendAsync(request, HttpCompletionOption.ResponseHeadersRead) + .ConfigureAwait(false); + if (!response.IsSuccessStatusCode) + { + throw new HttpException( + response.StatusCode, + await response.Content.ReadAsStringAsync().ConfigureAwait(false) + ); + } + + return JsonSerializer.Deserialize( + await response.Content.ReadAsStreamAsync().ConfigureAwait(false), + ModelBase.SerializerOptions + ) ?? throw new NullReferenceException(); + } + + public async Task Rename(FolderRenameParams parameters) + { + using HttpRequestMessage request = new(HttpMethod.Post, parameters.Url(this._client)) + { + Content = parameters.BodyContent(), + }; + parameters.AddHeadersToRequest(request, this._client); + using HttpResponseMessage response = await this + ._client.HttpClient.SendAsync(request, HttpCompletionOption.ResponseHeadersRead) + .ConfigureAwait(false); + if (!response.IsSuccessStatusCode) + { + throw new HttpException( + response.StatusCode, + await response.Content.ReadAsStringAsync().ConfigureAwait(false) + ); + } + + return JsonSerializer.Deserialize( + await response.Content.ReadAsStreamAsync().ConfigureAwait(false), + ModelBase.SerializerOptions + ) ?? throw new NullReferenceException(); + } +} diff --git a/src/Imagekit/Services/Folders/IFolderService.cs b/src/Imagekit/Services/Folders/IFolderService.cs new file mode 100644 index 00000000..da6b7be6 --- /dev/null +++ b/src/Imagekit/Services/Folders/IFolderService.cs @@ -0,0 +1,46 @@ +using System.Threading.Tasks; +using Imagekit.Models.Folders; +using Imagekit.Services.Folders.Job; + +namespace Imagekit.Services.Folders; + +public interface IFolderService +{ + IJobService Job { get; } + + /// + /// This will create a new folder. You can specify the folder name and location + /// of the parent folder where this new folder should be created. + /// + Task Create(FolderCreateParams parameters); + + /// + /// This will delete a folder and all its contents permanently. The API returns + /// an empty response. + /// + Task Delete(FolderDeleteParams parameters); + + /// + /// This will copy one folder into another. The selected folder, its nested folders, + /// files, and their versions (in `includeVersions` is set to true) are copied + /// in this operation. Note: If any file at the destination has the same name + /// as the source file, then the source file and its versions will be appended + /// to the destination file version history. + /// + Task Copy(FolderCopyParams parameters); + + /// + /// This will move one folder into another. The selected folder, its nested folders, + /// files, and their versions are moved in this operation. Note: If any file at + /// the destination has the same name as the source file, then the source file + /// and its versions will be appended to the destination file version history. + /// + Task Move(FolderMoveParams parameters); + + /// + /// This API allows you to rename an existing folder. The folder and all its nested + /// assets and sub-folders will remain unchanged, but their paths will be updated + /// to reflect the new folder name. + /// + Task Rename(FolderRenameParams parameters); +} diff --git a/src/Imagekit/Services/Folders/Job/IJobService.cs b/src/Imagekit/Services/Folders/Job/IJobService.cs new file mode 100644 index 00000000..eb919607 --- /dev/null +++ b/src/Imagekit/Services/Folders/Job/IJobService.cs @@ -0,0 +1,12 @@ +using System.Threading.Tasks; +using Imagekit.Models.Folders.Job; + +namespace Imagekit.Services.Folders.Job; + +public interface IJobService +{ + /// + /// This API returns the status of a bulk job like copy and move folder operations. + /// + Task Get(JobGetParams parameters); +} diff --git a/src/Imagekit/Services/Folders/Job/JobService.cs b/src/Imagekit/Services/Folders/Job/JobService.cs new file mode 100644 index 00000000..3530816f --- /dev/null +++ b/src/Imagekit/Services/Folders/Job/JobService.cs @@ -0,0 +1,38 @@ +using System; +using System.Net.Http; +using System.Text.Json; +using System.Threading.Tasks; +using Imagekit.Models.Folders.Job; + +namespace Imagekit.Services.Folders.Job; + +public sealed class JobService : IJobService +{ + readonly IImageKitClient _client; + + public JobService(IImageKitClient client) + { + _client = client; + } + + public async Task Get(JobGetParams parameters) + { + using HttpRequestMessage request = new(HttpMethod.Get, parameters.Url(this._client)); + parameters.AddHeadersToRequest(request, this._client); + using HttpResponseMessage response = await this + ._client.HttpClient.SendAsync(request, HttpCompletionOption.ResponseHeadersRead) + .ConfigureAwait(false); + if (!response.IsSuccessStatusCode) + { + throw new HttpException( + response.StatusCode, + await response.Content.ReadAsStringAsync().ConfigureAwait(false) + ); + } + + return JsonSerializer.Deserialize( + await response.Content.ReadAsStreamAsync().ConfigureAwait(false), + ModelBase.SerializerOptions + ) ?? throw new NullReferenceException(); + } +} diff --git a/src/Imagekit/Services/Webhooks/IWebhookService.cs b/src/Imagekit/Services/Webhooks/IWebhookService.cs new file mode 100644 index 00000000..7529d7b5 --- /dev/null +++ b/src/Imagekit/Services/Webhooks/IWebhookService.cs @@ -0,0 +1,3 @@ +namespace Imagekit.Services.Webhooks; + +public interface IWebhookService { } diff --git a/src/Imagekit/Services/Webhooks/WebhookService.cs b/src/Imagekit/Services/Webhooks/WebhookService.cs new file mode 100644 index 00000000..79912020 --- /dev/null +++ b/src/Imagekit/Services/Webhooks/WebhookService.cs @@ -0,0 +1,6 @@ +namespace Imagekit.Services.Webhooks; + +public sealed class WebhookService : IWebhookService +{ + public WebhookService(IImageKitClient client) { } +}