From 0a1b63fe38a7183b683a31837f62ca96c4da9bc4 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 14 Nov 2023 15:57:07 -0500 Subject: [PATCH 01/10] Bump requests from 2.20.0 to 2.31.0 (#50) * Bump requests from 2.20.0 to 2.31.0 Bumps [requests](https://github.com/psf/requests) from 2.20.0 to 2.31.0. - [Release notes](https://github.com/psf/requests/releases) - [Changelog](https://github.com/psf/requests/blob/main/HISTORY.md) - [Commits](https://github.com/psf/requests/compare/v2.20.0...v2.31.0) --- updated-dependencies: - dependency-name: requests dependency-type: direct:production ... Signed-off-by: dependabot[bot] * Bump version, update changelog --------- Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Andy Lu --- CHANGELOG.md | 5 ++++- setup.py | 6 +++--- 2 files changed, 7 insertions(+), 4 deletions(-) mode change 100755 => 100644 setup.py diff --git a/CHANGELOG.md b/CHANGELOG.md index 0248a07..de044d1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,8 @@ # Changelog ## 0.4.0 +## 0.4.1 + * Dependabot update [#50](https://github.com/singer-io/tap-zendesk-chat/pull/50) + * Code Refactoring [#45](https://github.com/singer-io/tap-zendesk-chat/pull/45) - Improved directory structure @@ -52,4 +55,4 @@ * Lowers the chat interval days retrieved to 14 to account for a 10k search result limit [#8](https://github.com/singer-io/tap-zendesk-chat/pull/8) ## 0.1.12 - * Allow chat interval days to be specified as a string in the config [#10](https://github.com/singer-io/tap-zendesk-chat/pull/10) + * Allow chat interval days to be specified as a string in the config [#10](https://github.com/singer-io/tap-zendesk-chat/pull/10) \ No newline at end of file diff --git a/setup.py b/setup.py old mode 100755 new mode 100644 index 76a55a0..cda1d62 --- a/setup.py +++ b/setup.py @@ -3,7 +3,7 @@ setup( name="tap-zendesk-chat", - version="0.4.0", + version="0.4.1", description="Singer.io tap for extracting data from the Zendesk Chat API", author="Stitch", url="https://singer.io", @@ -11,7 +11,7 @@ py_modules=["tap_zendesk_chat"], install_requires=[ "singer-python==5.12.1", - "requests==2.20.0", + "requests==2.31.0", ], extras_require={"dev": ["pylint", "ipdb", "nose"]}, entry_points=""" @@ -21,4 +21,4 @@ packages=find_packages(exclude=["tests"]), package_data={"schemas": ["tap_zendesk_chat/schemas/*.json"]}, include_package_data=True, -) +) \ No newline at end of file From 05101dcd0edff453e98a40af67ae84ec4afbe015 Mon Sep 17 00:00:00 2001 From: Eivin Giske Skaaren Date: Tue, 3 Sep 2024 12:27:53 +0200 Subject: [PATCH 02/10] Enable copilot usage in PR template according to Qlik policy --- .github/pull_request_template.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md index 58b80a3..938cd6d 100644 --- a/.github/pull_request_template.md +++ b/.github/pull_request_template.md @@ -9,3 +9,7 @@ # Rollback steps - revert this branch + +#### AI generated code +https://internal.qlik.dev/general/ways-of-working/code-reviews/#guidelines-for-ai-generated-code +- [ ] this PR has been written with the help of GitHub Copilot or another generative AI tool From 66a8384cb20b92c20e5cdabd3c4f4f75cc94c733 Mon Sep 17 00:00:00 2001 From: Vishal Pachpinde Date: Tue, 29 Oct 2024 13:48:15 +0530 Subject: [PATCH 03/10] Add support for subdomain (#52) * changed tap-impl for support to subdomain * updated discovery test * updated changelog and setup --------- Co-authored-by: Vi6hal <20889199+Vi6hal@users.noreply.github.com> --- .circleci/config.yml | 2 +- CHANGELOG.md | 7 +++-- setup.py | 2 +- tap_zendesk_chat/http.py | 37 ++++++++++++++++++++++++-- tap_zendesk_chat/streams.py | 1 + tests/unittests/test_auth_discovery.py | 17 +++++++++--- 6 files changed, 56 insertions(+), 10 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index c693ea8..25ff1d4 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -21,7 +21,7 @@ jobs: command: | source dev_env.sh source /usr/local/share/virtualenvs/tap-zendesk-chat/bin/activate - pylint tap_zendesk_chat -d "$PYLINT_DISABLE_LIST,no-self-use" + pylint tap_zendesk_chat -d "$PYLINT_DISABLE_LIST" - run: name: 'JSON Validator' command: | diff --git a/CHANGELOG.md b/CHANGELOG.md index de044d1..98f862d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,9 +1,12 @@ # Changelog -## 0.4.0 + +## 0.5.0 + * Zendesk Domain Change [#52](https://github.com/singer-io/tap-zendesk-chat/pull/52) + ## 0.4.1 * Dependabot update [#50](https://github.com/singer-io/tap-zendesk-chat/pull/50) - +## 0.4.0 * Code Refactoring [#45](https://github.com/singer-io/tap-zendesk-chat/pull/45) - Improved directory structure - Added pagination support to BANS stream diff --git a/setup.py b/setup.py index cda1d62..510a4f9 100644 --- a/setup.py +++ b/setup.py @@ -3,7 +3,7 @@ setup( name="tap-zendesk-chat", - version="0.4.1", + version="0.5.0", description="Singer.io tap for extracting data from the Zendesk Chat API", author="Stitch", url="https://singer.io", diff --git a/tap_zendesk_chat/http.py b/tap_zendesk_chat/http.py index a9239b3..1bd1934 100644 --- a/tap_zendesk_chat/http.py +++ b/tap_zendesk_chat/http.py @@ -9,21 +9,54 @@ class RateLimitException(Exception): pass +class InvalidConfigurationError(Exception): + pass + class Client: def __init__(self, config): self.access_token = config["access_token"] self.user_agent = config.get("user_agent", "tap-zendesk-chat") self.headers = {} + self.subdomain = config.get("subdomain") self.headers["Authorization"] = f"Bearer {self.access_token}" self.headers["User-Agent"] = self.user_agent + self.base_url = self.get_base_url() self.session = requests.Session() + def get_base_url(self): + """ + Determines the base URL to use for Zendesk API requests. + + Checks the availability of zendesk chat endpoints + and returns the available one + Returns: + str: The base URL to use for subsequent API requests. + + Raises: + InvalidConfigurationError: If neither endpoint is accessible. + """ + urls = [ + (f"https://{self.subdomain}.zendesk.com" , "/api/v2/chat/agents"), + (BASE_URL , "/api/v2/agents") + ] + if not self.subdomain: + # return base url incase of missing subdomain + return BASE_URL + for domain, endpoint in urls: + resp = requests.get(f"{domain}{endpoint}", headers=self.headers, timeout=25) + LOGGER.info("API CHECK %s %s", resp.url, resp.status_code) + if resp.status_code == 200: + return domain + raise InvalidConfigurationError("Please check the URL or reauthenticate") + @backoff.on_exception(backoff.expo, RateLimitException, max_tries=10, factor=2) def request(self, tap_stream_id, params=None, url=None, url_extra=""): with metrics.http_request_timer(tap_stream_id) as timer: - - url = url or f"{BASE_URL}/api/v2/{tap_stream_id}{url_extra}" + if self.base_url == BASE_URL: + url = url or f"{self.base_url}/api/v2/{tap_stream_id}{url_extra}" + else: + url = url or f"{self.base_url}/api/v2/chat/{tap_stream_id}{url_extra}" LOGGER.info("calling %s %s", url, params) response = self.session.get(url, headers=self.headers, params=params) timer.tags[metrics.Tag.http_status_code] = response.status_code diff --git a/tap_zendesk_chat/streams.py b/tap_zendesk_chat/streams.py index b3f94a2..829f89f 100644 --- a/tap_zendesk_chat/streams.py +++ b/tap_zendesk_chat/streams.py @@ -116,6 +116,7 @@ def _bulk_chats(self, ctx, chat_ids: List): body = ctx.client.request(self.tap_stream_id, params=params) return list(body["docs"].values()) + # pylint: disable=too-many-positional-arguments def _pull(self, ctx, chat_type, ts_field, full_sync, schema: Dict, stream_metadata: Dict, transformer: Transformer): """Pulls and writes pages of data for the given chat_type, where chat_type can be either "chat" or "offline_msg". diff --git a/tests/unittests/test_auth_discovery.py b/tests/unittests/test_auth_discovery.py index 52c173e..090ac67 100644 --- a/tests/unittests/test_auth_discovery.py +++ b/tests/unittests/test_auth_discovery.py @@ -4,7 +4,7 @@ from requests.exceptions import HTTPError import tap_zendesk_chat -from tap_zendesk_chat.http import Client +from tap_zendesk_chat.http import Client, InvalidConfigurationError # Mock args @@ -13,6 +13,7 @@ def __init__(self): self.discover = True self.properties = False self.config = {"access_token": "abc-def"} + self.config_wd_subdomain = {"access_token": "abc-def", "subdomain":"test"} self.state = False self.properties = {} @@ -43,9 +44,16 @@ def test_basic_auth_no_access_401(self): with self.assertRaises(HTTPError) as e: tap_zendesk_chat.discover(args.config) - # Verifying the message formed for the custom exception - expected_error_message = "401 Client Error: Unauthorized for url:" - self.assertIn(expected_error_message, str(e.exception)) + # Verifying the message formed for the custom exception + expected_error_message = "401 Client Error: Unauthorized for url:" + self.assertIn(expected_error_message, str(e.exception)) + + expected_error_message = "Please check the URL or reauthenticate" + + with self.assertRaises(InvalidConfigurationError) as e: + tap_zendesk_chat.discover(args.config_wd_subdomain) + self.assertIn(expected_error_message, str(e.exception)) + @mock.patch("tap_zendesk_chat.utils", return_value=Args()) @mock.patch("singer.catalog.Catalog.from_dict", return_value={"key": "value"}) @@ -63,6 +71,7 @@ def test_discovery(self, mock_utils, mock_catalog, mock_request): self.assertEqual(tap_zendesk_chat.discover(Args().config), expected) + class TestAccountEndpointAuthorized(unittest.TestCase): def test_is_account_not_authorized_404(self): """tests if account_not_authorized method in discover raises http From 06ce4cc7c648174aabc661fcc1dbc06f134467aa Mon Sep 17 00:00:00 2001 From: Vishal Pachpinde Date: Thu, 16 Jan 2025 21:22:57 +0530 Subject: [PATCH 04/10] Fix Timestamp issue with chats endpoint (#54) * fix: removed time zone info from start and end time for chats stream * updated changelog and setup.py * dependabot fix and bump version changes --------- Co-authored-by: Bubba Co-authored-by: Rutuja Deshmukh --- CHANGELOG.md | 4 ++++ setup.py | 4 ++-- tap_zendesk_chat/streams.py | 2 +- 3 files changed, 7 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 98f862d..311c4b5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,9 @@ # Changelog +## 0.5.1 + * Bug Fix with chats stream [#54](https://github.com/singer-io/tap-zendesk-chat/pull/54) + * Dependabot update + ## 0.5.0 * Zendesk Domain Change [#52](https://github.com/singer-io/tap-zendesk-chat/pull/52) diff --git a/setup.py b/setup.py index 510a4f9..d9002b8 100644 --- a/setup.py +++ b/setup.py @@ -3,7 +3,7 @@ setup( name="tap-zendesk-chat", - version="0.5.0", + version="0.5.1", description="Singer.io tap for extracting data from the Zendesk Chat API", author="Stitch", url="https://singer.io", @@ -11,7 +11,7 @@ py_modules=["tap_zendesk_chat"], install_requires=[ "singer-python==5.12.1", - "requests==2.31.0", + "requests==2.32.3", ], extras_require={"dev": ["pylint", "ipdb", "nose"]}, entry_points=""" diff --git a/tap_zendesk_chat/streams.py b/tap_zendesk_chat/streams.py index 829f89f..b2ea7d0 100644 --- a/tap_zendesk_chat/streams.py +++ b/tap_zendesk_chat/streams.py @@ -145,7 +145,7 @@ def _pull(self, ctx, chat_type, ts_field, full_sync, schema: Dict, stream_metada if next_url: search_resp = ctx.client.request(self.tap_stream_id, url=next_url) else: - params = {"q": f"type:{chat_type} AND {ts_field}:[{start_dt.isoformat()} TO {end_dt.isoformat()}]"} + params = {"q": f"type:{chat_type} AND {ts_field}:[{start_dt.replace(tzinfo=None).isoformat()} TO {end_dt.replace(tzinfo=None).isoformat()}]"} search_resp = ctx.client.request(self.tap_stream_id, params=params, url_extra="/search") next_url = search_resp["next_url"] From cd214441806ab1f5bf9cb60eed3386aa1a1324e5 Mon Sep 17 00:00:00 2001 From: William Mattern Date: Fri, 17 Jan 2025 10:12:27 -0500 Subject: [PATCH 05/10] gitignore idea files --- .gitignore | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/.gitignore b/.gitignore index 6a1a7e9..93b90cb 100644 --- a/.gitignore +++ b/.gitignore @@ -89,3 +89,7 @@ config.json !.vscode/launch.json !.vscode/extensions.json *.code-workspace + + +# JetBrains +.idea/* From 8e22b2ba4e25e18e97fa8e115300f7e0106c9589 Mon Sep 17 00:00:00 2001 From: William Mattern Date: Fri, 17 Jan 2025 16:48:31 -0500 Subject: [PATCH 06/10] fixing too many positional args --- tap_zendesk_chat/streams.py | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/tap_zendesk_chat/streams.py b/tap_zendesk_chat/streams.py index b2ea7d0..a9d3d13 100644 --- a/tap_zendesk_chat/streams.py +++ b/tap_zendesk_chat/streams.py @@ -116,8 +116,7 @@ def _bulk_chats(self, ctx, chat_ids: List): body = ctx.client.request(self.tap_stream_id, params=params) return list(body["docs"].values()) - # pylint: disable=too-many-positional-arguments - def _pull(self, ctx, chat_type, ts_field, full_sync, schema: Dict, stream_metadata: Dict, transformer: Transformer): + def _pull(self, *, ctx, chat_type, ts_field, full_sync, schema: Dict, stream_metadata: Dict, transformer: Transformer): """Pulls and writes pages of data for the given chat_type, where chat_type can be either "chat" or "offline_msg". @@ -181,18 +180,18 @@ def _should_run_full_sync(self, ctx) -> bool: def sync(self, ctx, schema: Dict, stream_metadata: Dict, transformer: Transformer): full_sync = self._should_run_full_sync(ctx) self._pull( - ctx, - "chat", - "end_timestamp", + ctx=ctx, + chat_type="chat", + ts_field="end_timestamp", full_sync=full_sync, schema=schema, stream_metadata=stream_metadata, transformer=transformer, ) self._pull( - ctx, - "offline_msg", - "timestamp", + ctx=ctx, + chat_type="offline_msg", + ts_field="timestamp", full_sync=full_sync, schema=schema, stream_metadata=stream_metadata, @@ -237,3 +236,4 @@ class Triggers(BaseStream): Shortcuts.tap_stream_id: Shortcuts, Triggers.tap_stream_id: Triggers, } + From 19b2a1197beeef4f95710687f11e0e4e60939755 Mon Sep 17 00:00:00 2001 From: William Mattern Date: Tue, 21 Jan 2025 16:22:52 -0500 Subject: [PATCH 07/10] fix EOF newline --- tap_zendesk_chat/streams.py | 1 - 1 file changed, 1 deletion(-) diff --git a/tap_zendesk_chat/streams.py b/tap_zendesk_chat/streams.py index 95cdbb7..4de7654 100644 --- a/tap_zendesk_chat/streams.py +++ b/tap_zendesk_chat/streams.py @@ -238,4 +238,3 @@ class Triggers(BaseStream): Triggers.tap_stream_id: Triggers, } - From b93e5e743967acf0b37242b8b94bdda2d8b6190e Mon Sep 17 00:00:00 2001 From: William Mattern Date: Tue, 21 Jan 2025 16:24:37 -0500 Subject: [PATCH 08/10] fix EOF newline --- setup.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/setup.py b/setup.py index d9002b8..f99bf6b 100644 --- a/setup.py +++ b/setup.py @@ -21,4 +21,5 @@ packages=find_packages(exclude=["tests"]), package_data={"schemas": ["tap_zendesk_chat/schemas/*.json"]}, include_package_data=True, -) \ No newline at end of file +) + From 29ae3904b11d274bab5a69bdb73788958e27a2ff Mon Sep 17 00:00:00 2001 From: William Mattern Date: Tue, 21 Jan 2025 16:25:22 -0500 Subject: [PATCH 09/10] fix EOF newline From bfc7cab4f39d36b526e50247a9f63aa995e873d7 Mon Sep 17 00:00:00 2001 From: William Mattern Date: Tue, 21 Jan 2025 16:25:36 -0500 Subject: [PATCH 10/10] fix EOF newline --- setup.py | 1 - 1 file changed, 1 deletion(-) diff --git a/setup.py b/setup.py index f99bf6b..d16ab3c 100644 --- a/setup.py +++ b/setup.py @@ -22,4 +22,3 @@ package_data={"schemas": ["tap_zendesk_chat/schemas/*.json"]}, include_package_data=True, ) -