ingestr 0.13.1__tar.gz → 0.13.3__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of ingestr might be problematic. Click here for more details.
- {ingestr-0.13.1 → ingestr-0.13.3}/PKG-INFO +1 -1
- {ingestr-0.13.1 → ingestr-0.13.3}/docs/.vitepress/config.mjs +1 -0
- ingestr-0.13.3/docs/supported-sources/applovin.md +144 -0
- {ingestr-0.13.1 → ingestr-0.13.3}/docs/supported-sources/clickhouse.md +3 -2
- ingestr-0.13.3/ingestr/src/applovin/__init__.py +282 -0
- {ingestr-0.13.1 → ingestr-0.13.3}/ingestr/src/destinations.py +13 -3
- {ingestr-0.13.1 → ingestr-0.13.3}/ingestr/src/factory.py +2 -0
- {ingestr-0.13.1 → ingestr-0.13.3}/ingestr/src/sources.py +45 -0
- ingestr-0.13.3/ingestr/src/version.py +1 -0
- ingestr-0.13.1/ingestr/src/version.py +0 -1
- {ingestr-0.13.1 → ingestr-0.13.3}/.dockerignore +0 -0
- {ingestr-0.13.1 → ingestr-0.13.3}/.githooks/pre-commit-hook.sh +0 -0
- {ingestr-0.13.1 → ingestr-0.13.3}/.github/workflows/deploy-docs.yml +0 -0
- {ingestr-0.13.1 → ingestr-0.13.3}/.github/workflows/secrets-scan.yml +0 -0
- {ingestr-0.13.1 → ingestr-0.13.3}/.github/workflows/tests.yml +0 -0
- {ingestr-0.13.1 → ingestr-0.13.3}/.gitignore +0 -0
- {ingestr-0.13.1 → ingestr-0.13.3}/.gitleaksignore +0 -0
- {ingestr-0.13.1 → ingestr-0.13.3}/.python-version +0 -0
- {ingestr-0.13.1 → ingestr-0.13.3}/.vale.ini +0 -0
- {ingestr-0.13.1 → ingestr-0.13.3}/Dockerfile +0 -0
- {ingestr-0.13.1 → ingestr-0.13.3}/LICENSE.md +0 -0
- {ingestr-0.13.1 → ingestr-0.13.3}/Makefile +0 -0
- {ingestr-0.13.1 → ingestr-0.13.3}/README.md +0 -0
- {ingestr-0.13.1 → ingestr-0.13.3}/docs/.vitepress/theme/custom.css +0 -0
- {ingestr-0.13.1 → ingestr-0.13.3}/docs/.vitepress/theme/index.js +0 -0
- {ingestr-0.13.1 → ingestr-0.13.3}/docs/commands/example-uris.md +0 -0
- {ingestr-0.13.1 → ingestr-0.13.3}/docs/commands/ingest.md +0 -0
- {ingestr-0.13.1 → ingestr-0.13.3}/docs/getting-started/core-concepts.md +0 -0
- {ingestr-0.13.1 → ingestr-0.13.3}/docs/getting-started/incremental-loading.md +0 -0
- {ingestr-0.13.1 → ingestr-0.13.3}/docs/getting-started/quickstart.md +0 -0
- {ingestr-0.13.1 → ingestr-0.13.3}/docs/getting-started/telemetry.md +0 -0
- {ingestr-0.13.1 → ingestr-0.13.3}/docs/index.md +0 -0
- {ingestr-0.13.1 → ingestr-0.13.3}/docs/media/athena.png +0 -0
- {ingestr-0.13.1 → ingestr-0.13.3}/docs/media/clickhouse_img.png +0 -0
- {ingestr-0.13.1 → ingestr-0.13.3}/docs/media/github.png +0 -0
- {ingestr-0.13.1 → ingestr-0.13.3}/docs/media/googleanalytics.png +0 -0
- {ingestr-0.13.1 → ingestr-0.13.3}/docs/media/linkedin_ads.png +0 -0
- {ingestr-0.13.1 → ingestr-0.13.3}/docs/media/tiktok.png +0 -0
- {ingestr-0.13.1 → ingestr-0.13.3}/docs/supported-sources/adjust.md +0 -0
- {ingestr-0.13.1 → ingestr-0.13.3}/docs/supported-sources/airtable.md +0 -0
- {ingestr-0.13.1 → ingestr-0.13.3}/docs/supported-sources/appsflyer.md +0 -0
- {ingestr-0.13.1 → ingestr-0.13.3}/docs/supported-sources/appstore.md +0 -0
- {ingestr-0.13.1 → ingestr-0.13.3}/docs/supported-sources/asana.md +0 -0
- {ingestr-0.13.1 → ingestr-0.13.3}/docs/supported-sources/athena.md +0 -0
- {ingestr-0.13.1 → ingestr-0.13.3}/docs/supported-sources/bigquery.md +0 -0
- {ingestr-0.13.1 → ingestr-0.13.3}/docs/supported-sources/chess.md +0 -0
- {ingestr-0.13.1 → ingestr-0.13.3}/docs/supported-sources/csv.md +0 -0
- {ingestr-0.13.1 → ingestr-0.13.3}/docs/supported-sources/custom_queries.md +0 -0
- {ingestr-0.13.1 → ingestr-0.13.3}/docs/supported-sources/databricks.md +0 -0
- {ingestr-0.13.1 → ingestr-0.13.3}/docs/supported-sources/duckdb.md +0 -0
- {ingestr-0.13.1 → ingestr-0.13.3}/docs/supported-sources/dynamodb.md +0 -0
- {ingestr-0.13.1 → ingestr-0.13.3}/docs/supported-sources/facebook-ads.md +0 -0
- {ingestr-0.13.1 → ingestr-0.13.3}/docs/supported-sources/gcs.md +0 -0
- {ingestr-0.13.1 → ingestr-0.13.3}/docs/supported-sources/github.md +0 -0
- {ingestr-0.13.1 → ingestr-0.13.3}/docs/supported-sources/google-ads.md +0 -0
- {ingestr-0.13.1 → ingestr-0.13.3}/docs/supported-sources/google_analytics.md +0 -0
- {ingestr-0.13.1 → ingestr-0.13.3}/docs/supported-sources/gorgias.md +0 -0
- {ingestr-0.13.1 → ingestr-0.13.3}/docs/supported-sources/gsheets.md +0 -0
- {ingestr-0.13.1 → ingestr-0.13.3}/docs/supported-sources/hubspot.md +0 -0
- {ingestr-0.13.1 → ingestr-0.13.3}/docs/supported-sources/kafka.md +0 -0
- {ingestr-0.13.1 → ingestr-0.13.3}/docs/supported-sources/klaviyo.md +0 -0
- {ingestr-0.13.1 → ingestr-0.13.3}/docs/supported-sources/linkedin_ads.md +0 -0
- {ingestr-0.13.1 → ingestr-0.13.3}/docs/supported-sources/mongodb.md +0 -0
- {ingestr-0.13.1 → ingestr-0.13.3}/docs/supported-sources/mssql.md +0 -0
- {ingestr-0.13.1 → ingestr-0.13.3}/docs/supported-sources/mysql.md +0 -0
- {ingestr-0.13.1 → ingestr-0.13.3}/docs/supported-sources/notion.md +0 -0
- {ingestr-0.13.1 → ingestr-0.13.3}/docs/supported-sources/oracle.md +0 -0
- {ingestr-0.13.1 → ingestr-0.13.3}/docs/supported-sources/postgres.md +0 -0
- {ingestr-0.13.1 → ingestr-0.13.3}/docs/supported-sources/redshift.md +0 -0
- {ingestr-0.13.1 → ingestr-0.13.3}/docs/supported-sources/s3.md +0 -0
- {ingestr-0.13.1 → ingestr-0.13.3}/docs/supported-sources/sap-hana.md +0 -0
- {ingestr-0.13.1 → ingestr-0.13.3}/docs/supported-sources/shopify.md +0 -0
- {ingestr-0.13.1 → ingestr-0.13.3}/docs/supported-sources/slack.md +0 -0
- {ingestr-0.13.1 → ingestr-0.13.3}/docs/supported-sources/snowflake.md +0 -0
- {ingestr-0.13.1 → ingestr-0.13.3}/docs/supported-sources/sqlite.md +0 -0
- {ingestr-0.13.1 → ingestr-0.13.3}/docs/supported-sources/stripe.md +0 -0
- {ingestr-0.13.1 → ingestr-0.13.3}/docs/supported-sources/tiktok-ads.md +0 -0
- {ingestr-0.13.1 → ingestr-0.13.3}/docs/supported-sources/zendesk.md +0 -0
- {ingestr-0.13.1 → ingestr-0.13.3}/ingestr/main.py +0 -0
- {ingestr-0.13.1 → ingestr-0.13.3}/ingestr/src/.gitignore +0 -0
- {ingestr-0.13.1 → ingestr-0.13.3}/ingestr/src/adjust/__init__.py +0 -0
- {ingestr-0.13.1 → ingestr-0.13.3}/ingestr/src/adjust/adjust_helpers.py +0 -0
- {ingestr-0.13.1 → ingestr-0.13.3}/ingestr/src/airtable/__init__.py +0 -0
- {ingestr-0.13.1 → ingestr-0.13.3}/ingestr/src/appsflyer/_init_.py +0 -0
- {ingestr-0.13.1 → ingestr-0.13.3}/ingestr/src/appsflyer/client.py +0 -0
- {ingestr-0.13.1 → ingestr-0.13.3}/ingestr/src/appstore/__init__.py +0 -0
- {ingestr-0.13.1 → ingestr-0.13.3}/ingestr/src/appstore/client.py +0 -0
- {ingestr-0.13.1 → ingestr-0.13.3}/ingestr/src/appstore/errors.py +0 -0
- {ingestr-0.13.1 → ingestr-0.13.3}/ingestr/src/appstore/models.py +0 -0
- {ingestr-0.13.1 → ingestr-0.13.3}/ingestr/src/appstore/resources.py +0 -0
- {ingestr-0.13.1 → ingestr-0.13.3}/ingestr/src/arrow/__init__.py +0 -0
- {ingestr-0.13.1 → ingestr-0.13.3}/ingestr/src/asana_source/__init__.py +0 -0
- {ingestr-0.13.1 → ingestr-0.13.3}/ingestr/src/asana_source/helpers.py +0 -0
- {ingestr-0.13.1 → ingestr-0.13.3}/ingestr/src/asana_source/settings.py +0 -0
- {ingestr-0.13.1 → ingestr-0.13.3}/ingestr/src/blob.py +0 -0
- {ingestr-0.13.1 → ingestr-0.13.3}/ingestr/src/chess/__init__.py +0 -0
- {ingestr-0.13.1 → ingestr-0.13.3}/ingestr/src/chess/helpers.py +0 -0
- {ingestr-0.13.1 → ingestr-0.13.3}/ingestr/src/chess/settings.py +0 -0
- {ingestr-0.13.1 → ingestr-0.13.3}/ingestr/src/dynamodb/__init__.py +0 -0
- {ingestr-0.13.1 → ingestr-0.13.3}/ingestr/src/errors.py +0 -0
- {ingestr-0.13.1 → ingestr-0.13.3}/ingestr/src/facebook_ads/__init__.py +0 -0
- {ingestr-0.13.1 → ingestr-0.13.3}/ingestr/src/facebook_ads/exceptions.py +0 -0
- {ingestr-0.13.1 → ingestr-0.13.3}/ingestr/src/facebook_ads/helpers.py +0 -0
- {ingestr-0.13.1 → ingestr-0.13.3}/ingestr/src/facebook_ads/settings.py +0 -0
- {ingestr-0.13.1 → ingestr-0.13.3}/ingestr/src/filesystem/__init__.py +0 -0
- {ingestr-0.13.1 → ingestr-0.13.3}/ingestr/src/filesystem/helpers.py +0 -0
- {ingestr-0.13.1 → ingestr-0.13.3}/ingestr/src/filesystem/readers.py +0 -0
- {ingestr-0.13.1 → ingestr-0.13.3}/ingestr/src/filters.py +0 -0
- {ingestr-0.13.1 → ingestr-0.13.3}/ingestr/src/github/__init__.py +0 -0
- {ingestr-0.13.1 → ingestr-0.13.3}/ingestr/src/github/helpers.py +0 -0
- {ingestr-0.13.1 → ingestr-0.13.3}/ingestr/src/github/queries.py +0 -0
- {ingestr-0.13.1 → ingestr-0.13.3}/ingestr/src/github/settings.py +0 -0
- {ingestr-0.13.1 → ingestr-0.13.3}/ingestr/src/google_ads/__init__.py +0 -0
- {ingestr-0.13.1 → ingestr-0.13.3}/ingestr/src/google_ads/field.py +0 -0
- {ingestr-0.13.1 → ingestr-0.13.3}/ingestr/src/google_ads/metrics.py +0 -0
- {ingestr-0.13.1 → ingestr-0.13.3}/ingestr/src/google_ads/predicates.py +0 -0
- {ingestr-0.13.1 → ingestr-0.13.3}/ingestr/src/google_ads/reports.py +0 -0
- {ingestr-0.13.1 → ingestr-0.13.3}/ingestr/src/google_analytics/__init__.py +0 -0
- {ingestr-0.13.1 → ingestr-0.13.3}/ingestr/src/google_analytics/helpers.py +0 -0
- {ingestr-0.13.1 → ingestr-0.13.3}/ingestr/src/google_sheets/README.md +0 -0
- {ingestr-0.13.1 → ingestr-0.13.3}/ingestr/src/google_sheets/__init__.py +0 -0
- {ingestr-0.13.1 → ingestr-0.13.3}/ingestr/src/google_sheets/helpers/__init__.py +0 -0
- {ingestr-0.13.1 → ingestr-0.13.3}/ingestr/src/google_sheets/helpers/api_calls.py +0 -0
- {ingestr-0.13.1 → ingestr-0.13.3}/ingestr/src/google_sheets/helpers/data_processing.py +0 -0
- {ingestr-0.13.1 → ingestr-0.13.3}/ingestr/src/gorgias/__init__.py +0 -0
- {ingestr-0.13.1 → ingestr-0.13.3}/ingestr/src/gorgias/helpers.py +0 -0
- {ingestr-0.13.1 → ingestr-0.13.3}/ingestr/src/hubspot/__init__.py +0 -0
- {ingestr-0.13.1 → ingestr-0.13.3}/ingestr/src/hubspot/helpers.py +0 -0
- {ingestr-0.13.1 → ingestr-0.13.3}/ingestr/src/hubspot/settings.py +0 -0
- {ingestr-0.13.1 → ingestr-0.13.3}/ingestr/src/kafka/__init__.py +0 -0
- {ingestr-0.13.1 → ingestr-0.13.3}/ingestr/src/kafka/helpers.py +0 -0
- {ingestr-0.13.1 → ingestr-0.13.3}/ingestr/src/klaviyo/_init_.py +0 -0
- {ingestr-0.13.1 → ingestr-0.13.3}/ingestr/src/klaviyo/client.py +0 -0
- {ingestr-0.13.1 → ingestr-0.13.3}/ingestr/src/klaviyo/helpers.py +0 -0
- {ingestr-0.13.1 → ingestr-0.13.3}/ingestr/src/linkedin_ads/__init__.py +0 -0
- {ingestr-0.13.1 → ingestr-0.13.3}/ingestr/src/linkedin_ads/dimension_time_enum.py +0 -0
- {ingestr-0.13.1 → ingestr-0.13.3}/ingestr/src/linkedin_ads/helpers.py +0 -0
- {ingestr-0.13.1 → ingestr-0.13.3}/ingestr/src/mongodb/__init__.py +0 -0
- {ingestr-0.13.1 → ingestr-0.13.3}/ingestr/src/mongodb/helpers.py +0 -0
- {ingestr-0.13.1 → ingestr-0.13.3}/ingestr/src/notion/__init__.py +0 -0
- {ingestr-0.13.1 → ingestr-0.13.3}/ingestr/src/notion/helpers/__init__.py +0 -0
- {ingestr-0.13.1 → ingestr-0.13.3}/ingestr/src/notion/helpers/client.py +0 -0
- {ingestr-0.13.1 → ingestr-0.13.3}/ingestr/src/notion/helpers/database.py +0 -0
- {ingestr-0.13.1 → ingestr-0.13.3}/ingestr/src/notion/settings.py +0 -0
- {ingestr-0.13.1 → ingestr-0.13.3}/ingestr/src/shopify/__init__.py +0 -0
- {ingestr-0.13.1 → ingestr-0.13.3}/ingestr/src/shopify/exceptions.py +0 -0
- {ingestr-0.13.1 → ingestr-0.13.3}/ingestr/src/shopify/helpers.py +0 -0
- {ingestr-0.13.1 → ingestr-0.13.3}/ingestr/src/shopify/settings.py +0 -0
- {ingestr-0.13.1 → ingestr-0.13.3}/ingestr/src/slack/__init__.py +0 -0
- {ingestr-0.13.1 → ingestr-0.13.3}/ingestr/src/slack/helpers.py +0 -0
- {ingestr-0.13.1 → ingestr-0.13.3}/ingestr/src/slack/settings.py +0 -0
- {ingestr-0.13.1 → ingestr-0.13.3}/ingestr/src/sql_database/__init__.py +0 -0
- {ingestr-0.13.1 → ingestr-0.13.3}/ingestr/src/sql_database/callbacks.py +0 -0
- {ingestr-0.13.1 → ingestr-0.13.3}/ingestr/src/stripe_analytics/__init__.py +0 -0
- {ingestr-0.13.1 → ingestr-0.13.3}/ingestr/src/stripe_analytics/helpers.py +0 -0
- {ingestr-0.13.1 → ingestr-0.13.3}/ingestr/src/stripe_analytics/settings.py +0 -0
- {ingestr-0.13.1 → ingestr-0.13.3}/ingestr/src/table_definition.py +0 -0
- {ingestr-0.13.1 → ingestr-0.13.3}/ingestr/src/telemetry/event.py +0 -0
- {ingestr-0.13.1 → ingestr-0.13.3}/ingestr/src/testdata/fakebqcredentials.json +0 -0
- {ingestr-0.13.1 → ingestr-0.13.3}/ingestr/src/tiktok_ads/__init__.py +0 -0
- {ingestr-0.13.1 → ingestr-0.13.3}/ingestr/src/tiktok_ads/tiktok_helpers.py +0 -0
- {ingestr-0.13.1 → ingestr-0.13.3}/ingestr/src/time.py +0 -0
- {ingestr-0.13.1 → ingestr-0.13.3}/ingestr/src/zendesk/__init__.py +0 -0
- {ingestr-0.13.1 → ingestr-0.13.3}/ingestr/src/zendesk/helpers/__init__.py +0 -0
- {ingestr-0.13.1 → ingestr-0.13.3}/ingestr/src/zendesk/helpers/api_helpers.py +0 -0
- {ingestr-0.13.1 → ingestr-0.13.3}/ingestr/src/zendesk/helpers/credentials.py +0 -0
- {ingestr-0.13.1 → ingestr-0.13.3}/ingestr/src/zendesk/helpers/talk_api.py +0 -0
- {ingestr-0.13.1 → ingestr-0.13.3}/ingestr/src/zendesk/settings.py +0 -0
- {ingestr-0.13.1 → ingestr-0.13.3}/ingestr/testdata/.gitignore +0 -0
- {ingestr-0.13.1 → ingestr-0.13.3}/ingestr/testdata/create_replace.csv +0 -0
- {ingestr-0.13.1 → ingestr-0.13.3}/ingestr/testdata/delete_insert_expected.csv +0 -0
- {ingestr-0.13.1 → ingestr-0.13.3}/ingestr/testdata/delete_insert_part1.csv +0 -0
- {ingestr-0.13.1 → ingestr-0.13.3}/ingestr/testdata/delete_insert_part2.csv +0 -0
- {ingestr-0.13.1 → ingestr-0.13.3}/ingestr/testdata/merge_expected.csv +0 -0
- {ingestr-0.13.1 → ingestr-0.13.3}/ingestr/testdata/merge_part1.csv +0 -0
- {ingestr-0.13.1 → ingestr-0.13.3}/ingestr/testdata/merge_part2.csv +0 -0
- {ingestr-0.13.1 → ingestr-0.13.3}/package-lock.json +0 -0
- {ingestr-0.13.1 → ingestr-0.13.3}/package.json +0 -0
- {ingestr-0.13.1 → ingestr-0.13.3}/pyproject.toml +0 -0
- {ingestr-0.13.1 → ingestr-0.13.3}/requirements-dev.txt +0 -0
- {ingestr-0.13.1 → ingestr-0.13.3}/requirements.txt +0 -0
- {ingestr-0.13.1 → ingestr-0.13.3}/resources/demo.gif +0 -0
- {ingestr-0.13.1 → ingestr-0.13.3}/resources/demo.tape +0 -0
- {ingestr-0.13.1 → ingestr-0.13.3}/resources/ingestr.svg +0 -0
- {ingestr-0.13.1 → ingestr-0.13.3}/styles/Google/AMPM.yml +0 -0
- {ingestr-0.13.1 → ingestr-0.13.3}/styles/Google/Acronyms.yml +0 -0
- {ingestr-0.13.1 → ingestr-0.13.3}/styles/Google/Colons.yml +0 -0
- {ingestr-0.13.1 → ingestr-0.13.3}/styles/Google/Contractions.yml +0 -0
- {ingestr-0.13.1 → ingestr-0.13.3}/styles/Google/DateFormat.yml +0 -0
- {ingestr-0.13.1 → ingestr-0.13.3}/styles/Google/Ellipses.yml +0 -0
- {ingestr-0.13.1 → ingestr-0.13.3}/styles/Google/EmDash.yml +0 -0
- {ingestr-0.13.1 → ingestr-0.13.3}/styles/Google/Exclamation.yml +0 -0
- {ingestr-0.13.1 → ingestr-0.13.3}/styles/Google/FirstPerson.yml +0 -0
- {ingestr-0.13.1 → ingestr-0.13.3}/styles/Google/Gender.yml +0 -0
- {ingestr-0.13.1 → ingestr-0.13.3}/styles/Google/GenderBias.yml +0 -0
- {ingestr-0.13.1 → ingestr-0.13.3}/styles/Google/HeadingPunctuation.yml +0 -0
- {ingestr-0.13.1 → ingestr-0.13.3}/styles/Google/Headings.yml +0 -0
- {ingestr-0.13.1 → ingestr-0.13.3}/styles/Google/Latin.yml +0 -0
- {ingestr-0.13.1 → ingestr-0.13.3}/styles/Google/LyHyphens.yml +0 -0
- {ingestr-0.13.1 → ingestr-0.13.3}/styles/Google/OptionalPlurals.yml +0 -0
- {ingestr-0.13.1 → ingestr-0.13.3}/styles/Google/Ordinal.yml +0 -0
- {ingestr-0.13.1 → ingestr-0.13.3}/styles/Google/OxfordComma.yml +0 -0
- {ingestr-0.13.1 → ingestr-0.13.3}/styles/Google/Parens.yml +0 -0
- {ingestr-0.13.1 → ingestr-0.13.3}/styles/Google/Passive.yml +0 -0
- {ingestr-0.13.1 → ingestr-0.13.3}/styles/Google/Periods.yml +0 -0
- {ingestr-0.13.1 → ingestr-0.13.3}/styles/Google/Quotes.yml +0 -0
- {ingestr-0.13.1 → ingestr-0.13.3}/styles/Google/Ranges.yml +0 -0
- {ingestr-0.13.1 → ingestr-0.13.3}/styles/Google/Semicolons.yml +0 -0
- {ingestr-0.13.1 → ingestr-0.13.3}/styles/Google/Slang.yml +0 -0
- {ingestr-0.13.1 → ingestr-0.13.3}/styles/Google/Spacing.yml +0 -0
- {ingestr-0.13.1 → ingestr-0.13.3}/styles/Google/Spelling.yml +0 -0
- {ingestr-0.13.1 → ingestr-0.13.3}/styles/Google/Units.yml +0 -0
- {ingestr-0.13.1 → ingestr-0.13.3}/styles/Google/We.yml +0 -0
- {ingestr-0.13.1 → ingestr-0.13.3}/styles/Google/Will.yml +0 -0
- {ingestr-0.13.1 → ingestr-0.13.3}/styles/Google/WordList.yml +0 -0
- {ingestr-0.13.1 → ingestr-0.13.3}/styles/Google/meta.json +0 -0
- {ingestr-0.13.1 → ingestr-0.13.3}/styles/Google/vocab.txt +0 -0
- {ingestr-0.13.1 → ingestr-0.13.3}/styles/bruin/Ingestr.yml +0 -0
- {ingestr-0.13.1 → ingestr-0.13.3}/styles/config/vocabularies/bruin/accept.txt +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: ingestr
|
|
3
|
-
Version: 0.13.
|
|
3
|
+
Version: 0.13.3
|
|
4
4
|
Summary: ingestr is a command-line application that ingests data from various sources and stores them in any database.
|
|
5
5
|
Project-URL: Homepage, https://github.com/bruin-data/ingestr
|
|
6
6
|
Project-URL: Issues, https://github.com/bruin-data/ingestr/issues
|
|
@@ -96,6 +96,7 @@ export default defineConfig({
|
|
|
96
96
|
{ text: "Airtable", link: "/supported-sources/airtable.md" },
|
|
97
97
|
{ text: "AppsFlyer", link: "/supported-sources/appsflyer.md" },
|
|
98
98
|
{ text: "Apple App Store", link: "/supported-sources/appstore.md"},
|
|
99
|
+
{ text: "Applovin", link: "/supported-sources/applovin.md"},
|
|
99
100
|
{ text: "Asana", link: "/supported-sources/asana.md" },
|
|
100
101
|
{ text: "Chess.com", link: "/supported-sources/chess.md" },
|
|
101
102
|
{ text: "DynamoDB", link: "/supported-sources/dynamodb.md" },
|
|
@@ -0,0 +1,144 @@
|
|
|
1
|
+
# Applovin
|
|
2
|
+
[AppLovin](https://www.applovin.com/) Corporation is an American mobile technology company headquartered in Palo Alto, California. AppLovin enables developers of all sizes to market, monetize, analyze and publish their apps through its mobile advertising, marketing, and analytics platforms MAX, AppDiscovery, and SparkLabs.
|
|
3
|
+
|
|
4
|
+
`ingestr` allows ingesting data from [AppDiscovery reporting API](https://developers.applovin.com/en/app-discovery/api/reporting-api/)
|
|
5
|
+
|
|
6
|
+
## URI Format
|
|
7
|
+
|
|
8
|
+
The URI format for Applovin is as follows:
|
|
9
|
+
```
|
|
10
|
+
applovin://?api_key=<your_api_key>
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
URI Parameters:
|
|
14
|
+
* `api_key`. report key generated from your [applovin account](https://www.applovin.com/analytics#keys).
|
|
15
|
+
|
|
16
|
+
## Setting up Applovin Integration
|
|
17
|
+
|
|
18
|
+
### Generate a Report Key
|
|
19
|
+
You can generate a report key from your [analytics dashboard](https://www.applovin.com/analytics#keys).
|
|
20
|
+
|
|
21
|
+
### Example: Loading Publisher Report
|
|
22
|
+
|
|
23
|
+
For this example, we'll assume that:
|
|
24
|
+
* `api_key` is `api_key_0`
|
|
25
|
+
|
|
26
|
+
We will run `ingestr` to save this data to a [duckdb](https://duckdb.org/) database called `report.db` under the table name `public.publisher_report`.
|
|
27
|
+
|
|
28
|
+
```sh
|
|
29
|
+
ingestr ingest \
|
|
30
|
+
--source-uri "applovin://?api_key=api_key_0
|
|
31
|
+
--source-table "publisher-report" \
|
|
32
|
+
--dest-uri "duckdb:///report.db" \
|
|
33
|
+
--dest-table "public.publisher_report"
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
### Example: Incremental loading
|
|
37
|
+
|
|
38
|
+
We will extend the [Loading Publisher Report](#example-loading-publisher-report) example to demonstrate incremental loading.
|
|
39
|
+
|
|
40
|
+
First, we run the example with a start date of `2025-01-01` and an end date of `2025-01-05`
|
|
41
|
+
|
|
42
|
+
```sh
|
|
43
|
+
ingestr ingest \
|
|
44
|
+
--source-uri "applovin://?api_key=api_key_0
|
|
45
|
+
--source-table "publisher-report" \
|
|
46
|
+
--dest-uri "duckdb:///report.db" \
|
|
47
|
+
--dest-table "public.publisher_report" \
|
|
48
|
+
--interval-start "2025-01-01" \
|
|
49
|
+
--interval-end "2025-01-05"
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
We can query the database to see which dates the data was ingested for:
|
|
53
|
+
|
|
54
|
+
```sh
|
|
55
|
+
$ duckdb report.db 'select day from public.publisher_report group by 1'
|
|
56
|
+
┌────────────┐
|
|
57
|
+
│ day │
|
|
58
|
+
│ date │
|
|
59
|
+
├────────────┤
|
|
60
|
+
│ 2025-01-01 │
|
|
61
|
+
│ 2025-01-02 │
|
|
62
|
+
│ 2025-01-03 │
|
|
63
|
+
│ 2025-01-04 │
|
|
64
|
+
│ 2025-01-05 │
|
|
65
|
+
└────────────┘
|
|
66
|
+
```
|
|
67
|
+
Now, we will run `ingestr` again, but we will omit start and end date to demonstrate an incremental load.
|
|
68
|
+
|
|
69
|
+
```sh
|
|
70
|
+
ingestr ingest \
|
|
71
|
+
--source-uri "applovin://?api_key=api_key_0
|
|
72
|
+
--source-table "publisher-report" \
|
|
73
|
+
--dest-uri "duckdb:///report.db" \
|
|
74
|
+
--dest-table "public.publisher_report"
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
Now we can check the database again, and we will see that the data was loaded for the rest of the days automatically.
|
|
78
|
+
```sh
|
|
79
|
+
$ duckdb report.db 'select day from public.publisher_report group by 1'
|
|
80
|
+
┌────────────┐
|
|
81
|
+
│ day │
|
|
82
|
+
│ date │
|
|
83
|
+
├────────────┤
|
|
84
|
+
│ 2025-01-01 │
|
|
85
|
+
│ 2025-01-02 │
|
|
86
|
+
│ 2025-01-03 │
|
|
87
|
+
│ 2025-01-04 │
|
|
88
|
+
│ 2025-01-05 │
|
|
89
|
+
│ 2025-01-06 │
|
|
90
|
+
│ . │
|
|
91
|
+
│ . │
|
|
92
|
+
│ . │
|
|
93
|
+
│ 2025-01-28 │
|
|
94
|
+
│ 2025-01-29 │
|
|
95
|
+
│ 2025-01-30 │
|
|
96
|
+
│ 2025-01-31 │
|
|
97
|
+
├────────────┤
|
|
98
|
+
│ 35 rows │
|
|
99
|
+
└────────────┘
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
## Tables
|
|
103
|
+
|
|
104
|
+
| Name | Description |
|
|
105
|
+
| --- | --- |
|
|
106
|
+
| `publisher-report` | Provides daily metrics from the `report` end point using the report_type `publisher` |
|
|
107
|
+
| `advertiser-report` | Provides daily metrics from the `report` end point using the report_type `advertiser`|
|
|
108
|
+
| `advertiser-probabilistic-report` | Provides daily metrics from the `probabilisticReport` end point using the report_type `advertiser` |
|
|
109
|
+
| `advertiser-ska-report` | Provides daily metrics from the `skaReport` end point using the report_type `advertiser` |
|
|
110
|
+
|
|
111
|
+
## Custom Reports
|
|
112
|
+
|
|
113
|
+
`applovin` source supports custom reports. You can pass a custom report definition to `--source-table` and it will dynamically create a report for you.
|
|
114
|
+
|
|
115
|
+
The format of a custom report looks like the following:
|
|
116
|
+
```
|
|
117
|
+
custom:{endpoint}:{report_type}:{columns}
|
|
118
|
+
```
|
|
119
|
+
Where:
|
|
120
|
+
* `{endpoint}` is the API endpoint for applovin reports (one of `report`, `probabilisticReport` or `skaReport`)
|
|
121
|
+
* `{report_type}` is the [report type](https://developers.applovin.com/en/app-discovery/api/reporting-api#required-parameters) (one of `publisher` or `advertiser`)
|
|
122
|
+
* `{columns}` are the [columns](https://developers.applovin.com/en/app-discovery/api/reporting-api#allowed-publisher-columns) of the given report type.
|
|
123
|
+
|
|
124
|
+
|
|
125
|
+
### Custom Report Example
|
|
126
|
+
For this example, we will ingest data from `report` end point with the report type `publisher`.
|
|
127
|
+
|
|
128
|
+
We want to obtain the following columns:
|
|
129
|
+
* ad_type
|
|
130
|
+
* clicks
|
|
131
|
+
* country
|
|
132
|
+
|
|
133
|
+
To achieve this, we can pass the custom report defintion in `--source-table`
|
|
134
|
+
|
|
135
|
+
```sh
|
|
136
|
+
ingestr ingest \
|
|
137
|
+
--source-uri "applovin://?api_key=api_key_0
|
|
138
|
+
--source-table "custom:report:publisher:ad_type,clicks,country" \
|
|
139
|
+
--dest-uri "duckdb:///report.db" \
|
|
140
|
+
--dest-table "public.custom_report"
|
|
141
|
+
```
|
|
142
|
+
|
|
143
|
+
> [!NOTE]
|
|
144
|
+
> The `day` column is automatically added to any custom report if it is not specified in the custom report definition.
|
|
@@ -7,14 +7,15 @@ Ingestr supports ClickHouse as a destination.
|
|
|
7
7
|
The URI format for ClickHouse as a destination is as follows:
|
|
8
8
|
|
|
9
9
|
```plaintext
|
|
10
|
-
clickhouse://<username>:<password>@<host>:<port>?http_port=<http_port>
|
|
10
|
+
clickhouse://<username>:<password>@<host>:<port>?http_port=<http_port>&secure=<secure>
|
|
11
11
|
```
|
|
12
12
|
## URI parameters:
|
|
13
13
|
- `username` (required): The username is required to authenticate with the ClickHouse server.
|
|
14
14
|
- `password` (required): The password is required to authenticate the provided username.
|
|
15
15
|
- `host` (required): The hostname or IP address of the ClickHouse server where the database is hosted.
|
|
16
16
|
- `port` (required): The TCP port number used by the ClickHouse server.
|
|
17
|
-
- `http_port` (optional): The port number to use when connecting to the ClickHouse server's HTTP interface.
|
|
17
|
+
- `http_port` (optional): The port number to use when connecting to the ClickHouse server's HTTP interface.By default, it is set to port `8443`.
|
|
18
|
+
- `secure` (optional): Set to `1` for a secure HTTPS connection or `0` for a non-secure HTTP connection. By default, it is set to `1`.
|
|
18
19
|
|
|
19
20
|
ClickHouse requires a `username`, `password`, `host` and `port` to connect to the ClickHouse server. For more information, read [here](https://dlthub.com/docs/dlt-ecosystem/destinations/clickhouse#2-setup-clickhouse-database). Once you've completed the guide, you should have all the above-mentioned credentials.
|
|
20
21
|
|
|
@@ -0,0 +1,282 @@
|
|
|
1
|
+
from datetime import datetime, timezone
|
|
2
|
+
from enum import Enum
|
|
3
|
+
from typing import Dict, List, Optional
|
|
4
|
+
|
|
5
|
+
import dlt
|
|
6
|
+
from dlt.sources.rest_api import EndpointResource, RESTAPIConfig, rest_api_resources
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
class InvalidCustomReportError(Exception):
|
|
10
|
+
def __init__(self):
|
|
11
|
+
super().__init__(
|
|
12
|
+
"Custom report should be in the format 'custom:{endpoint}:{report_type}:{dimensions}"
|
|
13
|
+
)
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
class InvalidDimensionError(Exception):
|
|
17
|
+
def __init__(self, dim: str, report_type: str):
|
|
18
|
+
super().__init__(f"Unknown dimension {dim} for report type {report_type}")
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
TYPE_HINTS = {
|
|
22
|
+
"application_is_hidden": {"data_type": "bool"},
|
|
23
|
+
"average_cpa": {"data_type": "double"},
|
|
24
|
+
"average_cpc": {"data_type": "double"},
|
|
25
|
+
"campaign_bid_goal": {"data_type": "double"},
|
|
26
|
+
"campaign_roas_goal": {"data_type": "double"},
|
|
27
|
+
"clicks": {"data_type": "bigint"},
|
|
28
|
+
"conversions": {"data_type": "bigint"},
|
|
29
|
+
"conversion_rate": {"data_type": "double"},
|
|
30
|
+
"cost": {"data_type": "double"}, # assuming float.
|
|
31
|
+
"ctr": {"data_type": "double"},
|
|
32
|
+
"day": {"data_type": "date"},
|
|
33
|
+
"first_purchase": {"data_type": "bigint"},
|
|
34
|
+
"ecpm": {"data_type": "double"},
|
|
35
|
+
"impressions": {"data_type": "bigint"},
|
|
36
|
+
"installs": {"data_type": "bigint"},
|
|
37
|
+
"revenue": {"data_type": "double"},
|
|
38
|
+
"redownloads": {"data_type": "bigint"},
|
|
39
|
+
"sales": {"data_type": "double"}, # assuming float.
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
class ReportType(Enum):
|
|
44
|
+
PUBLISHER = "publisher"
|
|
45
|
+
ADVERTISER = "advertiser"
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
REPORT_SCHEMA: Dict[ReportType, List[str]] = {
|
|
49
|
+
ReportType.PUBLISHER: [
|
|
50
|
+
"ad_type",
|
|
51
|
+
"application",
|
|
52
|
+
"application_is_hidden",
|
|
53
|
+
"bidding_integration",
|
|
54
|
+
"clicks",
|
|
55
|
+
"country",
|
|
56
|
+
"ctr",
|
|
57
|
+
"day",
|
|
58
|
+
"device_type",
|
|
59
|
+
"ecpm",
|
|
60
|
+
"impressions",
|
|
61
|
+
"package_name",
|
|
62
|
+
"placement_type",
|
|
63
|
+
"platform",
|
|
64
|
+
"revenue",
|
|
65
|
+
"size",
|
|
66
|
+
"store_id",
|
|
67
|
+
"zone",
|
|
68
|
+
"zone_id",
|
|
69
|
+
],
|
|
70
|
+
ReportType.ADVERTISER: [
|
|
71
|
+
"ad",
|
|
72
|
+
"ad_creative_type",
|
|
73
|
+
"ad_id",
|
|
74
|
+
"ad_type",
|
|
75
|
+
"average_cpa",
|
|
76
|
+
"average_cpc",
|
|
77
|
+
"campaign",
|
|
78
|
+
"campaign_ad_type",
|
|
79
|
+
"campaign_bid_goal",
|
|
80
|
+
"campaign_id_external",
|
|
81
|
+
"campaign_package_name",
|
|
82
|
+
"campaign_roas_goal",
|
|
83
|
+
"campaign_store_id",
|
|
84
|
+
"campaign_type",
|
|
85
|
+
"clicks",
|
|
86
|
+
"conversions",
|
|
87
|
+
"conversion_rate",
|
|
88
|
+
"cost",
|
|
89
|
+
"country",
|
|
90
|
+
"creative_set",
|
|
91
|
+
"creative_set_id",
|
|
92
|
+
"ctr",
|
|
93
|
+
"custom_page_id",
|
|
94
|
+
"day",
|
|
95
|
+
"device_type",
|
|
96
|
+
"external_placement_id",
|
|
97
|
+
"first_purchase",
|
|
98
|
+
"impressions",
|
|
99
|
+
"installs",
|
|
100
|
+
"optimization_day_target",
|
|
101
|
+
"placement_type",
|
|
102
|
+
"platform",
|
|
103
|
+
"redownloads",
|
|
104
|
+
"sales",
|
|
105
|
+
"size",
|
|
106
|
+
"target_event",
|
|
107
|
+
"traffic_source",
|
|
108
|
+
],
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
# NOTE(turtledev): These values are valid columns,
|
|
112
|
+
# but often don't produce a value. Find a way to either add
|
|
113
|
+
# a default value, or use an alternative strategy to de-duplicate
|
|
114
|
+
# OR make them nullable
|
|
115
|
+
SKA_REPORT_EXCLUDE = [
|
|
116
|
+
"ad",
|
|
117
|
+
"ad_id",
|
|
118
|
+
"ad_type",
|
|
119
|
+
"average_cpc",
|
|
120
|
+
"campaign_ad_type",
|
|
121
|
+
"clicks",
|
|
122
|
+
"conversions",
|
|
123
|
+
"conversion_rate",
|
|
124
|
+
"creative_set",
|
|
125
|
+
"creative_set_id",
|
|
126
|
+
"ctr",
|
|
127
|
+
"custom_page_id",
|
|
128
|
+
"device_type",
|
|
129
|
+
"first_purchase",
|
|
130
|
+
"impressions",
|
|
131
|
+
"placement_type",
|
|
132
|
+
"sales",
|
|
133
|
+
"size",
|
|
134
|
+
"traffic_source",
|
|
135
|
+
]
|
|
136
|
+
|
|
137
|
+
PROBABILISTIC_REPORT_EXCLUDE = [
|
|
138
|
+
"installs",
|
|
139
|
+
"redownloads",
|
|
140
|
+
]
|
|
141
|
+
|
|
142
|
+
|
|
143
|
+
@dlt.source
|
|
144
|
+
def applovin_source(
|
|
145
|
+
api_key: str,
|
|
146
|
+
start_date: str,
|
|
147
|
+
end_date: Optional[str],
|
|
148
|
+
custom: Optional[str],
|
|
149
|
+
):
|
|
150
|
+
ska_report_columns = exclude(
|
|
151
|
+
REPORT_SCHEMA[ReportType.ADVERTISER],
|
|
152
|
+
SKA_REPORT_EXCLUDE,
|
|
153
|
+
)
|
|
154
|
+
|
|
155
|
+
probabilistic_report_columns = exclude(
|
|
156
|
+
REPORT_SCHEMA[ReportType.ADVERTISER],
|
|
157
|
+
PROBABILISTIC_REPORT_EXCLUDE,
|
|
158
|
+
)
|
|
159
|
+
backfill = False
|
|
160
|
+
if end_date is None:
|
|
161
|
+
backfill = True
|
|
162
|
+
end_date = datetime.now(timezone.utc).date().strftime("%Y-%m-%d")
|
|
163
|
+
|
|
164
|
+
config: RESTAPIConfig = {
|
|
165
|
+
"client": {
|
|
166
|
+
"base_url": "https://r.applovin.com/",
|
|
167
|
+
"auth": {
|
|
168
|
+
"type": "api_key",
|
|
169
|
+
"name": "api_key",
|
|
170
|
+
"location": "query",
|
|
171
|
+
"api_key": api_key,
|
|
172
|
+
},
|
|
173
|
+
},
|
|
174
|
+
"resource_defaults": {
|
|
175
|
+
"write_disposition": "merge",
|
|
176
|
+
"endpoint": {
|
|
177
|
+
"incremental": {
|
|
178
|
+
"cursor_path": "day",
|
|
179
|
+
"start_param": "start",
|
|
180
|
+
"initial_value": start_date,
|
|
181
|
+
"range_start": "closed",
|
|
182
|
+
"range_end": "closed",
|
|
183
|
+
},
|
|
184
|
+
"params": {
|
|
185
|
+
"format": "json",
|
|
186
|
+
"end": end_date,
|
|
187
|
+
},
|
|
188
|
+
"paginator": "single_page",
|
|
189
|
+
},
|
|
190
|
+
},
|
|
191
|
+
"resources": [
|
|
192
|
+
resource(
|
|
193
|
+
"publisher-report",
|
|
194
|
+
"report",
|
|
195
|
+
REPORT_SCHEMA[ReportType.PUBLISHER],
|
|
196
|
+
ReportType.PUBLISHER,
|
|
197
|
+
),
|
|
198
|
+
resource(
|
|
199
|
+
"advertiser-report",
|
|
200
|
+
"report",
|
|
201
|
+
REPORT_SCHEMA[ReportType.ADVERTISER],
|
|
202
|
+
ReportType.ADVERTISER,
|
|
203
|
+
),
|
|
204
|
+
resource(
|
|
205
|
+
"advertiser-probabilistic-report",
|
|
206
|
+
"probabilisticReport",
|
|
207
|
+
probabilistic_report_columns,
|
|
208
|
+
ReportType.ADVERTISER,
|
|
209
|
+
),
|
|
210
|
+
resource(
|
|
211
|
+
"advertiser-ska-report",
|
|
212
|
+
"skaReport",
|
|
213
|
+
ska_report_columns,
|
|
214
|
+
ReportType.ADVERTISER,
|
|
215
|
+
),
|
|
216
|
+
],
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
if custom:
|
|
220
|
+
custom_report = custom_report_from_spec(custom)
|
|
221
|
+
config["resources"].append(custom_report)
|
|
222
|
+
|
|
223
|
+
if backfill:
|
|
224
|
+
config["resource_defaults"]["endpoint"]["incremental"]["end_value"] = end_date # type: ignore
|
|
225
|
+
|
|
226
|
+
yield from rest_api_resources(config)
|
|
227
|
+
|
|
228
|
+
|
|
229
|
+
def resource(
|
|
230
|
+
name: str,
|
|
231
|
+
endpoint: str,
|
|
232
|
+
dimensions: List[str],
|
|
233
|
+
report_type: ReportType,
|
|
234
|
+
) -> EndpointResource:
|
|
235
|
+
return {
|
|
236
|
+
"name": name,
|
|
237
|
+
"columns": build_type_hints(dimensions),
|
|
238
|
+
"merge_key": "day",
|
|
239
|
+
"endpoint": {
|
|
240
|
+
"path": endpoint,
|
|
241
|
+
"params": {
|
|
242
|
+
"report_type": report_type.value,
|
|
243
|
+
"columns": ",".join(dimensions),
|
|
244
|
+
},
|
|
245
|
+
},
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
|
|
249
|
+
def custom_report_from_spec(spec: str) -> EndpointResource:
|
|
250
|
+
parts = spec.split(":")
|
|
251
|
+
if len(parts) != 4:
|
|
252
|
+
raise InvalidCustomReportError()
|
|
253
|
+
|
|
254
|
+
_, endpoint, report, dims = parts
|
|
255
|
+
report_type = ReportType(report.strip())
|
|
256
|
+
dimensions = validate_dimensions(dims)
|
|
257
|
+
endpoint = endpoint.strip()
|
|
258
|
+
|
|
259
|
+
return resource(
|
|
260
|
+
name="custom_report",
|
|
261
|
+
endpoint=endpoint,
|
|
262
|
+
dimensions=dimensions,
|
|
263
|
+
report_type=report_type,
|
|
264
|
+
)
|
|
265
|
+
|
|
266
|
+
|
|
267
|
+
def validate_dimensions(dimensions: str) -> List[str]:
|
|
268
|
+
dims = [dim.strip() for dim in dimensions.split(",")]
|
|
269
|
+
|
|
270
|
+
if "day" not in dims:
|
|
271
|
+
dims.append("day")
|
|
272
|
+
|
|
273
|
+
return dims
|
|
274
|
+
|
|
275
|
+
|
|
276
|
+
def exclude(source: List[str], exclude_list: List[str]) -> List[str]:
|
|
277
|
+
excludes = set(exclude_list)
|
|
278
|
+
return [col for col in source if col not in excludes]
|
|
279
|
+
|
|
280
|
+
|
|
281
|
+
def build_type_hints(cols: List[str]) -> dict:
|
|
282
|
+
return {col: TYPE_HINTS[col] for col in cols if col in TYPE_HINTS}
|
|
@@ -299,10 +299,21 @@ class ClickhouseDestination:
|
|
|
299
299
|
)
|
|
300
300
|
|
|
301
301
|
query_params = parse_qs(parsed_uri.query)
|
|
302
|
+
secure = int(query_params["secure"][0]) if "secure" in query_params else 1
|
|
303
|
+
|
|
302
304
|
http_port = (
|
|
303
|
-
int(query_params["http_port"][0])
|
|
305
|
+
int(query_params["http_port"][0])
|
|
306
|
+
if "http_port" in query_params
|
|
307
|
+
else 8443
|
|
308
|
+
if secure == 1
|
|
309
|
+
else 8123
|
|
304
310
|
)
|
|
305
311
|
|
|
312
|
+
if secure not in (0, 1):
|
|
313
|
+
raise ValueError(
|
|
314
|
+
"Invalid value for secure. Set to `1` for a secure HTTPS connection or `0` for a non-secure HTTP connection."
|
|
315
|
+
)
|
|
316
|
+
|
|
306
317
|
credentials = ClickHouseCredentials(
|
|
307
318
|
{
|
|
308
319
|
"host": host,
|
|
@@ -311,10 +322,9 @@ class ClickhouseDestination:
|
|
|
311
322
|
"password": password,
|
|
312
323
|
"database": database,
|
|
313
324
|
"http_port": http_port,
|
|
314
|
-
"secure":
|
|
325
|
+
"secure": secure,
|
|
315
326
|
}
|
|
316
327
|
)
|
|
317
|
-
|
|
318
328
|
return dlt.destinations.clickhouse(credentials=credentials)
|
|
319
329
|
|
|
320
330
|
def dlt_run_params(self, uri: str, table: str, **kwargs) -> dict:
|
|
@@ -20,6 +20,7 @@ from ingestr.src.sources import (
|
|
|
20
20
|
AdjustSource,
|
|
21
21
|
AirtableSource,
|
|
22
22
|
AppleAppStoreSource,
|
|
23
|
+
AppLovinSource,
|
|
23
24
|
AppsflyerSource,
|
|
24
25
|
ArrowMemoryMappedSource,
|
|
25
26
|
AsanaSource,
|
|
@@ -131,6 +132,7 @@ class SourceDestinationFactory:
|
|
|
131
132
|
"appstore": AppleAppStoreSource,
|
|
132
133
|
"gs": GCSSource,
|
|
133
134
|
"linkedinads": LinkedInAdsSource,
|
|
135
|
+
"applovin": AppLovinSource,
|
|
134
136
|
}
|
|
135
137
|
destinations: Dict[str, Type[DestinationProtocol]] = {
|
|
136
138
|
"bigquery": BigQueryDestination,
|
|
@@ -50,6 +50,7 @@ from ingestr.src import blob
|
|
|
50
50
|
from ingestr.src.adjust import REQUIRED_CUSTOM_DIMENSIONS, adjust_source
|
|
51
51
|
from ingestr.src.adjust.adjust_helpers import parse_filters
|
|
52
52
|
from ingestr.src.airtable import airtable_source
|
|
53
|
+
from ingestr.src.applovin import applovin_source
|
|
53
54
|
from ingestr.src.appsflyer._init_ import appsflyer_source
|
|
54
55
|
from ingestr.src.appstore import app_store
|
|
55
56
|
from ingestr.src.appstore.client import AppStoreConnectClient
|
|
@@ -1737,3 +1738,47 @@ class LinkedInAdsSource:
|
|
|
1737
1738
|
metrics=metrics,
|
|
1738
1739
|
time_granularity=time_granularity,
|
|
1739
1740
|
).with_resources("custom_reports")
|
|
1741
|
+
|
|
1742
|
+
|
|
1743
|
+
class AppLovinSource:
|
|
1744
|
+
def handles_incrementality(self) -> bool:
|
|
1745
|
+
return True
|
|
1746
|
+
|
|
1747
|
+
def dlt_source(self, uri: str, table: str, **kwargs):
|
|
1748
|
+
if kwargs.get("incremental_key") is not None:
|
|
1749
|
+
raise ValueError(
|
|
1750
|
+
"Google Ads takes care of incrementality on its own, you should not provide incremental_key"
|
|
1751
|
+
)
|
|
1752
|
+
|
|
1753
|
+
parsed_uri = urlparse(uri)
|
|
1754
|
+
params = parse_qs(parsed_uri.query)
|
|
1755
|
+
|
|
1756
|
+
api_key = params.get("api_key", None)
|
|
1757
|
+
if api_key is None:
|
|
1758
|
+
raise MissingValueError("api_key", "AppLovin")
|
|
1759
|
+
|
|
1760
|
+
interval_start = kwargs.get("interval_start")
|
|
1761
|
+
interval_end = kwargs.get("interval_end")
|
|
1762
|
+
|
|
1763
|
+
now = datetime.now()
|
|
1764
|
+
start_date = (
|
|
1765
|
+
interval_start if interval_start is not None else now - timedelta(days=1)
|
|
1766
|
+
)
|
|
1767
|
+
end_date = interval_end
|
|
1768
|
+
|
|
1769
|
+
custom_report = None
|
|
1770
|
+
if table.startswith("custom:"):
|
|
1771
|
+
custom_report = table
|
|
1772
|
+
table = "custom_report"
|
|
1773
|
+
|
|
1774
|
+
src = applovin_source(
|
|
1775
|
+
api_key[0],
|
|
1776
|
+
start_date.strftime("%Y-%m-%d"),
|
|
1777
|
+
end_date.strftime("%Y-%m-%d") if end_date else None,
|
|
1778
|
+
custom_report,
|
|
1779
|
+
)
|
|
1780
|
+
|
|
1781
|
+
if table not in src.resources:
|
|
1782
|
+
raise UnsupportedResourceError(table, "AppLovin")
|
|
1783
|
+
|
|
1784
|
+
return src.with_resources(table)
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
__version__ = "0.13.3"
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
__version__ = "0.13.1"
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|