byteforge-telegram 0.1.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,10 @@
1
+ {
2
+ "permissions": {
3
+ "allow": [
4
+ "Skill(byteforge-claude-skills:python-pypi-setup)",
5
+ "Bash(test:*)"
6
+ ],
7
+ "deny": [],
8
+ "ask": []
9
+ }
10
+ }
@@ -0,0 +1,81 @@
1
+ # venv stuff
2
+ pyvenv.cfg
3
+ bin/
4
+
5
+ # Byte-compiled / optimized / DLL files
6
+ __pycache__/
7
+ *.py[cod]
8
+ *$py.class
9
+
10
+ # C extensions
11
+ *.so
12
+
13
+ # Distribution / packaging
14
+ .Python
15
+ build/
16
+ develop-eggs/
17
+ dist/
18
+ downloads/
19
+ eggs/
20
+ .eggs/
21
+ lib/
22
+ lib64/
23
+ parts/
24
+ sdist/
25
+ var/
26
+ wheels/
27
+ share/python-wheels/
28
+ *.egg-info/
29
+ .installed.cfg
30
+ *.egg
31
+ MANIFEST
32
+
33
+ # PyInstaller
34
+ *.manifest
35
+ *.spec
36
+
37
+ # Unit test / coverage reports
38
+ htmlcov/
39
+ .tox/
40
+ .nox/
41
+ .coverage
42
+ .coverage.*
43
+ .cache
44
+ nosetests.xml
45
+ coverage.xml
46
+ *.cover
47
+ *.py,cover
48
+ .hypothesis/
49
+ .pytest_cache/
50
+ cover/
51
+
52
+ # Environments
53
+ .env
54
+ .venv
55
+ env/
56
+ venv/
57
+ ENV/
58
+ env.bak/
59
+ venv.bak/
60
+
61
+ # IDEs
62
+ .vscode/
63
+ .idea/
64
+ *.swp
65
+ *.swo
66
+ *~
67
+
68
+ # OS
69
+ .DS_Store
70
+ Thumbs.db
71
+
72
+ # mypy
73
+ .mypy_cache/
74
+ .dmypy.json
75
+ dmypy.json
76
+
77
+ # Pyre type checker
78
+ .pyre/
79
+
80
+ # pytype static type analyzer
81
+ .pytype/
@@ -0,0 +1,213 @@
1
+ # CLAUDE.md
2
+
3
+ This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
4
+
5
+ ## Project Overview
6
+
7
+ `byteforge-telegram` is a reusable Python library for Telegram bot notifications and webhook management. It provides both synchronous and asynchronous APIs for sending Telegram messages and managing webhooks.
8
+
9
+ ## Development Commands
10
+
11
+ **CRITICAL**: This project uses a virtual environment. ALWAYS use `source bin/activate && python` and `source bin/activate && pip`. NEVER use `python3` or `pip3` directly - these are system executables and we always use the virtual environment.
12
+
13
+ ### Environment Setup
14
+ ```bash
15
+ # Virtual environment is already set up in this project
16
+
17
+ # Option 1: Install from requirements files
18
+ source bin/activate && pip install -r requirements.txt
19
+ source bin/activate && pip install -r dev-requirements.txt
20
+
21
+ # Option 2: Install in development mode (includes all dependencies)
22
+ source bin/activate && pip install -e ".[dev]"
23
+
24
+ # Note: requirements.txt includes mazza-base from private GitHub repo
25
+ # This requires CR_PAT environment variable to be set
26
+ # export CR_PAT=your_github_token
27
+ ```
28
+
29
+ ### Running Tests
30
+ ```bash
31
+ # Run all tests
32
+ source bin/activate && python -m pytest
33
+
34
+ # Run with coverage
35
+ source bin/activate && python -m pytest --cov=byteforge_telegram
36
+
37
+ # Run a single test file
38
+ source bin/activate && python -m pytest tests/test_notifier.py
39
+
40
+ # Run a specific test
41
+ source bin/activate && python -m pytest tests/test_notifier.py::test_send_message
42
+ ```
43
+
44
+ ### Code Formatting
45
+ ```bash
46
+ # Format code with Black (line length: 100)
47
+ source bin/activate && python -m black src/
48
+
49
+ # Check formatting without making changes
50
+ source bin/activate && python -m black --check src/
51
+
52
+ # Sort imports with isort
53
+ source bin/activate && python -m isort src/
54
+
55
+ # Check import sorting without making changes
56
+ source bin/activate && python -m isort --check-only src/
57
+ ```
58
+
59
+ ### Type Checking
60
+ ```bash
61
+ # Run mypy type checker
62
+ source bin/activate && python -m mypy src/
63
+ ```
64
+
65
+ ### Building and Publishing
66
+ ```bash
67
+ # Build package
68
+ source bin/activate && python -m build
69
+
70
+ # Publish to PyPI (requires credentials)
71
+ source bin/activate && python -m twine upload dist/*
72
+ ```
73
+
74
+ ### Testing CLI Tool Locally
75
+ ```bash
76
+ # After installing in development mode, the CLI is available
77
+ source bin/activate && setup-telegram-webhook --help
78
+ source bin/activate && setup-telegram-webhook --token YOUR_TOKEN --info
79
+ ```
80
+
81
+ ## Architecture
82
+
83
+ ### Core Components
84
+
85
+ **TelegramBotController** (`src/byteforge_telegram/notifier.py`)
86
+ - Main class for sending Telegram notifications
87
+ - Supports both sync (`send_message_sync`, `send_formatted_sync`) and async (`send_message`, `send_formatted`) methods
88
+ - Creates fresh Bot instances per call to avoid event loop conflicts
89
+ - Handles automatic session cleanup to prevent connection leaks
90
+ - Key design: Uses `_send_with_new_bot()` pattern to create disposable Bot instances
91
+
92
+ **WebhookManager** (`src/byteforge_telegram/webhook.py`)
93
+ - Manages Telegram webhook configuration via REST API
94
+ - Methods: `set_webhook()`, `get_webhook_info()`, `delete_webhook()`
95
+ - Uses synchronous `requests` library
96
+ - Validates HTTPS requirement for webhook URLs
97
+
98
+ **CLI Tool** (`src/byteforge_telegram/cli.py`)
99
+ - Command-line interface: `setup-telegram-webhook`
100
+ - Supports setting, viewing, and deleting webhooks
101
+ - Can use `--token` flag or `TELEGRAM_BOT_TOKEN` environment variable
102
+
103
+ **TelegramResponse** (`src/byteforge_telegram/models.py`)
104
+ - Dataclass for type-safe webhook response construction
105
+ - Used when handling webhook updates to return responses to Telegram
106
+ - Primary method: `to_dict()` - converts to dict for JSON serialization
107
+ - Supports reply_markup for inline keyboards and other Telegram features
108
+ - Default parse_mode is HTML
109
+
110
+ ### Sync/Async Design Pattern
111
+
112
+ The library handles both sync and async contexts by:
113
+ 1. Detecting running event loops with `asyncio.get_running_loop()`
114
+ 2. Creating tasks in existing loops OR running new loops with `asyncio.run()`
115
+ 3. Creating fresh Bot instances per message to avoid cross-loop contamination
116
+ 4. Cleaning up HTTP sessions in `finally` blocks
117
+
118
+ **CRITICAL**: When modifying async code:
119
+ - Never reuse Bot instances across async calls - always create new ones
120
+ - Always clean up sessions in `finally` blocks using dynamic attribute detection
121
+ - The `*_sync()` methods must handle both running and non-running event loop scenarios
122
+ - Use `try/except RuntimeError` to detect if an event loop is already running
123
+
124
+ ### Message Formatting
125
+
126
+ - Default parse mode: `ParseMode.HTML`
127
+ - `send_formatted()` builds HTML-formatted messages with title, key-value fields, optional emoji, and footer
128
+ - All formatting is HTML-based (bold with `<b>`, italic with `<i>`)
129
+
130
+ ## Important Patterns
131
+
132
+ ### Error Handling
133
+ - Methods return `Dict[str, bool]` mapping chat_id to success status
134
+ - Failures are logged but don't raise exceptions
135
+ - Network errors caught via `TelegramError` and general `Exception`
136
+
137
+ ### Session Management
138
+ - Each message send creates a new Bot instance
139
+ - Sessions are explicitly closed in `finally` blocks
140
+ - Uses dynamic attribute detection (`getattr`) to handle different session types
141
+
142
+ ### Type Hints
143
+ - All public methods include type hints for parameters and return types
144
+ - Uses `Optional`, `List`, `Dict`, `Any` from typing module
145
+ - Return types are explicit (e.g., `Dict[str, bool]`, `Optional[Dict[str, Any]]`)
146
+
147
+ ### Webhook Response Pattern
148
+
149
+ There are **two patterns** for handling Telegram webhooks:
150
+
151
+ **Pattern 1: Simple (using TelegramBotController)**
152
+ - Process the webhook update
153
+ - Use `TelegramBotController.send_message_sync()` to send responses
154
+ - Return `{'ok': True}` to acknowledge webhook
155
+ - Good for simple bots and async processing
156
+
157
+ **Pattern 2: Advanced (using TelegramResponse)**
158
+ - Process the webhook update
159
+ - Create `TelegramResponse` object
160
+ - Return `response.to_dict()` directly in webhook response
161
+ - Telegram processes the response inline
162
+ - More efficient, no separate API call
163
+ - Typical pattern:
164
+ ```python
165
+ response = TelegramResponse(
166
+ method='sendMessage',
167
+ chat_id=chat_id,
168
+ text='<b>Response text</b>',
169
+ parse_mode='HTML'
170
+ )
171
+ return jsonify(response.to_dict()), 200
172
+ ```
173
+
174
+ ## Project Structure
175
+
176
+ ```
177
+ src/byteforge_telegram/
178
+ ├── __init__.py # Package exports
179
+ ├── notifier.py # TelegramBotController and ParseMode
180
+ ├── webhook.py # WebhookManager
181
+ ├── models.py # TelegramResponse dataclass
182
+ └── cli.py # CLI entry point
183
+ ```
184
+
185
+ ## Dependencies
186
+
187
+ **Production (requirements.txt):**
188
+ - `python-telegram-bot` - Core Telegram API wrapper
189
+ - `mazza-base` - Mazza base library from private GitHub repo (requires CR_PAT env var)
190
+
191
+ **Development (dev-requirements.txt):**
192
+ - `mypy` - Type checking
193
+ - `black` - Code formatting
194
+ - `isort` - Import sorting
195
+
196
+ **Additional from pyproject.toml:**
197
+ - `requests>=2.31.0` - HTTP client for webhook management
198
+ - Dev: `pytest`, `pytest-asyncio`
199
+
200
+ ## Testing Notes
201
+
202
+ - No test files exist yet in the repository
203
+ - When adding tests, use `pytest-asyncio` for async test support
204
+ - Test both sync and async methods
205
+ - Mock Telegram API calls to avoid real API usage
206
+ - **CRITICAL**: After making changes, always run `source bin/activate && python -m pytest` BEFORE committing code
207
+ - Remember: NEVER use `python3` - always use the venv with `source bin/activate && python`
208
+
209
+ ## Version Management
210
+
211
+ - Version is defined in `pyproject.toml` (currently 0.1.0)
212
+ - Version must also be updated in `src/byteforge_telegram/__init__.py`
213
+ - When bumping version, update both files to keep them in sync
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2025 Jason Byteforge
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.
@@ -0,0 +1,4 @@
1
+ include README.md
2
+ include LICENSE
3
+ include pyproject.toml
4
+ recursive-include src *.py