firefeed-core 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.
Files changed (97) hide show
  1. firefeed_core-1.0.0/LICENSE +45 -0
  2. firefeed_core-1.0.0/PKG-INFO +276 -0
  3. firefeed_core-1.0.0/README.md +232 -0
  4. firefeed_core-1.0.0/pyproject.toml +139 -0
  5. firefeed_core-1.0.0/setup.cfg +4 -0
  6. firefeed_core-1.0.0/src/firefeed_core/__init__.py +52 -0
  7. firefeed_core-1.0.0/src/firefeed_core/api_client/__init__.py +17 -0
  8. firefeed_core-1.0.0/src/firefeed_core/api_client/circuit_breaker.py +141 -0
  9. firefeed_core-1.0.0/src/firefeed_core/api_client/client.py +434 -0
  10. firefeed_core-1.0.0/src/firefeed_core/api_client/rate_limiter.py +269 -0
  11. firefeed_core-1.0.0/src/firefeed_core/api_client/retry.py +183 -0
  12. firefeed_core-1.0.0/src/firefeed_core/auth/__init__.py +16 -0
  13. firefeed_core-1.0.0/src/firefeed_core/auth/permissions.py +243 -0
  14. firefeed_core-1.0.0/src/firefeed_core/auth/token_manager.py +390 -0
  15. firefeed_core-1.0.0/src/firefeed_core/auth/token_validator.py +241 -0
  16. firefeed_core-1.0.0/src/firefeed_core/config/__init__.py +30 -0
  17. firefeed_core-1.0.0/src/firefeed_core/config/base_config.py +375 -0
  18. firefeed_core-1.0.0/src/firefeed_core/config/logging_config.py +21 -0
  19. firefeed_core-1.0.0/src/firefeed_core/config/redis_config.py +210 -0
  20. firefeed_core-1.0.0/src/firefeed_core/config/redis_utils.py +224 -0
  21. firefeed_core-1.0.0/src/firefeed_core/config/services_config.py +251 -0
  22. firefeed_core-1.0.0/src/firefeed_core/config/settings.py +139 -0
  23. firefeed_core-1.0.0/src/firefeed_core/config/validation.py +414 -0
  24. firefeed_core-1.0.0/src/firefeed_core/di_container.py +108 -0
  25. firefeed_core-1.0.0/src/firefeed_core/email_service/__init__.py +0 -0
  26. firefeed_core-1.0.0/src/firefeed_core/email_service/sender.py +825 -0
  27. firefeed_core-1.0.0/src/firefeed_core/exceptions/__init__.py +161 -0
  28. firefeed_core-1.0.0/src/firefeed_core/exceptions/api_exceptions.py +234 -0
  29. firefeed_core-1.0.0/src/firefeed_core/exceptions/base_exceptions.py +139 -0
  30. firefeed_core-1.0.0/src/firefeed_core/exceptions/database_exceptions.py +25 -0
  31. firefeed_core-1.0.0/src/firefeed_core/exceptions/rss_exceptions.py +59 -0
  32. firefeed_core-1.0.0/src/firefeed_core/exceptions/service_exceptions.py +236 -0
  33. firefeed_core-1.0.0/src/firefeed_core/interfaces/__init__.py +11 -0
  34. firefeed_core-1.0.0/src/firefeed_core/interfaces/base_interfaces.py +225 -0
  35. firefeed_core-1.0.0/src/firefeed_core/interfaces/core_interfaces.py +65 -0
  36. firefeed_core-1.0.0/src/firefeed_core/interfaces/email_interfaces.py +36 -0
  37. firefeed_core-1.0.0/src/firefeed_core/interfaces/media_interfaces.py +36 -0
  38. firefeed_core-1.0.0/src/firefeed_core/interfaces/repository_interfaces.py +212 -0
  39. firefeed_core-1.0.0/src/firefeed_core/interfaces/rss_interfaces.py +171 -0
  40. firefeed_core-1.0.0/src/firefeed_core/interfaces/telegram_interfaces.py +208 -0
  41. firefeed_core-1.0.0/src/firefeed_core/interfaces/text_analysis_interfaces.py +36 -0
  42. firefeed_core-1.0.0/src/firefeed_core/interfaces/translation_interfaces.py +116 -0
  43. firefeed_core-1.0.0/src/firefeed_core/interfaces/user_interfaces.py +207 -0
  44. firefeed_core-1.0.0/src/firefeed_core/models/__init__.py +11 -0
  45. firefeed_core-1.0.0/src/firefeed_core/models/api_key_models.py +37 -0
  46. firefeed_core-1.0.0/src/firefeed_core/models/base_models.py +1172 -0
  47. firefeed_core-1.0.0/src/firefeed_core/models/category_models.py +8 -0
  48. firefeed_core-1.0.0/src/firefeed_core/models/error_models.py +7 -0
  49. firefeed_core-1.0.0/src/firefeed_core/models/media_models.py +7 -0
  50. firefeed_core-1.0.0/src/firefeed_core/models/rss_models.py +96 -0
  51. firefeed_core-1.0.0/src/firefeed_core/models/source_models.py +9 -0
  52. firefeed_core-1.0.0/src/firefeed_core/models/telegram_models.py +18 -0
  53. firefeed_core-1.0.0/src/firefeed_core/models/translation_models.py +14 -0
  54. firefeed_core-1.0.0/src/firefeed_core/models/user_models.py +126 -0
  55. firefeed_core-1.0.0/src/firefeed_core/services/email_service.py +825 -0
  56. firefeed_core-1.0.0/src/firefeed_core/services/rss_service.py +185 -0
  57. firefeed_core-1.0.0/src/firefeed_core/services/translation_service.py +602 -0
  58. firefeed_core-1.0.0/src/firefeed_core/tests/__init__.py +3 -0
  59. firefeed_core-1.0.0/src/firefeed_core/tests/integration/__init__.py +0 -0
  60. firefeed_core-1.0.0/src/firefeed_core/tests/integration/test_api_client.py +283 -0
  61. firefeed_core-1.0.0/src/firefeed_core/tests/integration/test_email_service.py +275 -0
  62. firefeed_core-1.0.0/src/firefeed_core/tests/unit/__init__.py +0 -0
  63. firefeed_core-1.0.0/src/firefeed_core/tests/unit/api/__init__.py +0 -0
  64. firefeed_core-1.0.0/src/firefeed_core/tests/unit/config/__init__.py +0 -0
  65. firefeed_core-1.0.0/src/firefeed_core/tests/unit/core/__init__.py +0 -0
  66. firefeed_core-1.0.0/src/firefeed_core/tests/unit/database/__init__.py +0 -0
  67. firefeed_core-1.0.0/src/firefeed_core/tests/unit/email/__init__.py +1 -0
  68. firefeed_core-1.0.0/src/firefeed_core/tests/unit/email/test_email_sender.py +296 -0
  69. firefeed_core-1.0.0/src/firefeed_core/tests/unit/exceptions/__init__.py +0 -0
  70. firefeed_core-1.0.0/src/firefeed_core/tests/unit/models/__init__.py +0 -0
  71. firefeed_core-1.0.0/src/firefeed_core/tests/unit/repositories/__init__.py +0 -0
  72. firefeed_core-1.0.0/src/firefeed_core/tests/unit/services/__init__.py +0 -0
  73. firefeed_core-1.0.0/src/firefeed_core/tests/unit/utils/__init__.py +0 -0
  74. firefeed_core-1.0.0/src/firefeed_core/utils/__init__.py +355 -0
  75. firefeed_core-1.0.0/src/firefeed_core/utils/api.py +67 -0
  76. firefeed_core-1.0.0/src/firefeed_core/utils/async_utils.py +415 -0
  77. firefeed_core-1.0.0/src/firefeed_core/utils/cache.py +74 -0
  78. firefeed_core-1.0.0/src/firefeed_core/utils/cache_utils.py +404 -0
  79. firefeed_core-1.0.0/src/firefeed_core/utils/cleanup.py +80 -0
  80. firefeed_core-1.0.0/src/firefeed_core/utils/file_utils.py +421 -0
  81. firefeed_core-1.0.0/src/firefeed_core/utils/formatting_utils.py +397 -0
  82. firefeed_core-1.0.0/src/firefeed_core/utils/image.py +185 -0
  83. firefeed_core-1.0.0/src/firefeed_core/utils/image_utils.py +333 -0
  84. firefeed_core-1.0.0/src/firefeed_core/utils/network_utils.py +430 -0
  85. firefeed_core-1.0.0/src/firefeed_core/utils/retry.py +72 -0
  86. firefeed_core-1.0.0/src/firefeed_core/utils/retry_utils.py +350 -0
  87. firefeed_core-1.0.0/src/firefeed_core/utils/security_utils.py +492 -0
  88. firefeed_core-1.0.0/src/firefeed_core/utils/text.py +90 -0
  89. firefeed_core-1.0.0/src/firefeed_core/utils/text_utils.py +431 -0
  90. firefeed_core-1.0.0/src/firefeed_core/utils/time_utils.py +363 -0
  91. firefeed_core-1.0.0/src/firefeed_core/utils/validation_utils.py +457 -0
  92. firefeed_core-1.0.0/src/firefeed_core/utils/video.py +126 -0
  93. firefeed_core-1.0.0/src/firefeed_core.egg-info/PKG-INFO +276 -0
  94. firefeed_core-1.0.0/src/firefeed_core.egg-info/SOURCES.txt +95 -0
  95. firefeed_core-1.0.0/src/firefeed_core.egg-info/dependency_links.txt +1 -0
  96. firefeed_core-1.0.0/src/firefeed_core.egg-info/requires.txt +25 -0
  97. firefeed_core-1.0.0/src/firefeed_core.egg-info/top_level.txt +1 -0
@@ -0,0 +1,45 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2025 FireFeed Project
4
+
5
+ Данная лицензия разрешает лицам, получившим копию данного программного обеспечения
6
+ и сопутствующей документации (в дальнейшем «Программное обеспечение»), безвозмездно
7
+ использовать Программное обеспечение без ограничений, включая неограниченное право
8
+ на использование, копирование, изменение, слияние, публикацию, распространение,
9
+ сублицензирование и/или продажу копий Программного обеспечения, а также лицам,
10
+ которым предоставляется данное Программное обеспечение, при соблюдении следующих условий:
11
+
12
+ Указанное выше уведомление об авторских правах и данные условия должны быть включены
13
+ во все копии или значимые части данного Программного обеспечения.
14
+
15
+ ДАННОЕ ПРОГРАММНОЕ ОБЕСПЕЧЕНИЕ ПРЕДОСТАВЛЯЕТСЯ «КАК ЕСТЬ», БЕЗ КАКИХ-ЛИБО ГАРАНТИЙ,
16
+ ЯВНО ВЫРАЖЕННЫХ ИЛИ ПОДРАЗУМЕВАЕМЫХ, ВКЛЮЧАЯ ГАРАНТИИ ТОВАРНОЙ ПРИГОДНОСТИ,
17
+ СООТВЕТСТВИЯ ПО ЕГО КОНКРЕТНОМУ НАЗНАЧЕНИЮ И ОТСУТСТВИЯ НАРУШЕНИЙ, НО НЕ ОГРАНИЧИВАЯСЬ
18
+ ИМИ. НИ В КАКОМ СЛУЧАЕ АВТОРЫ ИЛИ ПРАВООБЛАДАТЕЛИ НЕ НЕСУТ ОТВЕТСТВЕННОСТИ ПО КАКИМ-ЛИБО
19
+ ИСКАМ, ЗА УЩЕРБ ИЛИ ПО ИНЫМ ТРЕБОВАНИЯМ, В ТОМ ЧИСЛЕ, ПРИ ДЕЙСТВИИ КОНТРАКТА,
20
+ ДЕЛИКТЕ ИЛИ ИНОЙ СИТУАЦИИ, ВОЗНИКШИМ ИЗ-ЗА ИСПОЛЬЗОВАНИЯ ПРОГРАММНОГО ОБЕСПЕЧЕНИЯ
21
+ ИЛИ ИНЫХ ДЕЙСТВИЙ С ПРОГРАММНЫМ ОБЕСПЕЧЕНИЕМ.
22
+
23
+ ---
24
+
25
+ MIT License
26
+
27
+ Copyright (c) 2024 FireFeed Project
28
+
29
+ Permission is hereby granted, free of charge, to any person obtaining a copy
30
+ of this software and associated documentation files (the "Software"), to deal
31
+ in the Software without restriction, including without limitation the rights
32
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
33
+ copies of the Software, and to permit persons to whom the Software is
34
+ furnished to do so, subject to the following conditions:
35
+
36
+ The above copyright notice and this permission notice shall be included in all
37
+ copies or substantial portions of the Software.
38
+
39
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
40
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
41
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
42
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
43
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
44
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
45
+ SOFTWARE.
@@ -0,0 +1,276 @@
1
+ Metadata-Version: 2.4
2
+ Name: firefeed_core
3
+ Version: 1.0.0
4
+ Summary: Core utilities and models for FireFeed microservices
5
+ Author-email: FireFeed <mail@firefeed.net>
6
+ License: MIT
7
+ Project-URL: Homepage, https://firefeed.net
8
+ Project-URL: Repository, https://github.com/firefeed-net/firefeed-core
9
+ Project-URL: Documentation, https://docs.firefeed.net
10
+ Project-URL: Bug Tracker, https://github.com/firefeed-net/firefeed-core/issues
11
+ Keywords: firefeed,microservices,core,rss,news
12
+ Classifier: Development Status :: 4 - Beta
13
+ Classifier: Intended Audience :: Developers
14
+ Classifier: License :: OSI Approved :: MIT License
15
+ Classifier: Programming Language :: Python :: 3
16
+ Classifier: Programming Language :: Python :: 3.13
17
+ Requires-Python: >=3.13
18
+ Description-Content-Type: text/markdown
19
+ License-File: LICENSE
20
+ Requires-Dist: pydantic>=2.0.0
21
+ Requires-Dist: pydantic-settings>=2.0.0
22
+ Requires-Dist: python-dotenv>=1.0.0
23
+ Requires-Dist: httpx>=0.25.0
24
+ Requires-Dist: PyJWT>=2.8.0
25
+ Requires-Dist: typing-extensions>=4.5.0
26
+ Requires-Dist: datetime
27
+ Requires-Dist: jinja2>=3.1.0
28
+ Requires-Dist: aiosmtplib>=2.0.0
29
+ Provides-Extra: dev
30
+ Requires-Dist: pytest>=7.0.0; extra == "dev"
31
+ Requires-Dist: pytest-asyncio>=0.21.0; extra == "dev"
32
+ Requires-Dist: pytest-cov>=4.0.0; extra == "dev"
33
+ Requires-Dist: black>=23.0.0; extra == "dev"
34
+ Requires-Dist: isort>=5.12.0; extra == "dev"
35
+ Requires-Dist: mypy>=1.5.0; extra == "dev"
36
+ Requires-Dist: flake8>=6.0.0; extra == "dev"
37
+ Requires-Dist: pre-commit>=3.0.0; extra == "dev"
38
+ Provides-Extra: test
39
+ Requires-Dist: pytest>=7.0.0; extra == "test"
40
+ Requires-Dist: pytest-asyncio>=0.21.0; extra == "test"
41
+ Requires-Dist: pytest-cov>=4.0.0; extra == "test"
42
+ Requires-Dist: pytest-mock>=3.11.0; extra == "test"
43
+ Dynamic: license-file
44
+
45
+ # FireFeed Core
46
+
47
+ Core utilities and models for FireFeed microservices architecture.
48
+
49
+ FireFeed Core is a shared library that provides common components for all FireFeed microservices, ensuring consistency, security, and reliability across the distributed system.
50
+
51
+ ## 🚀 Features
52
+
53
+ - **API Client**: Robust HTTP client with authentication, retry policies, circuit breaker, and rate limiting
54
+ - **JWT Authentication**: Service-to-service authentication with token management
55
+ - **Exception Handling**: Comprehensive exception hierarchy for consistent error handling
56
+ - **Configuration**: Pydantic-based configuration management
57
+ - **Interfaces**: Abstract interfaces for service contracts
58
+ - **Utilities**: Common utility functions and helpers
59
+
60
+ ## 📦 Installation
61
+
62
+ ```bash
63
+ pip install firefeed-core
64
+ ```
65
+
66
+ ## 🔧 Quick Start
67
+
68
+ ### Basic API Client Usage
69
+
70
+ ```python
71
+ import asyncio
72
+ from firefeed_core import APIClient
73
+
74
+ async def main():
75
+ # Initialize API client
76
+ async with APIClient(
77
+ base_url="http://firefeed-api:8000",
78
+ token="your-jwt-token",
79
+ service_id="firefeed-rss-parser"
80
+ ) as client:
81
+
82
+ # Make authenticated requests
83
+ feeds = await client.get("/api/v1/internal/rss/feeds")
84
+ print(f"Found {len(feeds)} feeds")
85
+
86
+ # Create new RSS item
87
+ new_item = await client.post("/api/v1/internal/rss/items", {
88
+ "title": "Test Article",
89
+ "content": "This is a test article",
90
+ "feed_id": 123
91
+ })
92
+
93
+ asyncio.run(main())
94
+ ```
95
+
96
+ ### JWT Token Management
97
+
98
+ ```python
99
+ from firefeed_core import ServiceTokenManager
100
+
101
+ # Generate token for service
102
+ token_manager = ServiceTokenManager(
103
+ secret_key="your-secret-key",
104
+ issuer="firefeed-api"
105
+ )
106
+
107
+ token = token_manager.generate_service_token(
108
+ service_id="firefeed-rss-parser",
109
+ audience="firefeed-api",
110
+ scopes=["rss:read", "rss:write"]
111
+ )
112
+
113
+ # Verify token
114
+ payload = token_manager.verify_token(token)
115
+ print(f"Token for service: {payload.sub}")
116
+ ```
117
+
118
+ ### Exception Handling
119
+
120
+ ```python
121
+ from firefeed_core import APIException, NotFoundException
122
+
123
+ try:
124
+ result = await client.get("/api/v1/internal/rss/feeds/999")
125
+ except NotFoundException as e:
126
+ print(f"Feed not found: {e.message}")
127
+ except APIException as e:
128
+ print(f"API error: {e.message}")
129
+ ```
130
+
131
+ ## 🔐 Authentication
132
+
133
+ FireFeed Core uses JWT tokens for service-to-service authentication. Each service needs:
134
+
135
+ 1. **Service Token**: JWT token with appropriate scopes
136
+ 2. **Service ID**: Unique identifier for the service
137
+ 3. **Secret Key**: Shared secret for token verification
138
+
139
+ ### Environment Configuration
140
+
141
+ Each service should have its own `.env` file:
142
+
143
+ ```bash
144
+ # firefeed-rss-parser/.env
145
+ FIREFEED_API_URL=http://firefeed-api:8000
146
+ FIREFEED_API_TOKEN=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...
147
+ FIREFEED_RSS_PARSER_SERVICE_ID=rss-parser
148
+
149
+ # firefeed-telegram-bot/.env
150
+ FIREFEED_API_URL=http://firefeed-api:8000
151
+ FIREFEED_API_TOKEN=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...
152
+ FIREFEED_TELEGRAM_BOT_SERVICE_ID=telegram-bot
153
+ ```
154
+
155
+ ### Token Scopes
156
+
157
+ Services can be granted specific scopes for different operations:
158
+
159
+ - `rss:read` - Read RSS data
160
+ - `rss:write` - Create/modify RSS data
161
+ - `users:read` - Read user data
162
+ - `users:write` - Modify user data
163
+ - `categories:read` - Read categories
164
+ - `categories:write` - Modify categories
165
+
166
+ ## 🛠️ Advanced Features
167
+
168
+ ### Circuit Breaker
169
+
170
+ Automatically prevents requests to failing services:
171
+
172
+ ```python
173
+ from firefeed_core import APIClient
174
+
175
+ client = APIClient(
176
+ base_url="http://service:8000",
177
+ token="token",
178
+ service_id="my-service",
179
+ circuit_breaker_failure_threshold=5,
180
+ circuit_breaker_timeout=60
181
+ )
182
+ ```
183
+
184
+ ### Retry Policies
185
+
186
+ Configurable retry with exponential backoff:
187
+
188
+ ```python
189
+ client = APIClient(
190
+ base_url="http://service:8000",
191
+ token="token",
192
+ service_id="my-service",
193
+ max_retries=3
194
+ )
195
+ ```
196
+
197
+ ### Rate Limiting
198
+
199
+ Prevents API abuse:
200
+
201
+ ```python
202
+ client = APIClient(
203
+ base_url="http://service:8000",
204
+ token="token",
205
+ service_id="my-service",
206
+ rate_limit_requests=100,
207
+ rate_limit_window=60
208
+ )
209
+ ```
210
+
211
+ ## 📊 Monitoring
212
+
213
+ Each API client provides comprehensive statistics:
214
+
215
+ ```python
216
+ stats = client.get_stats()
217
+ print(f"Circuit breaker state: {stats['circuit_breaker']['state']}")
218
+ print(f"Rate limit usage: {stats['rate_limiter']['current_requests']}")
219
+ ```
220
+
221
+ ## 🏗️ Architecture
222
+
223
+ FireFeed Core follows these principles:
224
+
225
+ 1. **API-First**: All services communicate via HTTP APIs only
226
+ 2. **Zero Direct Database Access**: Services never access databases directly
227
+ 3. **Token-Based Security**: All inter-service communication is authenticated
228
+ 4. **Fault Tolerance**: Circuit breakers, retries, and rate limiting
229
+ 5. **Consistent Error Handling**: Standardized exception hierarchy
230
+
231
+ ### Service Communication Flow
232
+
233
+ ```
234
+ ┌─────────────────────┐ JWT Token ┌─────────────────────┐
235
+ │ firefeed-rss-parser│ ──────────────→ │ firefeed-api │
236
+ │ (Dumb Service) │ │ (Smart Service) │
237
+ │ │ ←────────────── │ │
238
+ │ - RSS Processing │ HTTP API │ - Database Access │
239
+ │ - No DB Access │ │ - Business Logic │
240
+ └─────────────────────┘ └─────────────────────┘
241
+ ```
242
+
243
+ ## 🧪 Testing
244
+
245
+ ```bash
246
+ # Install test dependencies
247
+ pip install -e ".[test]"
248
+
249
+ # Run tests
250
+ pytest
251
+
252
+ # Run with coverage
253
+ pytest --cov=firefeed_core
254
+ ```
255
+
256
+ ## 📝 Contributing
257
+
258
+ 1. Fork the repository
259
+ 2. Create a feature branch
260
+ 3. Make your changes
261
+ 4. Add tests
262
+ 5. Submit a pull request
263
+
264
+ ## 📄 License
265
+
266
+ MIT License - see LICENSE file for details.
267
+
268
+ ## 🔗 Related Projects
269
+
270
+ - [FireFeed API](https://github.com/firefeed-net/firefeed-api) - Main API service
271
+ - [FireFeed RSS Parser](https://github.com/firefeed-net/firefeed-rss-parser) - RSS processing service
272
+ - [FireFeed Telegram Bot](https://github.com/firefeed-net/firefeed-telegram-bot) - Telegram bot service
273
+
274
+ ---
275
+
276
+ **Note**: This is a core library intended for use within the FireFeed microservices ecosystem.
@@ -0,0 +1,232 @@
1
+ # FireFeed Core
2
+
3
+ Core utilities and models for FireFeed microservices architecture.
4
+
5
+ FireFeed Core is a shared library that provides common components for all FireFeed microservices, ensuring consistency, security, and reliability across the distributed system.
6
+
7
+ ## 🚀 Features
8
+
9
+ - **API Client**: Robust HTTP client with authentication, retry policies, circuit breaker, and rate limiting
10
+ - **JWT Authentication**: Service-to-service authentication with token management
11
+ - **Exception Handling**: Comprehensive exception hierarchy for consistent error handling
12
+ - **Configuration**: Pydantic-based configuration management
13
+ - **Interfaces**: Abstract interfaces for service contracts
14
+ - **Utilities**: Common utility functions and helpers
15
+
16
+ ## 📦 Installation
17
+
18
+ ```bash
19
+ pip install firefeed-core
20
+ ```
21
+
22
+ ## 🔧 Quick Start
23
+
24
+ ### Basic API Client Usage
25
+
26
+ ```python
27
+ import asyncio
28
+ from firefeed_core import APIClient
29
+
30
+ async def main():
31
+ # Initialize API client
32
+ async with APIClient(
33
+ base_url="http://firefeed-api:8000",
34
+ token="your-jwt-token",
35
+ service_id="firefeed-rss-parser"
36
+ ) as client:
37
+
38
+ # Make authenticated requests
39
+ feeds = await client.get("/api/v1/internal/rss/feeds")
40
+ print(f"Found {len(feeds)} feeds")
41
+
42
+ # Create new RSS item
43
+ new_item = await client.post("/api/v1/internal/rss/items", {
44
+ "title": "Test Article",
45
+ "content": "This is a test article",
46
+ "feed_id": 123
47
+ })
48
+
49
+ asyncio.run(main())
50
+ ```
51
+
52
+ ### JWT Token Management
53
+
54
+ ```python
55
+ from firefeed_core import ServiceTokenManager
56
+
57
+ # Generate token for service
58
+ token_manager = ServiceTokenManager(
59
+ secret_key="your-secret-key",
60
+ issuer="firefeed-api"
61
+ )
62
+
63
+ token = token_manager.generate_service_token(
64
+ service_id="firefeed-rss-parser",
65
+ audience="firefeed-api",
66
+ scopes=["rss:read", "rss:write"]
67
+ )
68
+
69
+ # Verify token
70
+ payload = token_manager.verify_token(token)
71
+ print(f"Token for service: {payload.sub}")
72
+ ```
73
+
74
+ ### Exception Handling
75
+
76
+ ```python
77
+ from firefeed_core import APIException, NotFoundException
78
+
79
+ try:
80
+ result = await client.get("/api/v1/internal/rss/feeds/999")
81
+ except NotFoundException as e:
82
+ print(f"Feed not found: {e.message}")
83
+ except APIException as e:
84
+ print(f"API error: {e.message}")
85
+ ```
86
+
87
+ ## 🔐 Authentication
88
+
89
+ FireFeed Core uses JWT tokens for service-to-service authentication. Each service needs:
90
+
91
+ 1. **Service Token**: JWT token with appropriate scopes
92
+ 2. **Service ID**: Unique identifier for the service
93
+ 3. **Secret Key**: Shared secret for token verification
94
+
95
+ ### Environment Configuration
96
+
97
+ Each service should have its own `.env` file:
98
+
99
+ ```bash
100
+ # firefeed-rss-parser/.env
101
+ FIREFEED_API_URL=http://firefeed-api:8000
102
+ FIREFEED_API_TOKEN=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...
103
+ FIREFEED_RSS_PARSER_SERVICE_ID=rss-parser
104
+
105
+ # firefeed-telegram-bot/.env
106
+ FIREFEED_API_URL=http://firefeed-api:8000
107
+ FIREFEED_API_TOKEN=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...
108
+ FIREFEED_TELEGRAM_BOT_SERVICE_ID=telegram-bot
109
+ ```
110
+
111
+ ### Token Scopes
112
+
113
+ Services can be granted specific scopes for different operations:
114
+
115
+ - `rss:read` - Read RSS data
116
+ - `rss:write` - Create/modify RSS data
117
+ - `users:read` - Read user data
118
+ - `users:write` - Modify user data
119
+ - `categories:read` - Read categories
120
+ - `categories:write` - Modify categories
121
+
122
+ ## 🛠️ Advanced Features
123
+
124
+ ### Circuit Breaker
125
+
126
+ Automatically prevents requests to failing services:
127
+
128
+ ```python
129
+ from firefeed_core import APIClient
130
+
131
+ client = APIClient(
132
+ base_url="http://service:8000",
133
+ token="token",
134
+ service_id="my-service",
135
+ circuit_breaker_failure_threshold=5,
136
+ circuit_breaker_timeout=60
137
+ )
138
+ ```
139
+
140
+ ### Retry Policies
141
+
142
+ Configurable retry with exponential backoff:
143
+
144
+ ```python
145
+ client = APIClient(
146
+ base_url="http://service:8000",
147
+ token="token",
148
+ service_id="my-service",
149
+ max_retries=3
150
+ )
151
+ ```
152
+
153
+ ### Rate Limiting
154
+
155
+ Prevents API abuse:
156
+
157
+ ```python
158
+ client = APIClient(
159
+ base_url="http://service:8000",
160
+ token="token",
161
+ service_id="my-service",
162
+ rate_limit_requests=100,
163
+ rate_limit_window=60
164
+ )
165
+ ```
166
+
167
+ ## 📊 Monitoring
168
+
169
+ Each API client provides comprehensive statistics:
170
+
171
+ ```python
172
+ stats = client.get_stats()
173
+ print(f"Circuit breaker state: {stats['circuit_breaker']['state']}")
174
+ print(f"Rate limit usage: {stats['rate_limiter']['current_requests']}")
175
+ ```
176
+
177
+ ## 🏗️ Architecture
178
+
179
+ FireFeed Core follows these principles:
180
+
181
+ 1. **API-First**: All services communicate via HTTP APIs only
182
+ 2. **Zero Direct Database Access**: Services never access databases directly
183
+ 3. **Token-Based Security**: All inter-service communication is authenticated
184
+ 4. **Fault Tolerance**: Circuit breakers, retries, and rate limiting
185
+ 5. **Consistent Error Handling**: Standardized exception hierarchy
186
+
187
+ ### Service Communication Flow
188
+
189
+ ```
190
+ ┌─────────────────────┐ JWT Token ┌─────────────────────┐
191
+ │ firefeed-rss-parser│ ──────────────→ │ firefeed-api │
192
+ │ (Dumb Service) │ │ (Smart Service) │
193
+ │ │ ←────────────── │ │
194
+ │ - RSS Processing │ HTTP API │ - Database Access │
195
+ │ - No DB Access │ │ - Business Logic │
196
+ └─────────────────────┘ └─────────────────────┘
197
+ ```
198
+
199
+ ## 🧪 Testing
200
+
201
+ ```bash
202
+ # Install test dependencies
203
+ pip install -e ".[test]"
204
+
205
+ # Run tests
206
+ pytest
207
+
208
+ # Run with coverage
209
+ pytest --cov=firefeed_core
210
+ ```
211
+
212
+ ## 📝 Contributing
213
+
214
+ 1. Fork the repository
215
+ 2. Create a feature branch
216
+ 3. Make your changes
217
+ 4. Add tests
218
+ 5. Submit a pull request
219
+
220
+ ## 📄 License
221
+
222
+ MIT License - see LICENSE file for details.
223
+
224
+ ## 🔗 Related Projects
225
+
226
+ - [FireFeed API](https://github.com/firefeed-net/firefeed-api) - Main API service
227
+ - [FireFeed RSS Parser](https://github.com/firefeed-net/firefeed-rss-parser) - RSS processing service
228
+ - [FireFeed Telegram Bot](https://github.com/firefeed-net/firefeed-telegram-bot) - Telegram bot service
229
+
230
+ ---
231
+
232
+ **Note**: This is a core library intended for use within the FireFeed microservices ecosystem.
@@ -0,0 +1,139 @@
1
+ [build-system]
2
+ requires = ["setuptools>=61.0", "wheel"]
3
+ build-backend = "setuptools.build_meta"
4
+
5
+ [project]
6
+ name = "firefeed_core"
7
+ version = "1.0.0"
8
+ description = "Core utilities and models for FireFeed microservices"
9
+ authors = [
10
+ {name = "FireFeed", email = "mail@firefeed.net"}
11
+ ]
12
+ readme = "README.md"
13
+ license = {text = "MIT"}
14
+ requires-python = ">=3.13"
15
+ classifiers = [
16
+ "Development Status :: 4 - Beta",
17
+ "Intended Audience :: Developers",
18
+ "License :: OSI Approved :: MIT License",
19
+ "Programming Language :: Python :: 3",
20
+ "Programming Language :: Python :: 3.13",
21
+ ]
22
+ keywords = ["firefeed", "microservices", "core", "rss", "news"]
23
+ dependencies = [
24
+ "pydantic>=2.0.0",
25
+ "pydantic-settings>=2.0.0",
26
+ "python-dotenv>=1.0.0",
27
+ "httpx>=0.25.0",
28
+ "PyJWT>=2.8.0",
29
+ "typing-extensions>=4.5.0",
30
+ "datetime",
31
+ "jinja2>=3.1.0",
32
+ "aiosmtplib>=2.0.0",
33
+ ]
34
+
35
+ [project.optional-dependencies]
36
+ dev = [
37
+ "pytest>=7.0.0",
38
+ "pytest-asyncio>=0.21.0",
39
+ "pytest-cov>=4.0.0",
40
+ "black>=23.0.0",
41
+ "isort>=5.12.0",
42
+ "mypy>=1.5.0",
43
+ "flake8>=6.0.0",
44
+ "pre-commit>=3.0.0",
45
+ ]
46
+
47
+ test = [
48
+ "pytest>=7.0.0",
49
+ "pytest-asyncio>=0.21.0",
50
+ "pytest-cov>=4.0.0",
51
+ "pytest-mock>=3.11.0",
52
+ ]
53
+
54
+ [project.urls]
55
+ Homepage = "https://firefeed.net"
56
+ Repository = "https://github.com/firefeed-net/firefeed-core"
57
+ Documentation = "https://docs.firefeed.net"
58
+ "Bug Tracker" = "https://github.com/firefeed-net/firefeed-core/issues"
59
+
60
+ [tool.setuptools.packages.find]
61
+ where = ["src"]
62
+ include = ["firefeed_core*"]
63
+ exclude = ["tests*"]
64
+
65
+ [tool.black]
66
+ line-length = 88
67
+ target-version = ['py313']
68
+ include = '\.pyi?$'
69
+ extend-exclude = '''
70
+ /(
71
+ # directories
72
+ \.eggs
73
+ | \.git
74
+ | \.hg
75
+ | \.mypy_cache
76
+ | \.tox
77
+ | \.venv
78
+ | build
79
+ | dist
80
+ )/
81
+ '''
82
+
83
+ [tool.isort]
84
+ profile = "black"
85
+ multi_line_output = 3
86
+ line_length = 88
87
+ known_first_party = ["firefeed_core"]
88
+
89
+ [tool.mypy]
90
+ python_version = "3.13"
91
+ warn_return_any = true
92
+ warn_unused_configs = true
93
+ disallow_untyped_defs = true
94
+ disallow_incomplete_defs = true
95
+ check_untyped_defs = true
96
+ disallow_untyped_decorators = true
97
+ no_implicit_optional = true
98
+ warn_redundant_casts = true
99
+ warn_unused_ignores = true
100
+ warn_no_return = true
101
+ warn_unreachable = true
102
+ strict_equality = true
103
+
104
+ [[tool.mypy.overrides]]
105
+ module = "tests.*"
106
+ disallow_untyped_defs = false
107
+
108
+ [tool.pytest.ini_options]
109
+ minversion = "7.0"
110
+ addopts = "-ra -q --strict-markers --cov=firefeed_core --cov-report=term-missing --cov-report=html"
111
+ testpaths = ["tests"]
112
+ asyncio_mode = "auto"
113
+ markers = [
114
+ "slow: marks tests as slow (deselect with '-m \"not slow\"')",
115
+ "integration: marks tests as integration tests",
116
+ "unit: marks tests as unit tests",
117
+ ]
118
+
119
+ [tool.coverage.run]
120
+ source = ["firefeed_core"]
121
+ omit = [
122
+ "*/tests/*",
123
+ "*/test_*",
124
+ "*/conftest.py",
125
+ ]
126
+
127
+ [tool.coverage.report]
128
+ exclude_lines = [
129
+ "pragma: no cover",
130
+ "def __repr__",
131
+ "if self.debug:",
132
+ "if settings.DEBUG",
133
+ "raise AssertionError",
134
+ "raise NotImplementedError",
135
+ "if 0:",
136
+ "if __name__ == .__main__.:",
137
+ "class .*\\bProtocol\\):",
138
+ "@(abc\\.)?abstractmethod",
139
+ ]
@@ -0,0 +1,4 @@
1
+ [egg_info]
2
+ tag_build =
3
+ tag_date = 0
4
+