dailydotsnek 1.0.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.
@@ -0,0 +1 @@
1
+ test.txt
@@ -0,0 +1,6 @@
1
+ # Changelog
2
+
3
+ See docs/changelog.md for the full changelog.
4
+
5
+ ## [1.0.0] - 2026-10-13
6
+ - Initial release
@@ -0,0 +1 @@
1
+ See docs/contributing.md for contribution guidelines and local development instructions.
@@ -0,0 +1,77 @@
1
+ Metadata-Version: 2.5
2
+ Name: dailydotsnek
3
+ Version: 1.0.0
4
+ Summary: Python SDK for Daily.dev api
5
+ Requires-Python: >=3.10
6
+ Description-Content-Type: text/markdown
7
+
8
+ # dailydotsnek
9
+
10
+ A lightweight, well-documented Python SDK for the daily.dev public API.
11
+
12
+ Features
13
+ - Clean, minimal API client interfaces
14
+ - Environment- or manual-token authentication helpers
15
+ - Full method coverage for feeds, posts, bookmarks, profile, and search
16
+
17
+ Installation
18
+
19
+ Install from PyPI when the package is published:
20
+
21
+ ```bash
22
+ pip install dailydotsnek
23
+ ```
24
+
25
+ (For local development):
26
+
27
+ ```bash
28
+ pip install -e .
29
+ ```
30
+
31
+ Quickstart
32
+
33
+ ```python
34
+ from snek.tokenSys import AutoApiToken, ManualApiToken
35
+ from snek.snekSDK import SnekSDK
36
+
37
+ # AutoApiToken reads the DAILY_DEV_KEY env var (via python-dotenv)
38
+ token = AutoApiToken()
39
+ # or
40
+ # token = ManualApiToken("your_api_key_here")
41
+
42
+ client = SnekSDK(token)
43
+
44
+ posts = client.getPopularFeed()
45
+ print(posts)
46
+ ```
47
+
48
+ Documentation
49
+
50
+ A full, polished documentation site is included under `docs/` and configured with MkDocs.
51
+
52
+ Building the package (locally)
53
+
54
+ - Build a wheel with hatch (project uses hatchling):
55
+
56
+ ```bash
57
+ python -m pip install -U hatch
58
+ hatch build
59
+ ```
60
+
61
+ - The built artifacts will be in `dist/`.
62
+
63
+ Publishing (prepare-only):
64
+
65
+ This repository has been prepared for PyPI publishing. To publish, configure credentials (see docs/ for instructions) and run a publish command such as:
66
+
67
+ ```bash
68
+ # With twine
69
+ python -m pip install --upgrade build twine
70
+ python -m build
71
+ python -m twine upload dist/*
72
+
73
+ # or with hatch
74
+ hatch publish # requires hatch and configuration
75
+ ```
76
+
77
+ See the docs/ for more information and examples.
@@ -0,0 +1,70 @@
1
+ # dailydotsnek
2
+
3
+ A lightweight, well-documented Python SDK for the daily.dev public API.
4
+
5
+ Features
6
+ - Clean, minimal API client interfaces
7
+ - Environment- or manual-token authentication helpers
8
+ - Full method coverage for feeds, posts, bookmarks, profile, and search
9
+
10
+ Installation
11
+
12
+ Install from PyPI when the package is published:
13
+
14
+ ```bash
15
+ pip install dailydotsnek
16
+ ```
17
+
18
+ (For local development):
19
+
20
+ ```bash
21
+ pip install -e .
22
+ ```
23
+
24
+ Quickstart
25
+
26
+ ```python
27
+ from snek.tokenSys import AutoApiToken, ManualApiToken
28
+ from snek.snekSDK import SnekSDK
29
+
30
+ # AutoApiToken reads the DAILY_DEV_KEY env var (via python-dotenv)
31
+ token = AutoApiToken()
32
+ # or
33
+ # token = ManualApiToken("your_api_key_here")
34
+
35
+ client = SnekSDK(token)
36
+
37
+ posts = client.getPopularFeed()
38
+ print(posts)
39
+ ```
40
+
41
+ Documentation
42
+
43
+ A full, polished documentation site is included under `docs/` and configured with MkDocs.
44
+
45
+ Building the package (locally)
46
+
47
+ - Build a wheel with hatch (project uses hatchling):
48
+
49
+ ```bash
50
+ python -m pip install -U hatch
51
+ hatch build
52
+ ```
53
+
54
+ - The built artifacts will be in `dist/`.
55
+
56
+ Publishing (prepare-only):
57
+
58
+ This repository has been prepared for PyPI publishing. To publish, configure credentials (see docs/ for instructions) and run a publish command such as:
59
+
60
+ ```bash
61
+ # With twine
62
+ python -m pip install --upgrade build twine
63
+ python -m build
64
+ python -m twine upload dist/*
65
+
66
+ # or with hatch
67
+ hatch publish # requires hatch and configuration
68
+ ```
69
+
70
+ See the docs/ for more information and examples.
@@ -0,0 +1,33 @@
1
+ # API Reference (hand-curated)
2
+
3
+ This page provides a concise, example-driven reference for the primary `SnekSDK` methods. The SDK wraps the daily.dev public API and returns decoded JSON objects when responses include a JSON body.
4
+
5
+ ## SnekSDK
6
+
7
+ Create an instance with a token (see Quickstart):
8
+
9
+ ```python
10
+ client = SnekSDK(token)
11
+ ```
12
+
13
+ Key methods
14
+
15
+ - `getPersonalisedFeed()` — personalized feed for authenticated user
16
+ - `getPopularFeed()` — popular posts
17
+ - `getDiscussedFeed()` — posts with active discussions
18
+ - `getTagFeed(tag)` — posts for a tag
19
+ - `getPost(post_id)` — single post
20
+
21
+ Bookmarks
22
+ - `getBookmarks()`
23
+ - `addBookmarks(post_ids, list_id=None)`
24
+ - `getBookmarkLists()`
25
+
26
+ Profile
27
+ - `getProfile()`
28
+ - `updateProfile(**data)`
29
+
30
+ Search
31
+ - `searchPosts(query)`, `searchTags(query)`, `searchSources(query)`
32
+
33
+ Refer to the source in `src/snek/snekSDK.py` for the full, up-to-date list of methods and parameter shapes.
@@ -0,0 +1,10 @@
1
+ # Changelog
2
+
3
+ All notable changes to this project are documented in this file.
4
+
5
+ ## [1.0.0] - 2026-10-13
6
+ ### Added
7
+ - Initial public release
8
+ - Core SDK methods for feeds, posts, bookmarks, profile, and search
9
+ - Basic documentation and examples
10
+
@@ -0,0 +1,32 @@
1
+ # Contributing
2
+
3
+ Thanks for considering contributing to dailydotsnek! This project welcomes improvements to documentation, bug fixes, and new features.
4
+
5
+ Guidelines
6
+
7
+ - Open an issue to discuss larger changes before implementing.
8
+ - Fork the repo and create a topic branch for your change.
9
+ - Keep changes small and focused; write tests for new behaviors.
10
+
11
+ Code style
12
+
13
+ - Target Python 3.10+.
14
+ - Use type hints where helpful.
15
+ - Keep public API backwards-compatible.
16
+
17
+ Testing
18
+
19
+ Add tests under a `tests/` directory and run with `pytest`.
20
+
21
+ Documentation
22
+
23
+ Docs are written in Markdown and built with MkDocs. To preview locally:
24
+
25
+ ```bash
26
+ pip install mkdocs mkdocs-material
27
+ mkdocs serve
28
+ ```
29
+
30
+ License
31
+
32
+ This project is licensed under the MIT License.
@@ -0,0 +1,13 @@
1
+ # dailydotsnek
2
+
3
+ Welcome to the official documentation for dailydotsnek — a polished, developer-friendly Python SDK for the daily.dev public API.
4
+
5
+ This documentation is designed to be concise, readable, and example-driven. Use the navigation on the left to find installation instructions, a quickstart, API reference, contributing guidelines, and changelog.
6
+
7
+ Highlights
8
+
9
+ - Ergonomic token helpers (AutoApiToken / ManualApiToken)
10
+ - A single SnekSDK client with convenience methods for feeds, posts, bookmarks, profile, and search
11
+ - Designed for Python 3.10+
12
+
13
+ If you're new here, start with Installation and Quickstart for a 2-minute walkthrough.
@@ -0,0 +1,20 @@
1
+ # Installation
2
+
3
+ Install the published package from PyPI (when available):
4
+
5
+ ```bash
6
+ pip install dailydotsnek
7
+ ```
8
+
9
+ For local development, install in editable mode:
10
+
11
+ ```bash
12
+ python -m pip install -U pip
13
+ python -m pip install -e .
14
+ ```
15
+
16
+ Requirements
17
+ - Python 3.10+
18
+ - Optional: python-dotenv if using AutoApiToken
19
+
20
+ Virtual environments are recommended for development and testing.
@@ -0,0 +1,46 @@
1
+ # Publishing to TestPyPI / PyPI
2
+
3
+ This project is prepared for PyPI publishing using standard tools. Two common approaches are described below.
4
+
5
+ Prerequisites
6
+
7
+ - Python 3.10+ installed
8
+ - An account on Test PyPI (https://test.pypi.org/) and/or PyPI (https://pypi.org/)
9
+ - `twine` and `build` installed locally
10
+
11
+ Create a `.pypirc` (optional)
12
+
13
+ Create `~/.pypirc` to store credentials so `twine` can pick them up automatically:
14
+
15
+ ```
16
+ [distutils]
17
+ index-servers =
18
+ pypi
19
+ testpypi
20
+
21
+ [pypi]
22
+ username = __token__
23
+ password = <pypi-api-token>
24
+
25
+ [testpypi]
26
+ repository: https://test.pypi.org/legacy/
27
+ username = __token__
28
+ password = <testpypi-api-token>
29
+ ```
30
+
31
+ Build and upload (TestPyPI recommended first)
32
+
33
+ ```bash
34
+ python -m pip install --upgrade build twine
35
+ python -m build
36
+ # Upload to test PyPI
37
+ python -m twine upload --repository testpypi dist/*
38
+
39
+ # After verification, upload to real PyPI
40
+ python -m twine upload dist/*
41
+ ```
42
+
43
+ Notes
44
+
45
+ - Use API tokens rather than your account password. Create them in your PyPI account settings.
46
+ - For automated releases, use GitHub Actions or another CI; keep tokens in repository secrets and restrict publish jobs.
@@ -0,0 +1,37 @@
1
+ # Quickstart & Usage
2
+
3
+ ## Authentication
4
+
5
+ Two token helpers are provided:
6
+
7
+ - `AutoApiToken()` — loads `DAILY_DEV_KEY` from environment using python-dotenv.
8
+ - `ManualApiToken("<token>")` — provide token explicitly.
9
+
10
+ ```python
11
+ from snek.tokenSys import AutoApiToken, ManualApiToken
12
+ from snek.snekSDK import SnekSDK
13
+
14
+ # Auto (dotenv)
15
+ token = AutoApiToken()
16
+ client = SnekSDK(token)
17
+
18
+ # Manual
19
+ # token = ManualApiToken("sk_live_...")
20
+ # client = SnekSDK(token)
21
+ ```
22
+
23
+ ## Example: get popular feed
24
+
25
+ ```python
26
+ posts = client.getPopularFeed()
27
+ for p in posts.get("data", []):
28
+ print(p.get("title"))
29
+ ```
30
+
31
+ ## Error handling
32
+
33
+ The client surface raises requests HTTP errors on non-2xx responses. Catch `requests.HTTPError` to handle API errors.
34
+
35
+ ## Rate limits
36
+
37
+ Use `getRateLimit()`, `getRateRemaining()` and `getRateResetTime()` to inspect API rate-limit headers.
@@ -0,0 +1,175 @@
1
+ #!/usr/bin/env python3
2
+
3
+ from __future__ import annotations
4
+
5
+ import argparse
6
+ import ast
7
+ from pathlib import Path
8
+
9
+
10
+ IGNORED_DIRS = {
11
+ "__pycache__",
12
+ ".git",
13
+ ".venv",
14
+ "venv",
15
+ "node_modules",
16
+ }
17
+
18
+
19
+ def find_symbols(path: Path) -> list[str]:
20
+ """Return public functions/classes defined directly in a Python file."""
21
+ try:
22
+ tree = ast.parse(path.read_text(encoding="utf-8"), filename=str(path))
23
+ except SyntaxError as exc:
24
+ print(f"warning: could not parse {path}: {exc}")
25
+ return []
26
+
27
+ symbols: list[str] = []
28
+
29
+ for node in tree.body:
30
+ if isinstance(
31
+ node,
32
+ (
33
+ ast.FunctionDef,
34
+ ast.AsyncFunctionDef,
35
+ ast.ClassDef,
36
+ ),
37
+ ):
38
+ if not node.name.startswith("_"):
39
+ symbols.append(node.name)
40
+
41
+ return sorted(symbols)
42
+
43
+
44
+ def python_files(directory: Path) -> list[Path]:
45
+ """Find Python files directly inside a directory."""
46
+ return sorted(
47
+ path
48
+ for path in directory.iterdir()
49
+ if path.is_file()
50
+ and path.suffix == ".py"
51
+ and path.name != "__init__.py"
52
+ )
53
+
54
+
55
+ def package_directories(src: Path) -> list[Path]:
56
+ """Find every directory containing Python/package code."""
57
+ directories: set[Path] = set()
58
+
59
+ for path in src.rglob("*"):
60
+ if not path.is_dir():
61
+ continue
62
+
63
+ if any(part in IGNORED_DIRS for part in path.parts):
64
+ continue
65
+
66
+ if any(path.glob("*.py")):
67
+ directories.add(path)
68
+
69
+ # Include parents so nested packages get __init__.py files too.
70
+ for directory in list(directories):
71
+ current = directory
72
+ while current != src and current != current.parent:
73
+ directories.add(current)
74
+ current = current.parent
75
+
76
+ return sorted(directories)
77
+
78
+
79
+ def module_import(module: str, symbols: list[str]) -> str:
80
+ """Create an import line for a module."""
81
+ if symbols:
82
+ names = ", ".join(symbols)
83
+ return f"from .{module} import {names}"
84
+
85
+ return f"from . import {module}"
86
+
87
+
88
+ def generate_init(directory: Path, src: Path) -> str:
89
+ """Generate the contents of an __init__.py."""
90
+ files = python_files(directory)
91
+
92
+ lines = [
93
+ '"""Automatically generated package exports."""',
94
+ "",
95
+ ]
96
+
97
+ # Export functions/classes from Python files.
98
+ for file in files:
99
+ symbols = find_symbols(file)
100
+ module = file.stem
101
+
102
+ lines.append(module_import(module, symbols))
103
+
104
+ # Export child packages.
105
+ child_packages = []
106
+
107
+ for child in sorted(directory.iterdir()):
108
+ if not child.is_dir():
109
+ continue
110
+
111
+ if child.name in IGNORED_DIRS:
112
+ continue
113
+
114
+ if any(child.glob("*.py")) or any(child.iterdir()):
115
+ child_packages.append(child.name)
116
+
117
+ if files and child_packages:
118
+ lines.append("")
119
+
120
+ for package in child_packages:
121
+ lines.append(f"from . import {package}")
122
+
123
+ lines.append("")
124
+
125
+ return "\n".join(lines)
126
+
127
+
128
+ def map_src(src: Path, *, dry_run: bool = False) -> None:
129
+ if not src.exists():
130
+ raise FileNotFoundError(f"Source directory does not exist: {src}")
131
+
132
+ if not src.is_dir():
133
+ raise NotADirectoryError(f"Not a directory: {src}")
134
+
135
+ directories = package_directories(src)
136
+
137
+ for directory in directories:
138
+ init_file = directory / "__init__.py"
139
+ content = generate_init(directory, src)
140
+
141
+ if dry_run:
142
+ print(f"\n### {init_file}")
143
+ print(content)
144
+ continue
145
+
146
+ init_file.write_text(content, encoding="utf-8")
147
+ print(f"generated {init_file}")
148
+
149
+
150
+ def main() -> None:
151
+ parser = argparse.ArgumentParser(
152
+ description="Generate __init__.py exports for a Python src/ tree."
153
+ )
154
+
155
+ parser.add_argument(
156
+ "src",
157
+ nargs="?",
158
+ type=Path,
159
+ default=Path("src"),
160
+ help="Source directory (default: src)",
161
+ )
162
+
163
+ parser.add_argument(
164
+ "--dry-run",
165
+ action="store_true",
166
+ help="Print generated files without modifying anything.",
167
+ )
168
+
169
+ args = parser.parse_args()
170
+
171
+ map_src(args.src, dry_run=args.dry_run)
172
+
173
+
174
+ if __name__ == "__main__":
175
+ main()
@@ -0,0 +1,24 @@
1
+ site_name: dailydotsnek
2
+ site_description: "Professional documentation for the dailydotsnek Python SDK"
3
+ site_author: "Your Name"
4
+ repo_url: https://github.com/yourusername/dailydotsnek
5
+
6
+ nav:
7
+ - Home: index.md
8
+ - Installation: installation.md
9
+ - Quickstart: usage.md
10
+ - API Reference: api.md
11
+ - Contributing: contributing.md
12
+ - Changelog: changelog.md
13
+
14
+ theme:
15
+ name: material
16
+ palette:
17
+ primary: 'indigo'
18
+ accent: 'indigo'
19
+
20
+ markdown_extensions:
21
+ - admonition
22
+ - codehilite
23
+ - toc:
24
+ permalink: true
@@ -0,0 +1,14 @@
1
+ [build-system]
2
+ requires = ["hatchling"]
3
+ build-backend = "hatchling.build"
4
+
5
+ [project]
6
+ name = "dailydotsnek"
7
+ version = "1.0.0"
8
+ description = "Python SDK for Daily.dev api"
9
+ readme = "README.md"
10
+ requires-python = ">=3.10"
11
+ dependencies = []
12
+
13
+ [tool.hatch.build.targets.wheel]
14
+ packages = ["src/snek"]
File without changes
@@ -0,0 +1,109 @@
1
+
2
+ import requests
3
+
4
+ from .tokenSys import ManualApiToken, AutoApiToken
5
+
6
+
7
+ class RawFetch:
8
+ def __init__(self, token: ManualApiToken | AutoApiToken):
9
+ self.token = token
10
+ self.base_url = "https://api.daily.dev/public/v1"
11
+
12
+ def fetch(
13
+ self,
14
+ endpoint: str,
15
+ method: str = "GET",
16
+ params: dict | None = None,
17
+ json: dict | list | None = None,
18
+ ):
19
+ url = f"{self.base_url}/{endpoint.lstrip('/')}"
20
+
21
+ headers = {
22
+ "Authorization": f"Bearer {self.token.get_token()}",
23
+ "Accept": "application/json",
24
+ }
25
+
26
+ response = requests.request(
27
+ method=method,
28
+ url=url,
29
+ headers=headers,
30
+ params=params,
31
+ json=json,
32
+ )
33
+
34
+ if response.ok:
35
+ # Some successful requests may return no body.
36
+ if not response.content:
37
+ return None
38
+
39
+ return response.json()
40
+
41
+ response.raise_for_status()
42
+
43
+ # ─────────────────────────────────────────────
44
+ # Convenience methods
45
+ # ─────────────────────────────────────────────
46
+
47
+ def get(
48
+ self,
49
+ endpoint: str,
50
+ params: dict | None = None,
51
+ ):
52
+ return self.fetch(
53
+ endpoint,
54
+ method="GET",
55
+ params=params,
56
+ )
57
+
58
+ def post(
59
+ self,
60
+ endpoint: str,
61
+ json: dict | list | None = None,
62
+ params: dict | None = None,
63
+ ):
64
+ return self.fetch(
65
+ endpoint,
66
+ method="POST",
67
+ params=params,
68
+ json=json,
69
+ )
70
+
71
+ def put(
72
+ self,
73
+ endpoint: str,
74
+ json: dict | list | None = None,
75
+ params: dict | None = None,
76
+ ):
77
+ return self.fetch(
78
+ endpoint,
79
+ method="PUT",
80
+ params=params,
81
+ json=json,
82
+ )
83
+
84
+ def patch(
85
+ self,
86
+ endpoint: str,
87
+ json: dict | list | None = None,
88
+ params: dict | None = None,
89
+ ):
90
+ return self.fetch(
91
+ endpoint,
92
+ method="PATCH",
93
+ params=params,
94
+ json=json,
95
+ )
96
+
97
+ def delete(
98
+ self,
99
+ endpoint: str,
100
+ params: dict | None = None,
101
+ json: dict | list | None = None,
102
+ ):
103
+ return self.fetch(
104
+ endpoint,
105
+ method="DELETE",
106
+ params=params,
107
+ json=json,
108
+ )
109
+
@@ -0,0 +1,107 @@
1
+ import requests
2
+
3
+ from .tokenSys import ManualApiToken, AutoApiToken
4
+
5
+
6
+ class RawFetch:
7
+ def __init__(self, token: ManualApiToken | AutoApiToken):
8
+ self.token = token
9
+ self.base_url = "https://api.daily.dev/public/v1"
10
+
11
+ def fetch(
12
+ self,
13
+ endpoint: str,
14
+ method: str = "GET",
15
+ params: dict | None = None,
16
+ json: dict | list | None = None,
17
+ ):
18
+ url = f"{self.base_url}/{endpoint.lstrip('/') }"
19
+
20
+ headers = {
21
+ "Authorization": f"Bearer {self.token.get_token()}",
22
+ "Accept": "application/json",
23
+ }
24
+
25
+ response = requests.request(
26
+ method=method,
27
+ url=url,
28
+ headers=headers,
29
+ params=params,
30
+ json=json,
31
+ )
32
+
33
+ if response.ok:
34
+ # Some successful requests may return no body.
35
+ if not response.content:
36
+ return None
37
+
38
+ return response.json()
39
+
40
+ response.raise_for_status()
41
+
42
+ # ─────────────────────────────────────────────
43
+ # Convenience methods
44
+ # ─────────────────────────────────────────────
45
+
46
+ def get(
47
+ self,
48
+ endpoint: str,
49
+ params: dict | None = None,
50
+ ):
51
+ return self.fetch(
52
+ endpoint,
53
+ method="GET",
54
+ params=params,
55
+ )
56
+
57
+ def post(
58
+ self,
59
+ endpoint: str,
60
+ json: dict | list | None = None,
61
+ params: dict | None = None,
62
+ ):
63
+ return self.fetch(
64
+ endpoint,
65
+ method="POST",
66
+ params=params,
67
+ json=json,
68
+ )
69
+
70
+ def put(
71
+ self,
72
+ endpoint: str,
73
+ json: dict | list | None = None,
74
+ params: dict | None = None,
75
+ ):
76
+ return self.fetch(
77
+ endpoint,
78
+ method="PUT",
79
+ params=params,
80
+ json=json,
81
+ )
82
+
83
+ def patch(
84
+ self,
85
+ endpoint: str,
86
+ json: dict | list | None = None,
87
+ params: dict | None = None,
88
+ ):
89
+ return self.fetch(
90
+ endpoint,
91
+ method="PATCH",
92
+ params=params,
93
+ json=json,
94
+ )
95
+
96
+ def delete(
97
+ self,
98
+ endpoint: str,
99
+ params: dict | None = None,
100
+ json: dict | list | None = None,
101
+ ):
102
+ return self.fetch(
103
+ endpoint,
104
+ method="DELETE",
105
+ params=params,
106
+ json=json,
107
+ )
@@ -0,0 +1,239 @@
1
+
2
+ import requests
3
+
4
+ from .tokenSys import ManualApiToken, AutoApiToken
5
+ from .rawFetch_fixed import RawFetch
6
+
7
+
8
+ class SnekSDK:
9
+ def __init__(self, token: ManualApiToken | AutoApiToken):
10
+ self.token = token
11
+ self.base_url = "https://api.daily.dev/public/v1"
12
+ self.fetch = RawFetch(token=self.token)
13
+
14
+
15
+
16
+ def getRateLimit(self):
17
+ return self.fetch.fetch("x-ratelimit-limit")
18
+
19
+ def getRateRemaining(self):
20
+ return self.fetch.fetch("x-ratelimit-remaining")
21
+
22
+ def getRateResetTime(self):
23
+ return self.fetch.fetch("x-ratelimit-reset")
24
+
25
+ def getRetryTime(self):
26
+ return self.fetch.fetch("retry-after")
27
+
28
+
29
+ def getPersonalisedFeed(self):
30
+ return self.fetch.fetch("feeds/foryou")
31
+
32
+ def getPopularFeed(self):
33
+ return self.fetch.fetch("feeds/popular")
34
+
35
+ def getDiscussedFeed(self):
36
+ return self.fetch.fetch("feeds/discussed")
37
+
38
+ def getTagFeed(self, tag: str):
39
+ return self.fetch.fetch(f"feeds/tag/{tag}")
40
+
41
+ def getSourceFeed(self, source: str):
42
+ return self.fetch.fetch(f"feeds/source/{source}")
43
+
44
+
45
+
46
+ def getPost(self, post_id: str):
47
+ return self.fetch.fetch(f"posts/{post_id}")
48
+
49
+ def getPostComments(self, post_id: str):
50
+ return self.fetch.fetch(f"posts/{post_id}/comments")
51
+
52
+
53
+
54
+ def searchPosts(self, query: str):
55
+ return self.fetch.fetch("search/posts", params={"q": query})
56
+
57
+ def searchTags(self, query: str):
58
+ return self.fetch.fetch("search/tags", params={"q": query})
59
+
60
+ def searchSources(self, query: str):
61
+ return self.fetch.fetch("search/sources", params={"q": query})
62
+
63
+
64
+
65
+ def getBookmarks(self):
66
+ return self.fetch.fetch("bookmarks/")
67
+
68
+ def addBookmarks(self, post_ids: list[str], list_id: str | None = None):
69
+ data: dict[str, object] = {
70
+ "postIds": post_ids,
71
+ }
72
+
73
+ if list_id is not None:
74
+ data["listId"] = list_id
75
+
76
+ return self.fetch.fetch(
77
+ "bookmarks/",
78
+ method="POST",
79
+ json=data,
80
+ )
81
+
82
+ def searchBookmarks(self, query: str):
83
+ return self.fetch.fetch(
84
+ "bookmarks/search",
85
+ params={"q": query},
86
+ )
87
+
88
+ def getBookmarkLists(self):
89
+ return self.fetch.fetch("bookmarks/lists")
90
+
91
+ def createBookmarkList(self, name: str, icon: str | None = None):
92
+ data = {
93
+ "name": name,
94
+ }
95
+
96
+ if icon is not None:
97
+ data["icon"] = icon
98
+
99
+ return self.fetch.fetch(
100
+ "bookmarks/lists",
101
+ method="POST",
102
+ json=data,
103
+ )
104
+
105
+ def deleteBookmarkList(self, list_id: str):
106
+ return self.fetch.fetch(
107
+ f"bookmarks/lists/{list_id}",
108
+ method="DELETE",
109
+ )
110
+
111
+ def deleteBookmark(self, bookmark_id: str):
112
+ return self.fetch.fetch(
113
+ f"bookmarks/{bookmark_id}",
114
+ method="DELETE",
115
+ )
116
+
117
+ def moveBookmark(self, bookmark_id: str, list_id: str | None):
118
+ return self.fetch.fetch(
119
+ f"bookmarks/{bookmark_id}",
120
+ method="PATCH",
121
+ json={
122
+ "listId": list_id,
123
+ },
124
+ )
125
+
126
+
127
+
128
+ def getProfile(self):
129
+ return self.fetch.fetch("profile")
130
+
131
+ def updateProfile(self, **data):
132
+ return self.fetch.fetch(
133
+ "profile",
134
+ method="PATCH",
135
+ json=data,
136
+ )
137
+
138
+
139
+
140
+ def searchStack(self, query: str):
141
+ return self.fetch.fetch(
142
+ "profile/stack/search",
143
+ params={"q": query},
144
+ )
145
+
146
+ def getStack(self):
147
+ return self.fetch.fetch("profile/stack/")
148
+
149
+ def addStackItem(self, **data):
150
+ return self.fetch.fetch(
151
+ "profile/stack/",
152
+ method="POST",
153
+ json=data,
154
+ )
155
+
156
+ def updateStackItem(self, item_id: str, **data):
157
+ return self.fetch.fetch(
158
+ f"profile/stack/{item_id}",
159
+ method="PATCH",
160
+ json=data,
161
+ )
162
+
163
+ def deleteStackItem(self, item_id: str):
164
+ return self.fetch.fetch(
165
+ f"profile/stack/{item_id}",
166
+ method="DELETE",
167
+ )
168
+
169
+ def reorderStack(self, **data):
170
+ return self.fetch.fetch(
171
+ "profile/stack/reorder",
172
+ method="PUT",
173
+ json=data,
174
+ )
175
+
176
+
177
+
178
+ def getExperiences(self):
179
+ return self.fetch.fetch("profile/experiences/")
180
+
181
+ def createExperience(self, **data):
182
+ return self.fetch.fetch(
183
+ "profile/experiences/",
184
+ method="POST",
185
+ json=data,
186
+ )
187
+
188
+ def getExperience(self, experience_id: str):
189
+ return self.fetch.fetch(
190
+ f"profile/experiences/{experience_id}",
191
+ )
192
+
193
+ def updateExperience(self, experience_id: str, **data):
194
+ return self.fetch.fetch(
195
+ f"profile/experiences/{experience_id}",
196
+ method="PUT",
197
+ json=data,
198
+ )
199
+
200
+ def deleteExperience(self, experience_id: str):
201
+ return self.fetch.fetch(
202
+ f"profile/experiences/{experience_id}",
203
+ method="DELETE",
204
+ )
205
+
206
+
207
+
208
+ def getTags(self):
209
+ return self.fetch.fetch("tags/")
210
+
211
+
212
+
213
+ def recommendByKeyword(self, keyword: str):
214
+ return self.fetch.fetch(
215
+ "recommend/keyword",
216
+ params={"keyword": keyword},
217
+ )
218
+
219
+ def recommendSemantic(self, **params):
220
+ """
221
+ Deprecated by daily.dev.
222
+ Prefer recommendByKeyword().
223
+ """
224
+ return self.fetch.fetch(
225
+ "recommend/semantic",
226
+ params=params,
227
+ )
228
+
229
+
230
+ def signup(self, **data):
231
+ return self.fetch.fetch(
232
+ "signup/",
233
+ method="POST",
234
+ json=data,
235
+ )
236
+
237
+
238
+
239
+
@@ -0,0 +1,20 @@
1
+ import os
2
+ import dotenv
3
+
4
+ class ManualApiToken:
5
+ def __init__(self, token: str):
6
+ self.token = token
7
+
8
+ def get_token(self) -> str:
9
+ return self.token
10
+
11
+ class AutoApiToken:
12
+ """
13
+ Works ONLY if you have a enviroment variable named DAILY_DEV_KEY.
14
+ """
15
+ def __init__(self):
16
+ dotenv.load_dotenv()
17
+ self.token = os.getenv("DAILY_DEV_KEY")
18
+
19
+ def get_token(self) -> str:
20
+ return str(self.token)
File without changes