discolike-cli 0.1.0__tar.gz → 0.2.0__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.
- discolike_cli-0.2.0/LICENSE +21 -0
- {discolike_cli-0.1.0 → discolike_cli-0.2.0}/PKG-INFO +14 -6
- {discolike_cli-0.1.0 → discolike_cli-0.2.0}/README.md +3 -3
- {discolike_cli-0.1.0 → discolike_cli-0.2.0}/pyproject.toml +12 -2
- {discolike_cli-0.1.0 → discolike_cli-0.2.0}/src/discolike_cli/_output.py +26 -8
- discolike_cli-0.2.0/src/discolike_cli/account.py +22 -0
- discolike_cli-0.2.0/src/discolike_cli/auth.py +81 -0
- discolike_cli-0.2.0/src/discolike_cli/company.py +121 -0
- discolike_cli-0.2.0/src/discolike_cli/contacts.py +310 -0
- discolike_cli-0.2.0/src/discolike_cli/discogen.py +150 -0
- discolike_cli-0.2.0/src/discolike_cli/discover.py +144 -0
- discolike_cli-0.2.0/src/discolike_cli/email.py +166 -0
- discolike_cli-0.2.0/src/discolike_cli/enrich.py +111 -0
- {discolike_cli-0.1.0 → discolike_cli-0.2.0}/src/discolike_cli/main.py +18 -5
- discolike_cli-0.2.0/src/discolike_cli/match.py +63 -0
- discolike_cli-0.2.0/src/discolike_cli/providers.py +246 -0
- discolike_cli-0.2.0/src/discolike_cli/py.typed +0 -0
- discolike_cli-0.2.0/src/discolike_cli/queries.py +127 -0
- discolike_cli-0.2.0/tests/conftest.py +41 -0
- discolike_cli-0.2.0/tests/test_account.py +23 -0
- discolike_cli-0.2.0/tests/test_auth.py +210 -0
- discolike_cli-0.2.0/tests/test_company.py +134 -0
- discolike_cli-0.1.0/tests/test_contacts.py → discolike_cli-0.2.0/tests/test_contacts_cli.py +111 -61
- discolike_cli-0.1.0/tests/test_discogen.py → discolike_cli-0.2.0/tests/test_discogen_cli.py +51 -55
- discolike_cli-0.2.0/tests/test_discover.py +131 -0
- discolike_cli-0.2.0/tests/test_email_cli.py +283 -0
- discolike_cli-0.1.0/tests/test_enrich.py → discolike_cli-0.2.0/tests/test_enrich_cli.py +60 -64
- discolike_cli-0.2.0/tests/test_match_cli.py +219 -0
- {discolike_cli-0.1.0 → discolike_cli-0.2.0}/tests/test_output.py +53 -3
- discolike_cli-0.2.0/tests/test_providers_cli.py +219 -0
- discolike_cli-0.2.0/tests/test_queries_cli.py +180 -0
- discolike_cli-0.1.0/src/discolike_cli/account.py +0 -16
- discolike_cli-0.1.0/src/discolike_cli/auth.py +0 -60
- discolike_cli-0.1.0/src/discolike_cli/company.py +0 -87
- discolike_cli-0.1.0/src/discolike_cli/contacts.py +0 -230
- discolike_cli-0.1.0/src/discolike_cli/discogen.py +0 -119
- discolike_cli-0.1.0/src/discolike_cli/discover.py +0 -111
- discolike_cli-0.1.0/src/discolike_cli/enrich.py +0 -91
- discolike_cli-0.1.0/src/discolike_cli/match.py +0 -54
- discolike_cli-0.1.0/src/discolike_cli/queries.py +0 -65
- discolike_cli-0.1.0/tests/conftest.py +0 -23
- discolike_cli-0.1.0/tests/test_account.py +0 -29
- discolike_cli-0.1.0/tests/test_auth.py +0 -121
- discolike_cli-0.1.0/tests/test_company.py +0 -117
- discolike_cli-0.1.0/tests/test_discover.py +0 -112
- discolike_cli-0.1.0/tests/test_match.py +0 -178
- discolike_cli-0.1.0/tests/test_queries_cli.py +0 -102
- {discolike_cli-0.1.0 → discolike_cli-0.2.0}/.gitignore +0 -0
- {discolike_cli-0.1.0 → discolike_cli-0.2.0}/src/discolike_cli/__init__.py +0 -0
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 DiscoLike Inc.
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
@@ -1,30 +1,38 @@
|
|
|
1
|
-
Metadata-Version: 2.
|
|
1
|
+
Metadata-Version: 2.5
|
|
2
2
|
Name: discolike-cli
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.2.0
|
|
4
4
|
Summary: Official CLI for the DiscoLike API
|
|
5
5
|
Project-URL: Homepage, https://www.discolike.com
|
|
6
6
|
Project-URL: Documentation, https://docs.discolike.com
|
|
7
7
|
Project-URL: Repository, https://github.com/Discolike/discolike-python
|
|
8
|
+
Project-URL: Changelog, https://github.com/Discolike/discolike-python/blob/main/CHANGELOG.md
|
|
9
|
+
Project-URL: Issues, https://github.com/Discolike/discolike-python/issues
|
|
8
10
|
Author-email: DiscoLike <support@discolike.com>
|
|
9
11
|
License-Expression: MIT
|
|
12
|
+
License-File: LICENSE
|
|
10
13
|
Keywords: business-data,cli,discolike,enrichment
|
|
11
14
|
Classifier: Development Status :: 4 - Beta
|
|
15
|
+
Classifier: Environment :: Console
|
|
12
16
|
Classifier: Intended Audience :: Developers
|
|
17
|
+
Classifier: Operating System :: OS Independent
|
|
13
18
|
Classifier: Programming Language :: Python :: 3
|
|
19
|
+
Classifier: Programming Language :: Python :: 3 :: Only
|
|
14
20
|
Classifier: Programming Language :: Python :: 3.10
|
|
15
21
|
Classifier: Programming Language :: Python :: 3.11
|
|
16
22
|
Classifier: Programming Language :: Python :: 3.12
|
|
17
23
|
Classifier: Programming Language :: Python :: 3.13
|
|
18
24
|
Classifier: Programming Language :: Python :: 3.14
|
|
25
|
+
Classifier: Topic :: Utilities
|
|
26
|
+
Classifier: Typing :: Typed
|
|
19
27
|
Requires-Python: >=3.10
|
|
20
|
-
Requires-Dist: discolike
|
|
28
|
+
Requires-Dist: discolike==0.2.0
|
|
21
29
|
Requires-Dist: rich>=13.0
|
|
22
30
|
Requires-Dist: typer>=0.12
|
|
23
31
|
Description-Content-Type: text/markdown
|
|
24
32
|
|
|
25
33
|
# discolike-cli
|
|
26
34
|
|
|
27
|
-
Official CLI for the [DiscoLike API](https://
|
|
35
|
+
Official CLI for the [DiscoLike API](https://discolike.com) — the `discolike` command from your terminal. Built on the [`discolike`](https://pypi.org/project/discolike/) SDK.
|
|
28
36
|
|
|
29
37
|
## Installation
|
|
30
38
|
|
|
@@ -51,7 +59,7 @@ Prompts for an API key (or pass `--api-key`) and verifies it against your accoun
|
|
|
51
59
|
## Quickstart
|
|
52
60
|
|
|
53
61
|
```bash
|
|
54
|
-
discolike discover --icp-
|
|
62
|
+
discolike discover --icp-prompt "managed IT services for SMBs" --country US --max-records 25
|
|
55
63
|
discolike match "Stripe Inc" --city "San Francisco"
|
|
56
64
|
discolike match --file companies.csv --name-column company_name --wait
|
|
57
65
|
discolike count --phrase-match "book a demo" --country US
|
|
@@ -59,7 +67,7 @@ discolike company data stripe.com
|
|
|
59
67
|
discolike extract https://stripe.com/enterprise
|
|
60
68
|
```
|
|
61
69
|
|
|
62
|
-
Top-level commands: `discover`, `count`, `match`, `extract`, `validate-icp`, `append`, `segment` — plus `auth`, `company`, `contacts`, `discogen`, `queries`, and `
|
|
70
|
+
Top-level commands: `discover`, `count`, `match`, `extract`, `validate-icp`, `append`, `segment` — plus `auth`, `company`, `contacts`, `discogen`, `queries`, `account`, `search-providers`, and `llm-providers` command groups.
|
|
63
71
|
|
|
64
72
|
### Conventions
|
|
65
73
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# discolike-cli
|
|
2
2
|
|
|
3
|
-
Official CLI for the [DiscoLike API](https://
|
|
3
|
+
Official CLI for the [DiscoLike API](https://discolike.com) — the `discolike` command from your terminal. Built on the [`discolike`](https://pypi.org/project/discolike/) SDK.
|
|
4
4
|
|
|
5
5
|
## Installation
|
|
6
6
|
|
|
@@ -27,7 +27,7 @@ Prompts for an API key (or pass `--api-key`) and verifies it against your accoun
|
|
|
27
27
|
## Quickstart
|
|
28
28
|
|
|
29
29
|
```bash
|
|
30
|
-
discolike discover --icp-
|
|
30
|
+
discolike discover --icp-prompt "managed IT services for SMBs" --country US --max-records 25
|
|
31
31
|
discolike match "Stripe Inc" --city "San Francisco"
|
|
32
32
|
discolike match --file companies.csv --name-column company_name --wait
|
|
33
33
|
discolike count --phrase-match "book a demo" --country US
|
|
@@ -35,7 +35,7 @@ discolike company data stripe.com
|
|
|
35
35
|
discolike extract https://stripe.com/enterprise
|
|
36
36
|
```
|
|
37
37
|
|
|
38
|
-
Top-level commands: `discover`, `count`, `match`, `extract`, `validate-icp`, `append`, `segment` — plus `auth`, `company`, `contacts`, `discogen`, `queries`, and `
|
|
38
|
+
Top-level commands: `discover`, `count`, `match`, `extract`, `validate-icp`, `append`, `segment` — plus `auth`, `company`, `contacts`, `discogen`, `queries`, `account`, `search-providers`, and `llm-providers` command groups.
|
|
39
39
|
|
|
40
40
|
### Conventions
|
|
41
41
|
|
|
@@ -4,14 +4,15 @@ build-backend = "hatchling.build"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "discolike-cli"
|
|
7
|
-
version = "0.
|
|
7
|
+
version = "0.2.0"
|
|
8
8
|
description = "Official CLI for the DiscoLike API"
|
|
9
9
|
readme = "README.md"
|
|
10
10
|
license = "MIT"
|
|
11
|
+
license-files = ["LICENSE"]
|
|
11
12
|
requires-python = ">=3.10"
|
|
12
13
|
authors = [{ name = "DiscoLike", email = "support@discolike.com" }]
|
|
13
14
|
dependencies = [
|
|
14
|
-
"discolike
|
|
15
|
+
"discolike==0.2.0",
|
|
15
16
|
"typer>=0.12",
|
|
16
17
|
"rich>=13.0",
|
|
17
18
|
]
|
|
@@ -25,6 +26,11 @@ classifiers = [
|
|
|
25
26
|
"Programming Language :: Python :: 3.12",
|
|
26
27
|
"Programming Language :: Python :: 3.13",
|
|
27
28
|
"Programming Language :: Python :: 3.14",
|
|
29
|
+
"Programming Language :: Python :: 3 :: Only",
|
|
30
|
+
"Operating System :: OS Independent",
|
|
31
|
+
"Environment :: Console",
|
|
32
|
+
"Topic :: Utilities",
|
|
33
|
+
"Typing :: Typed",
|
|
28
34
|
]
|
|
29
35
|
|
|
30
36
|
[project.scripts]
|
|
@@ -34,12 +40,16 @@ discolike = "discolike_cli.main:app"
|
|
|
34
40
|
Homepage = "https://www.discolike.com"
|
|
35
41
|
Documentation = "https://docs.discolike.com"
|
|
36
42
|
Repository = "https://github.com/Discolike/discolike-python"
|
|
43
|
+
Changelog = "https://github.com/Discolike/discolike-python/blob/main/CHANGELOG.md"
|
|
44
|
+
Issues = "https://github.com/Discolike/discolike-python/issues"
|
|
37
45
|
|
|
38
46
|
[tool.uv.sources]
|
|
47
|
+
discolike-testkit = { workspace = true }
|
|
39
48
|
discolike = { workspace = true }
|
|
40
49
|
|
|
41
50
|
[dependency-groups]
|
|
42
51
|
dev = [
|
|
52
|
+
"discolike-testkit",
|
|
43
53
|
"pytest>=8",
|
|
44
54
|
"pytest-asyncio>=0.24",
|
|
45
55
|
"ruff>=0.8",
|
|
@@ -60,21 +60,39 @@ def _normalize(data: Any) -> Any: # noqa: ANN401 -- accepts arbitrary JSON-seri
|
|
|
60
60
|
return data
|
|
61
61
|
|
|
62
62
|
|
|
63
|
-
|
|
64
|
-
|
|
63
|
+
TABLE_CELL_MAX_CHARS = 80
|
|
64
|
+
TABLE_MAX_COLUMNS = 8
|
|
65
|
+
_SCALAR_TYPES = (str, int, float, bool, type(None))
|
|
66
|
+
|
|
67
|
+
|
|
68
|
+
def _scalar_columns(rows: list[dict[str, Any]]) -> list[str]:
|
|
69
|
+
columns = [column for column in rows[0] if all(isinstance(row.get(column), _SCALAR_TYPES) for row in rows)]
|
|
70
|
+
return columns[:TABLE_MAX_COLUMNS]
|
|
65
71
|
|
|
66
72
|
|
|
67
73
|
def _qualifies_for_table(data: Any) -> bool: # noqa: ANN401 -- runtime-narrowed via isinstance, not a fixed shape
|
|
68
|
-
return
|
|
74
|
+
return (
|
|
75
|
+
isinstance(data, list)
|
|
76
|
+
and len(data) > 0
|
|
77
|
+
and all(isinstance(item, dict) for item in data)
|
|
78
|
+
and len(_scalar_columns(data)) > 0
|
|
79
|
+
)
|
|
80
|
+
|
|
81
|
+
|
|
82
|
+
def _cell(value: Any) -> str: # noqa: ANN401 -- scalar JSON value, narrowed by _scalar_columns
|
|
83
|
+
text = "" if value is None else str(value)
|
|
84
|
+
if len(text) > TABLE_CELL_MAX_CHARS:
|
|
85
|
+
return text[: TABLE_CELL_MAX_CHARS - 1] + "…"
|
|
86
|
+
return text
|
|
69
87
|
|
|
70
88
|
|
|
71
89
|
def _render_table(rows: list[dict[str, Any]]) -> None:
|
|
72
90
|
table = Table()
|
|
73
|
-
columns =
|
|
91
|
+
columns = _scalar_columns(rows)
|
|
74
92
|
for column in columns:
|
|
75
|
-
table.add_column(column)
|
|
93
|
+
table.add_column(column, overflow="ellipsis", no_wrap=True)
|
|
76
94
|
for row in rows:
|
|
77
|
-
table.add_row(*(
|
|
95
|
+
table.add_row(*(_cell(row.get(column)) for column in columns))
|
|
78
96
|
Console().print(table)
|
|
79
97
|
|
|
80
98
|
|
|
@@ -117,7 +135,7 @@ def handle_errors(fn: Callable[P, R]) -> Callable[P, R]:
|
|
|
117
135
|
return wrapper
|
|
118
136
|
|
|
119
137
|
|
|
120
|
-
def run_job(job: SupportsWait, *, wait: bool, timeout: float) -> None:
|
|
138
|
+
def run_job(job: SupportsWait, *, wait: bool, timeout: float, fmt: str | None = None) -> None:
|
|
121
139
|
if not wait:
|
|
122
140
|
emit(
|
|
123
141
|
{
|
|
@@ -132,4 +150,4 @@ def run_job(job: SupportsWait, *, wait: bool, timeout: float) -> None:
|
|
|
132
150
|
sys.stderr.write(f"progress: {status.progress}%\n")
|
|
133
151
|
|
|
134
152
|
final = job.wait(timeout=timeout, on_poll=_on_poll)
|
|
135
|
-
emit(final.results if final.results is not None else final.to_dict())
|
|
153
|
+
emit(final.results if final.results is not None else final.to_dict(), fmt=fmt)
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
import typer
|
|
4
|
+
|
|
5
|
+
from discolike_cli._output import emit
|
|
6
|
+
from discolike_cli._output import handle_errors
|
|
7
|
+
|
|
8
|
+
FORMAT_HELP = "Output format: json or table (table auto-selected on a TTY; falls back to JSON for non-tabular data)."
|
|
9
|
+
|
|
10
|
+
app = typer.Typer(help="Account usage and quota.")
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
@app.command("usage")
|
|
14
|
+
@handle_errors
|
|
15
|
+
def usage_command(
|
|
16
|
+
ctx: typer.Context,
|
|
17
|
+
fmt: str | None = typer.Option(None, "--format", help=FORMAT_HELP),
|
|
18
|
+
) -> None:
|
|
19
|
+
"""Month-to-date usage: requests, records, and spend."""
|
|
20
|
+
from discolike_cli.main import get_client
|
|
21
|
+
|
|
22
|
+
emit(get_client(ctx).account.usage(), fmt=fmt)
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
import json
|
|
4
|
+
import sys
|
|
5
|
+
from typing import Any
|
|
6
|
+
|
|
7
|
+
import typer
|
|
8
|
+
|
|
9
|
+
from discolike._config import KEYS_URL
|
|
10
|
+
from discolike._config import delete_config
|
|
11
|
+
from discolike._config import load_config
|
|
12
|
+
from discolike._config import resolve_api_key
|
|
13
|
+
from discolike._config import save_config
|
|
14
|
+
from discolike_cli._output import emit
|
|
15
|
+
from discolike_cli._output import handle_errors
|
|
16
|
+
|
|
17
|
+
app = typer.Typer(help="Manage API credentials: log in, check key status, log out.")
|
|
18
|
+
|
|
19
|
+
MASKED_VISIBLE_CHARS = 4
|
|
20
|
+
|
|
21
|
+
SOURCE_OPTION = "option"
|
|
22
|
+
SOURCE_ENV = "env"
|
|
23
|
+
SOURCE_CONFIG = "config"
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
def _mask(key: str) -> str:
|
|
27
|
+
return "…" + key[-MASKED_VISIBLE_CHARS:]
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
def _global_key_source(ctx: typer.Context) -> str:
|
|
31
|
+
# typer vendors click without re-exporting ParameterSource, so match on the enum member name.
|
|
32
|
+
source = ctx.find_root().get_parameter_source("api_key")
|
|
33
|
+
return SOURCE_ENV if source is not None and source.name == "ENVIRONMENT" else SOURCE_OPTION
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
def _verify(ctx: typer.Context, *, api_key: str) -> None:
|
|
37
|
+
from discolike_cli.main import build_client
|
|
38
|
+
|
|
39
|
+
kwargs: dict[str, Any] = {"api_key": api_key}
|
|
40
|
+
base_url = ctx.obj.get("base_url")
|
|
41
|
+
if base_url is not None:
|
|
42
|
+
kwargs["base_url"] = base_url
|
|
43
|
+
build_client(**kwargs).account.usage()
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
@app.command()
|
|
47
|
+
@handle_errors
|
|
48
|
+
def login(
|
|
49
|
+
ctx: typer.Context,
|
|
50
|
+
api_key: str | None = typer.Option(None, help=f"API key. Create one at {KEYS_URL}. Prompted for if omitted."),
|
|
51
|
+
) -> None:
|
|
52
|
+
"""Verify an API key and save it to the local config file."""
|
|
53
|
+
# An ambient DISCOLIKE_API_KEY must not silently become the saved key; only an explicit flag may.
|
|
54
|
+
passed_globally = ctx.obj.get("api_key") if _global_key_source(ctx) == SOURCE_OPTION else None
|
|
55
|
+
key = api_key or passed_globally or typer.prompt("API key", hide_input=True)
|
|
56
|
+
_verify(ctx, api_key=key)
|
|
57
|
+
save_config({"auth_method": "api_key", "api_key": key})
|
|
58
|
+
print(json.dumps({"logged_in": True, "source": "api_key"}), file=sys.stderr)
|
|
59
|
+
|
|
60
|
+
|
|
61
|
+
@app.command()
|
|
62
|
+
@handle_errors
|
|
63
|
+
def status(ctx: typer.Context) -> None:
|
|
64
|
+
"""Show which API key is in use (option, env, or config) and verify it against the API."""
|
|
65
|
+
key = ctx.obj.get("api_key")
|
|
66
|
+
source = _global_key_source(ctx)
|
|
67
|
+
if not key:
|
|
68
|
+
key = load_config().get("api_key")
|
|
69
|
+
source = SOURCE_CONFIG
|
|
70
|
+
if not key:
|
|
71
|
+
resolve_api_key(None)
|
|
72
|
+
_verify(ctx, api_key=str(key))
|
|
73
|
+
emit({"source": source, "api_key": _mask(str(key)), "valid": True})
|
|
74
|
+
|
|
75
|
+
|
|
76
|
+
@app.command()
|
|
77
|
+
@handle_errors
|
|
78
|
+
def logout() -> None:
|
|
79
|
+
"""Delete saved credentials from the local config file."""
|
|
80
|
+
delete_config()
|
|
81
|
+
emit({"logged_out": True})
|
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
import typer
|
|
4
|
+
|
|
5
|
+
from discolike_cli._output import emit
|
|
6
|
+
from discolike_cli._output import handle_errors
|
|
7
|
+
|
|
8
|
+
FORMAT_HELP = "Output format: json or table (table auto-selected on a TTY; falls back to JSON for non-tabular data)."
|
|
9
|
+
DOMAIN_HELP = "Company domain, e.g. stripe.com"
|
|
10
|
+
MATCH_HELP = "Domain match mode, e.g. loose"
|
|
11
|
+
|
|
12
|
+
app = typer.Typer(
|
|
13
|
+
help="Company profiles by domain: firmographics, scores, growth, redirects, vendors, subsidiaries, and public links."
|
|
14
|
+
)
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
@app.command()
|
|
18
|
+
@handle_errors
|
|
19
|
+
def data(
|
|
20
|
+
ctx: typer.Context,
|
|
21
|
+
domain: str = typer.Argument(..., help=DOMAIN_HELP),
|
|
22
|
+
fmt: str | None = typer.Option(None, "--format", help=FORMAT_HELP),
|
|
23
|
+
) -> None:
|
|
24
|
+
"""Full company profile (firmographics) for a domain."""
|
|
25
|
+
from discolike_cli.main import get_client
|
|
26
|
+
|
|
27
|
+
emit(get_client(ctx).companies.data(domain=domain), fmt=fmt)
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
@app.command()
|
|
31
|
+
@handle_errors
|
|
32
|
+
def score(
|
|
33
|
+
ctx: typer.Context,
|
|
34
|
+
domain: str = typer.Argument(..., help=DOMAIN_HELP),
|
|
35
|
+
fmt: str | None = typer.Option(None, "--format", help=FORMAT_HELP),
|
|
36
|
+
) -> None:
|
|
37
|
+
"""Company score for a domain."""
|
|
38
|
+
from discolike_cli.main import get_client
|
|
39
|
+
|
|
40
|
+
emit(get_client(ctx).companies.score(domain=domain), fmt=fmt)
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
@app.command()
|
|
44
|
+
@handle_errors
|
|
45
|
+
def growth(
|
|
46
|
+
ctx: typer.Context,
|
|
47
|
+
domain: str = typer.Argument(..., help=DOMAIN_HELP),
|
|
48
|
+
fmt: str | None = typer.Option(None, "--format", help=FORMAT_HELP),
|
|
49
|
+
) -> None:
|
|
50
|
+
"""Growth signals for a domain."""
|
|
51
|
+
from discolike_cli.main import get_client
|
|
52
|
+
|
|
53
|
+
emit(get_client(ctx).companies.growth(domain=domain), fmt=fmt)
|
|
54
|
+
|
|
55
|
+
|
|
56
|
+
@app.command()
|
|
57
|
+
@handle_errors
|
|
58
|
+
def redirects(
|
|
59
|
+
ctx: typer.Context,
|
|
60
|
+
domain: str = typer.Argument(..., help=DOMAIN_HELP),
|
|
61
|
+
match: str | None = typer.Option(None, "--match", help=MATCH_HELP),
|
|
62
|
+
fmt: str | None = typer.Option(None, "--format", help=FORMAT_HELP),
|
|
63
|
+
) -> None:
|
|
64
|
+
"""Domain redirects for a company domain."""
|
|
65
|
+
from discolike_cli.main import get_client
|
|
66
|
+
|
|
67
|
+
emit(get_client(ctx).companies.redirects(domain=domain, match=match), fmt=fmt)
|
|
68
|
+
|
|
69
|
+
|
|
70
|
+
@app.command()
|
|
71
|
+
@handle_errors
|
|
72
|
+
def vendors(
|
|
73
|
+
ctx: typer.Context,
|
|
74
|
+
domain: str = typer.Argument(..., help=DOMAIN_HELP),
|
|
75
|
+
match: str | None = typer.Option(None, "--match", help=MATCH_HELP),
|
|
76
|
+
fmt: str | None = typer.Option(None, "--format", help=FORMAT_HELP),
|
|
77
|
+
) -> None:
|
|
78
|
+
"""Vendors associated with a company domain."""
|
|
79
|
+
from discolike_cli.main import get_client
|
|
80
|
+
|
|
81
|
+
emit(get_client(ctx).companies.vendors(domain=domain, match=match), fmt=fmt)
|
|
82
|
+
|
|
83
|
+
|
|
84
|
+
@app.command()
|
|
85
|
+
@handle_errors
|
|
86
|
+
def subsidiaries(
|
|
87
|
+
ctx: typer.Context,
|
|
88
|
+
domain: str = typer.Argument(..., help=DOMAIN_HELP),
|
|
89
|
+
match: str | None = typer.Option(None, "--match", help=MATCH_HELP),
|
|
90
|
+
fmt: str | None = typer.Option(None, "--format", help=FORMAT_HELP),
|
|
91
|
+
) -> None:
|
|
92
|
+
"""Subsidiaries of a company domain."""
|
|
93
|
+
from discolike_cli.main import get_client
|
|
94
|
+
|
|
95
|
+
emit(get_client(ctx).companies.subsidiaries(domain=domain, match=match), fmt=fmt)
|
|
96
|
+
|
|
97
|
+
|
|
98
|
+
@app.command(name="public-links")
|
|
99
|
+
@handle_errors
|
|
100
|
+
def public_links(
|
|
101
|
+
ctx: typer.Context,
|
|
102
|
+
domain: str = typer.Argument(..., help=DOMAIN_HELP),
|
|
103
|
+
source: str = typer.Option(..., "--source", help="Public link source, e.g. crunchbase"),
|
|
104
|
+
fmt: str | None = typer.Option(None, "--format", help=FORMAT_HELP),
|
|
105
|
+
) -> None:
|
|
106
|
+
"""Public profile links for a domain from a given source."""
|
|
107
|
+
from discolike_cli.main import get_client
|
|
108
|
+
|
|
109
|
+
emit(get_client(ctx).companies.public_links(domain=domain, source=source), fmt=fmt)
|
|
110
|
+
|
|
111
|
+
|
|
112
|
+
@handle_errors
|
|
113
|
+
def extract_command(
|
|
114
|
+
ctx: typer.Context,
|
|
115
|
+
url: str = typer.Argument(..., help="Page URL to extract content from"),
|
|
116
|
+
fmt: str | None = typer.Option(None, "--format", help=FORMAT_HELP),
|
|
117
|
+
) -> None:
|
|
118
|
+
"""Extract page content from a URL."""
|
|
119
|
+
from discolike_cli.main import get_client
|
|
120
|
+
|
|
121
|
+
emit(get_client(ctx).companies.extract(url=url), fmt=fmt)
|