social-plugin 0.1.1__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.
- social_plugin-0.1.1/.env.example +32 -0
- social_plugin-0.1.1/LICENSE +21 -0
- social_plugin-0.1.1/MANIFEST.in +5 -0
- social_plugin-0.1.1/PKG-INFO +213 -0
- social_plugin-0.1.1/README.md +160 -0
- social_plugin-0.1.1/config/config.example.yaml +121 -0
- social_plugin-0.1.1/pyproject.toml +72 -0
- social_plugin-0.1.1/setup.cfg +4 -0
- social_plugin-0.1.1/social_plugin/__init__.py +8 -0
- social_plugin-0.1.1/social_plugin/analytics/__init__.py +0 -0
- social_plugin-0.1.1/social_plugin/analytics/tracker.py +129 -0
- social_plugin-0.1.1/social_plugin/auth/__init__.py +0 -0
- social_plugin-0.1.1/social_plugin/auth/google_auth.py +51 -0
- social_plugin-0.1.1/social_plugin/auth/linkedin_auth.py +29 -0
- social_plugin-0.1.1/social_plugin/auth/twitter_auth.py +59 -0
- social_plugin-0.1.1/social_plugin/cli.py +988 -0
- social_plugin-0.1.1/social_plugin/config.py +222 -0
- social_plugin-0.1.1/social_plugin/db.py +297 -0
- social_plugin-0.1.1/social_plugin/drafts/__init__.py +0 -0
- social_plugin-0.1.1/social_plugin/drafts/draft_manager.py +119 -0
- social_plugin-0.1.1/social_plugin/drafts/models.py +104 -0
- social_plugin-0.1.1/social_plugin/generator/__init__.py +0 -0
- social_plugin-0.1.1/social_plugin/generator/claude_client.py +78 -0
- social_plugin-0.1.1/social_plugin/generator/content_generator.py +221 -0
- social_plugin-0.1.1/social_plugin/generator/llm_client.py +322 -0
- social_plugin-0.1.1/social_plugin/generator/prompts.py +123 -0
- social_plugin-0.1.1/social_plugin/generator/safety.py +91 -0
- social_plugin-0.1.1/social_plugin/init_wizard.py +235 -0
- social_plugin-0.1.1/social_plugin/notifications/__init__.py +0 -0
- social_plugin-0.1.1/social_plugin/notifications/slack_notifier.py +73 -0
- social_plugin-0.1.1/social_plugin/publisher/__init__.py +0 -0
- social_plugin-0.1.1/social_plugin/publisher/linkedin_publisher.py +101 -0
- social_plugin-0.1.1/social_plugin/publisher/media_uploader.py +64 -0
- social_plugin-0.1.1/social_plugin/publisher/twitter_publisher.py +125 -0
- social_plugin-0.1.1/social_plugin/sources/__init__.py +0 -0
- social_plugin-0.1.1/social_plugin/sources/gdocs_reader.py +102 -0
- social_plugin-0.1.1/social_plugin/sources/local_reader.py +132 -0
- social_plugin-0.1.1/social_plugin/sources/models.py +45 -0
- social_plugin-0.1.1/social_plugin/sources/pdf_reader.py +95 -0
- social_plugin-0.1.1/social_plugin/templates/__init__.py +0 -0
- social_plugin-0.1.1/social_plugin/templates/config.template.yaml +68 -0
- social_plugin-0.1.1/social_plugin/trends/__init__.py +0 -0
- social_plugin-0.1.1/social_plugin/trends/linkedin_trends.py +96 -0
- social_plugin-0.1.1/social_plugin/trends/models.py +45 -0
- social_plugin-0.1.1/social_plugin/trends/twitter_trends.py +100 -0
- social_plugin-0.1.1/social_plugin/utils/__init__.py +0 -0
- social_plugin-0.1.1/social_plugin/utils/logger.py +48 -0
- social_plugin-0.1.1/social_plugin/utils/retry.py +28 -0
- social_plugin-0.1.1/social_plugin.egg-info/PKG-INFO +213 -0
- social_plugin-0.1.1/social_plugin.egg-info/SOURCES.txt +57 -0
- social_plugin-0.1.1/social_plugin.egg-info/dependency_links.txt +1 -0
- social_plugin-0.1.1/social_plugin.egg-info/entry_points.txt +2 -0
- social_plugin-0.1.1/social_plugin.egg-info/requires.txt +28 -0
- social_plugin-0.1.1/social_plugin.egg-info/top_level.txt +1 -0
- social_plugin-0.1.1/tests/test_config.py +65 -0
- social_plugin-0.1.1/tests/test_db.py +100 -0
- social_plugin-0.1.1/tests/test_drafts.py +118 -0
- social_plugin-0.1.1/tests/test_prompts.py +53 -0
- social_plugin-0.1.1/tests/test_safety.py +51 -0
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
# =============================================================================
|
|
2
|
+
# LLM Provider (set ONE of these based on your chosen provider)
|
|
3
|
+
# =============================================================================
|
|
4
|
+
|
|
5
|
+
# Anthropic Claude (default)
|
|
6
|
+
ANTHROPIC_API_KEY=sk-ant-xxx
|
|
7
|
+
|
|
8
|
+
# OpenAI GPT (alternative)
|
|
9
|
+
OPENAI_API_KEY=sk-xxx
|
|
10
|
+
|
|
11
|
+
# Google Gemini (alternative)
|
|
12
|
+
GOOGLE_API_KEY=xxx
|
|
13
|
+
|
|
14
|
+
# =============================================================================
|
|
15
|
+
# Twitter/X API (Pay-Per-Use)
|
|
16
|
+
# =============================================================================
|
|
17
|
+
TWITTER_API_KEY=xxx
|
|
18
|
+
TWITTER_API_SECRET=xxx
|
|
19
|
+
TWITTER_ACCESS_TOKEN=xxx
|
|
20
|
+
TWITTER_ACCESS_TOKEN_SECRET=xxx
|
|
21
|
+
TWITTER_BEARER_TOKEN=xxx
|
|
22
|
+
|
|
23
|
+
# LinkedIn (future auto-post)
|
|
24
|
+
LINKEDIN_CLIENT_ID=xxx
|
|
25
|
+
LINKEDIN_CLIENT_SECRET=xxx
|
|
26
|
+
LINKEDIN_ACCESS_TOKEN=xxx
|
|
27
|
+
|
|
28
|
+
# Google Docs (service account JSON path — only needed for Google Docs sources)
|
|
29
|
+
GOOGLE_SERVICE_ACCOUNT_PATH=credentials/service-account.json
|
|
30
|
+
|
|
31
|
+
# Slack
|
|
32
|
+
SLACK_WEBHOOK_URL=https://hooks.slack.com/services/xxx/xxx/xxx
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2025 Nirmal Sharma
|
|
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,213 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: social-plugin
|
|
3
|
+
Version: 0.1.1
|
|
4
|
+
Summary: CLI tool for AI-powered social media content generation and publishing
|
|
5
|
+
Author: Nirmal Sharma
|
|
6
|
+
License-Expression: MIT
|
|
7
|
+
Project-URL: Homepage, https://github.com/nirmalsharma/social-plugin
|
|
8
|
+
Project-URL: Repository, https://github.com/nirmalsharma/social-plugin
|
|
9
|
+
Project-URL: Issues, https://github.com/nirmalsharma/social-plugin/issues
|
|
10
|
+
Keywords: social-media,ai,cli,content-generation,twitter,linkedin,claude,gpt,gemini
|
|
11
|
+
Classifier: Development Status :: 4 - Beta
|
|
12
|
+
Classifier: Environment :: Console
|
|
13
|
+
Classifier: Intended Audience :: Developers
|
|
14
|
+
Classifier: Intended Audience :: End Users/Desktop
|
|
15
|
+
Classifier: Operating System :: OS Independent
|
|
16
|
+
Classifier: Programming Language :: Python :: 3
|
|
17
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
18
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
19
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
20
|
+
Classifier: Topic :: Internet
|
|
21
|
+
Classifier: Topic :: Utilities
|
|
22
|
+
Requires-Python: >=3.11
|
|
23
|
+
Description-Content-Type: text/markdown
|
|
24
|
+
License-File: LICENSE
|
|
25
|
+
Requires-Dist: click>=8.1
|
|
26
|
+
Requires-Dist: rich>=13.0
|
|
27
|
+
Requires-Dist: pyyaml>=6.0
|
|
28
|
+
Requires-Dist: python-dotenv>=1.0
|
|
29
|
+
Requires-Dist: anthropic>=0.40
|
|
30
|
+
Requires-Dist: openai>=1.0
|
|
31
|
+
Requires-Dist: google-generativeai>=0.8
|
|
32
|
+
Requires-Dist: tweepy>=4.14
|
|
33
|
+
Requires-Dist: google-api-python-client>=2.100
|
|
34
|
+
Requires-Dist: google-auth>=2.23
|
|
35
|
+
Requires-Dist: google-auth-oauthlib>=1.1
|
|
36
|
+
Requires-Dist: feedparser>=6.0
|
|
37
|
+
Requires-Dist: beautifulsoup4>=4.12
|
|
38
|
+
Requires-Dist: httpx>=0.25
|
|
39
|
+
Requires-Dist: pdfplumber>=0.10
|
|
40
|
+
Requires-Dist: Pillow>=10.0
|
|
41
|
+
Requires-Dist: tenacity>=8.2
|
|
42
|
+
Requires-Dist: python-dateutil>=2.8
|
|
43
|
+
Requires-Dist: better-profanity>=0.7
|
|
44
|
+
Requires-Dist: slack-sdk>=3.23
|
|
45
|
+
Requires-Dist: python-docx>=1.0
|
|
46
|
+
Provides-Extra: dev
|
|
47
|
+
Requires-Dist: pytest>=7.4; extra == "dev"
|
|
48
|
+
Requires-Dist: pytest-asyncio>=0.21; extra == "dev"
|
|
49
|
+
Requires-Dist: pytest-mock>=3.11; extra == "dev"
|
|
50
|
+
Requires-Dist: build>=1.0; extra == "dev"
|
|
51
|
+
Requires-Dist: twine>=5.0; extra == "dev"
|
|
52
|
+
Dynamic: license-file
|
|
53
|
+
|
|
54
|
+
# Social Plugin
|
|
55
|
+
|
|
56
|
+
AI-powered CLI tool for social media content generation and publishing, focused on Physical AI & Robotics.
|
|
57
|
+
|
|
58
|
+
Discovers trending topics via RSS feeds, reads reference content from local files/Google Docs/PDFs, uses AI to generate tweet and LinkedIn post drafts, and posts approved content.
|
|
59
|
+
|
|
60
|
+
## Quick Start
|
|
61
|
+
|
|
62
|
+
**macOS / Linux:**
|
|
63
|
+
```bash
|
|
64
|
+
pipx install social-plugin
|
|
65
|
+
social-plugin init
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
**Windows (PowerShell):**
|
|
69
|
+
```powershell
|
|
70
|
+
pipx install social-plugin
|
|
71
|
+
social-plugin init
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
The `init` wizard walks you through choosing an AI provider, entering API keys, and configuring your topics.
|
|
75
|
+
|
|
76
|
+
## Prerequisites
|
|
77
|
+
|
|
78
|
+
You need an API key from at least one provider:
|
|
79
|
+
|
|
80
|
+
| Provider | Get API Key | Models |
|
|
81
|
+
|----------|-------------|--------|
|
|
82
|
+
| **Anthropic** | [console.anthropic.com](https://console.anthropic.com/) | `claude-sonnet-4-5-20250929`, `claude-opus-4-6` |
|
|
83
|
+
| **OpenAI** | [platform.openai.com](https://platform.openai.com/) | `gpt-4o`, `gpt-4o-mini`, `o1`, `o3-mini` |
|
|
84
|
+
| **Google** | [aistudio.google.com](https://aistudio.google.com/) | `gemini-2.0-flash`, `gemini-2.5-pro` |
|
|
85
|
+
|
|
86
|
+
For posting to Twitter/X, you also need API keys from [developer.x.com](https://developer.x.com/).
|
|
87
|
+
|
|
88
|
+
## Manual Install (from source)
|
|
89
|
+
|
|
90
|
+
```bash
|
|
91
|
+
git clone https://github.com/nirmalsharma/social-plugin.git
|
|
92
|
+
cd social-plugin
|
|
93
|
+
python -m venv .venv && source .venv/bin/activate
|
|
94
|
+
pip install -e ".[dev]"
|
|
95
|
+
cp config/config.example.yaml config/config.yaml
|
|
96
|
+
cp .env.example .env
|
|
97
|
+
# Edit .env with your API keys
|
|
98
|
+
social-plugin --help
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
## Configuration
|
|
102
|
+
|
|
103
|
+
After running `social-plugin init`, config is stored in:
|
|
104
|
+
|
|
105
|
+
- **macOS:** `~/Library/Application Support/social-plugin/config.yaml`
|
|
106
|
+
- **Linux:** `~/.config/social-plugin/config.yaml`
|
|
107
|
+
- **Windows:** `%APPDATA%\social-plugin\config.yaml`
|
|
108
|
+
|
|
109
|
+
If running from the repo directory, `./config/config.yaml` takes priority (development mode).
|
|
110
|
+
|
|
111
|
+
### Multi-Provider Config
|
|
112
|
+
|
|
113
|
+
```yaml
|
|
114
|
+
generation:
|
|
115
|
+
provider: "anthropic" # "anthropic", "openai", or "google"
|
|
116
|
+
model: "claude-sonnet-4-5-20250929" # or "gpt-4o", "gemini-2.0-flash"
|
|
117
|
+
max_tokens: 4096
|
|
118
|
+
temperature: 0.7
|
|
119
|
+
```
|
|
120
|
+
|
|
121
|
+
Provider is auto-detected from the model name if not set. Set the matching env var:
|
|
122
|
+
|
|
123
|
+
- `ANTHROPIC_API_KEY` for Claude models
|
|
124
|
+
- `OPENAI_API_KEY` for GPT/o1/o3 models
|
|
125
|
+
- `GOOGLE_API_KEY` for Gemini models
|
|
126
|
+
|
|
127
|
+
## Usage
|
|
128
|
+
|
|
129
|
+
### Typical Workflow
|
|
130
|
+
|
|
131
|
+
```bash
|
|
132
|
+
social-plugin fetch-trends # 1. Get latest trending topics
|
|
133
|
+
social-plugin fetch-sources # 2. Read local docs/PDFs
|
|
134
|
+
social-plugin generate # 3. Generate AI drafts
|
|
135
|
+
social-plugin drafts # 4. Review pending drafts
|
|
136
|
+
social-plugin approve <id> # 5. Approve a draft
|
|
137
|
+
social-plugin post --id <id> # 6. Post to Twitter/LinkedIn
|
|
138
|
+
```
|
|
139
|
+
|
|
140
|
+
Or run steps 1-3 in one command:
|
|
141
|
+
|
|
142
|
+
```bash
|
|
143
|
+
social-plugin run-all
|
|
144
|
+
```
|
|
145
|
+
|
|
146
|
+
### All Commands
|
|
147
|
+
|
|
148
|
+
| Command | Description |
|
|
149
|
+
|---------|-------------|
|
|
150
|
+
| `init` | Interactive setup wizard |
|
|
151
|
+
| `config --show` | Show config paths and active provider |
|
|
152
|
+
| `fetch-trends` | Fetch trending topics from RSS feeds |
|
|
153
|
+
| `fetch-sources` | Read configured Google Docs, PDFs, local files |
|
|
154
|
+
| `generate` | Generate 1 tweet + 1 LinkedIn draft |
|
|
155
|
+
| `generate --dry-run` | Preview without saving |
|
|
156
|
+
| `drafts` | List pending drafts |
|
|
157
|
+
| `drafts --status all` | List all drafts |
|
|
158
|
+
| `show <id>` | Full draft details |
|
|
159
|
+
| `review <id>` | Interactive review (approve/edit/regen/reject) |
|
|
160
|
+
| `approve <id>` | Approve for posting |
|
|
161
|
+
| `reject <id> -n "reason"` | Reject with notes |
|
|
162
|
+
| `edit <id>` | Open in $EDITOR |
|
|
163
|
+
| `regen <id> -t "casual"` | Regenerate with new tone |
|
|
164
|
+
| `post --id <id>` | Post specific draft |
|
|
165
|
+
| `post --all-approved` | Post all approved drafts |
|
|
166
|
+
| `run-all` | Full pipeline: trends + sources + generate |
|
|
167
|
+
| `stats` | Analytics dashboard |
|
|
168
|
+
| `history --days 30` | Content history |
|
|
169
|
+
| `expire` | Expire old pending drafts |
|
|
170
|
+
| `auth-check` | Verify API credentials |
|
|
171
|
+
|
|
172
|
+
### Draft Lifecycle
|
|
173
|
+
|
|
174
|
+
```
|
|
175
|
+
PENDING → approve → APPROVED → post → POSTED
|
|
176
|
+
↓ ↑ ↓
|
|
177
|
+
reject regen(tone) FAILED
|
|
178
|
+
↓
|
|
179
|
+
REJECTED
|
|
180
|
+
↓
|
|
181
|
+
expire (7 days) → EXPIRED
|
|
182
|
+
```
|
|
183
|
+
|
|
184
|
+
## Development
|
|
185
|
+
|
|
186
|
+
```bash
|
|
187
|
+
python -m venv .venv && source .venv/bin/activate
|
|
188
|
+
pip install -e ".[dev]"
|
|
189
|
+
python -m pytest tests/ -v
|
|
190
|
+
```
|
|
191
|
+
|
|
192
|
+
### Install from TestPyPI
|
|
193
|
+
|
|
194
|
+
To test a pre-release build before it goes to PyPI:
|
|
195
|
+
|
|
196
|
+
```bash
|
|
197
|
+
pipx install --index-url https://test.pypi.org/simple/ --extra-index-url https://pypi.org/simple/ social-plugin
|
|
198
|
+
```
|
|
199
|
+
|
|
200
|
+
### Publishing
|
|
201
|
+
|
|
202
|
+
CI publishes automatically on tag push via GitHub Actions:
|
|
203
|
+
|
|
204
|
+
```bash
|
|
205
|
+
git tag v0.1.0
|
|
206
|
+
git push --tags
|
|
207
|
+
```
|
|
208
|
+
|
|
209
|
+
This triggers: **build** → **TestPyPI** → **PyPI** (sequential, OIDC trusted publishing).
|
|
210
|
+
|
|
211
|
+
## License
|
|
212
|
+
|
|
213
|
+
MIT
|
|
@@ -0,0 +1,160 @@
|
|
|
1
|
+
# Social Plugin
|
|
2
|
+
|
|
3
|
+
AI-powered CLI tool for social media content generation and publishing, focused on Physical AI & Robotics.
|
|
4
|
+
|
|
5
|
+
Discovers trending topics via RSS feeds, reads reference content from local files/Google Docs/PDFs, uses AI to generate tweet and LinkedIn post drafts, and posts approved content.
|
|
6
|
+
|
|
7
|
+
## Quick Start
|
|
8
|
+
|
|
9
|
+
**macOS / Linux:**
|
|
10
|
+
```bash
|
|
11
|
+
pipx install social-plugin
|
|
12
|
+
social-plugin init
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
**Windows (PowerShell):**
|
|
16
|
+
```powershell
|
|
17
|
+
pipx install social-plugin
|
|
18
|
+
social-plugin init
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
The `init` wizard walks you through choosing an AI provider, entering API keys, and configuring your topics.
|
|
22
|
+
|
|
23
|
+
## Prerequisites
|
|
24
|
+
|
|
25
|
+
You need an API key from at least one provider:
|
|
26
|
+
|
|
27
|
+
| Provider | Get API Key | Models |
|
|
28
|
+
|----------|-------------|--------|
|
|
29
|
+
| **Anthropic** | [console.anthropic.com](https://console.anthropic.com/) | `claude-sonnet-4-5-20250929`, `claude-opus-4-6` |
|
|
30
|
+
| **OpenAI** | [platform.openai.com](https://platform.openai.com/) | `gpt-4o`, `gpt-4o-mini`, `o1`, `o3-mini` |
|
|
31
|
+
| **Google** | [aistudio.google.com](https://aistudio.google.com/) | `gemini-2.0-flash`, `gemini-2.5-pro` |
|
|
32
|
+
|
|
33
|
+
For posting to Twitter/X, you also need API keys from [developer.x.com](https://developer.x.com/).
|
|
34
|
+
|
|
35
|
+
## Manual Install (from source)
|
|
36
|
+
|
|
37
|
+
```bash
|
|
38
|
+
git clone https://github.com/nirmalsharma/social-plugin.git
|
|
39
|
+
cd social-plugin
|
|
40
|
+
python -m venv .venv && source .venv/bin/activate
|
|
41
|
+
pip install -e ".[dev]"
|
|
42
|
+
cp config/config.example.yaml config/config.yaml
|
|
43
|
+
cp .env.example .env
|
|
44
|
+
# Edit .env with your API keys
|
|
45
|
+
social-plugin --help
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
## Configuration
|
|
49
|
+
|
|
50
|
+
After running `social-plugin init`, config is stored in:
|
|
51
|
+
|
|
52
|
+
- **macOS:** `~/Library/Application Support/social-plugin/config.yaml`
|
|
53
|
+
- **Linux:** `~/.config/social-plugin/config.yaml`
|
|
54
|
+
- **Windows:** `%APPDATA%\social-plugin\config.yaml`
|
|
55
|
+
|
|
56
|
+
If running from the repo directory, `./config/config.yaml` takes priority (development mode).
|
|
57
|
+
|
|
58
|
+
### Multi-Provider Config
|
|
59
|
+
|
|
60
|
+
```yaml
|
|
61
|
+
generation:
|
|
62
|
+
provider: "anthropic" # "anthropic", "openai", or "google"
|
|
63
|
+
model: "claude-sonnet-4-5-20250929" # or "gpt-4o", "gemini-2.0-flash"
|
|
64
|
+
max_tokens: 4096
|
|
65
|
+
temperature: 0.7
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
Provider is auto-detected from the model name if not set. Set the matching env var:
|
|
69
|
+
|
|
70
|
+
- `ANTHROPIC_API_KEY` for Claude models
|
|
71
|
+
- `OPENAI_API_KEY` for GPT/o1/o3 models
|
|
72
|
+
- `GOOGLE_API_KEY` for Gemini models
|
|
73
|
+
|
|
74
|
+
## Usage
|
|
75
|
+
|
|
76
|
+
### Typical Workflow
|
|
77
|
+
|
|
78
|
+
```bash
|
|
79
|
+
social-plugin fetch-trends # 1. Get latest trending topics
|
|
80
|
+
social-plugin fetch-sources # 2. Read local docs/PDFs
|
|
81
|
+
social-plugin generate # 3. Generate AI drafts
|
|
82
|
+
social-plugin drafts # 4. Review pending drafts
|
|
83
|
+
social-plugin approve <id> # 5. Approve a draft
|
|
84
|
+
social-plugin post --id <id> # 6. Post to Twitter/LinkedIn
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
Or run steps 1-3 in one command:
|
|
88
|
+
|
|
89
|
+
```bash
|
|
90
|
+
social-plugin run-all
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
### All Commands
|
|
94
|
+
|
|
95
|
+
| Command | Description |
|
|
96
|
+
|---------|-------------|
|
|
97
|
+
| `init` | Interactive setup wizard |
|
|
98
|
+
| `config --show` | Show config paths and active provider |
|
|
99
|
+
| `fetch-trends` | Fetch trending topics from RSS feeds |
|
|
100
|
+
| `fetch-sources` | Read configured Google Docs, PDFs, local files |
|
|
101
|
+
| `generate` | Generate 1 tweet + 1 LinkedIn draft |
|
|
102
|
+
| `generate --dry-run` | Preview without saving |
|
|
103
|
+
| `drafts` | List pending drafts |
|
|
104
|
+
| `drafts --status all` | List all drafts |
|
|
105
|
+
| `show <id>` | Full draft details |
|
|
106
|
+
| `review <id>` | Interactive review (approve/edit/regen/reject) |
|
|
107
|
+
| `approve <id>` | Approve for posting |
|
|
108
|
+
| `reject <id> -n "reason"` | Reject with notes |
|
|
109
|
+
| `edit <id>` | Open in $EDITOR |
|
|
110
|
+
| `regen <id> -t "casual"` | Regenerate with new tone |
|
|
111
|
+
| `post --id <id>` | Post specific draft |
|
|
112
|
+
| `post --all-approved` | Post all approved drafts |
|
|
113
|
+
| `run-all` | Full pipeline: trends + sources + generate |
|
|
114
|
+
| `stats` | Analytics dashboard |
|
|
115
|
+
| `history --days 30` | Content history |
|
|
116
|
+
| `expire` | Expire old pending drafts |
|
|
117
|
+
| `auth-check` | Verify API credentials |
|
|
118
|
+
|
|
119
|
+
### Draft Lifecycle
|
|
120
|
+
|
|
121
|
+
```
|
|
122
|
+
PENDING → approve → APPROVED → post → POSTED
|
|
123
|
+
↓ ↑ ↓
|
|
124
|
+
reject regen(tone) FAILED
|
|
125
|
+
↓
|
|
126
|
+
REJECTED
|
|
127
|
+
↓
|
|
128
|
+
expire (7 days) → EXPIRED
|
|
129
|
+
```
|
|
130
|
+
|
|
131
|
+
## Development
|
|
132
|
+
|
|
133
|
+
```bash
|
|
134
|
+
python -m venv .venv && source .venv/bin/activate
|
|
135
|
+
pip install -e ".[dev]"
|
|
136
|
+
python -m pytest tests/ -v
|
|
137
|
+
```
|
|
138
|
+
|
|
139
|
+
### Install from TestPyPI
|
|
140
|
+
|
|
141
|
+
To test a pre-release build before it goes to PyPI:
|
|
142
|
+
|
|
143
|
+
```bash
|
|
144
|
+
pipx install --index-url https://test.pypi.org/simple/ --extra-index-url https://pypi.org/simple/ social-plugin
|
|
145
|
+
```
|
|
146
|
+
|
|
147
|
+
### Publishing
|
|
148
|
+
|
|
149
|
+
CI publishes automatically on tag push via GitHub Actions:
|
|
150
|
+
|
|
151
|
+
```bash
|
|
152
|
+
git tag v0.1.0
|
|
153
|
+
git push --tags
|
|
154
|
+
```
|
|
155
|
+
|
|
156
|
+
This triggers: **build** → **TestPyPI** → **PyPI** (sequential, OIDC trusted publishing).
|
|
157
|
+
|
|
158
|
+
## License
|
|
159
|
+
|
|
160
|
+
MIT
|
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
# =============================================================================
|
|
2
|
+
# Social Plugin — Example Configuration
|
|
3
|
+
# =============================================================================
|
|
4
|
+
# Copy this file to config/config.yaml and customize.
|
|
5
|
+
# Secrets go in .env (see .env.example).
|
|
6
|
+
|
|
7
|
+
# --- Topics ---
|
|
8
|
+
# Define what you post about. Keywords are used for trend relevance scoring.
|
|
9
|
+
topics:
|
|
10
|
+
primary: "Physical AI and Robotics"
|
|
11
|
+
keywords:
|
|
12
|
+
- "physical AI"
|
|
13
|
+
- "robotics"
|
|
14
|
+
- "embodied AI"
|
|
15
|
+
- "humanoid robots"
|
|
16
|
+
- "sim-to-real"
|
|
17
|
+
hashtags:
|
|
18
|
+
twitter: ["#PhysicalAI", "#Robotics", "#EmbodiedAI"]
|
|
19
|
+
linkedin: ["#PhysicalAI", "#Robotics", "#AI"]
|
|
20
|
+
|
|
21
|
+
# --- Accounts ---
|
|
22
|
+
# Which platforms to generate content for and posting limits.
|
|
23
|
+
accounts:
|
|
24
|
+
twitter:
|
|
25
|
+
enabled: true
|
|
26
|
+
api_tier: "pay-per-use" # X API is pay-per-use as of 2025
|
|
27
|
+
max_posts_per_day: 1
|
|
28
|
+
linkedin:
|
|
29
|
+
enabled: true
|
|
30
|
+
auto_post: false # Set to true when LinkedIn Developer app is ready
|
|
31
|
+
max_posts_per_day: 1
|
|
32
|
+
|
|
33
|
+
# --- Content Sources ---
|
|
34
|
+
# Direct links to reference material. NOT folder-based — each source is explicit.
|
|
35
|
+
sources:
|
|
36
|
+
# Google Docs — share each doc with your service account email
|
|
37
|
+
google_docs:
|
|
38
|
+
- id: "1aBcDeFgHiJkLmNoPqRsTuVwXyZ"
|
|
39
|
+
name: "Weekly AI Briefing"
|
|
40
|
+
- url: "https://docs.google.com/document/d/xxx/edit"
|
|
41
|
+
name: "Research Notes"
|
|
42
|
+
|
|
43
|
+
# Remote PDFs only (URLs) — local PDFs go in local_files
|
|
44
|
+
pdfs:
|
|
45
|
+
- url: "https://arxiv.org/pdf/xxxx.pdf"
|
|
46
|
+
name: "ArXiv Paper"
|
|
47
|
+
|
|
48
|
+
# Local files — supports txt, md, csv, pdf, doc, docx
|
|
49
|
+
local_files:
|
|
50
|
+
- path: "/Users/you/notes/ai-thoughts.md"
|
|
51
|
+
- path: "/Users/you/Documents/robotics-paper.pdf"
|
|
52
|
+
name: "Robotics Paper"
|
|
53
|
+
- path: "/Users/you/Documents/research-brief.docx"
|
|
54
|
+
name: "Research Brief"
|
|
55
|
+
|
|
56
|
+
# Media attachments for posts
|
|
57
|
+
media:
|
|
58
|
+
- path: "/Users/you/media/robot-demo.png"
|
|
59
|
+
description: "Robot manipulation demo"
|
|
60
|
+
- drive_url: "https://drive.google.com/file/d/xxx"
|
|
61
|
+
description: "Lab photo"
|
|
62
|
+
|
|
63
|
+
cache_ttl_hours: 24 # How long cached sources are considered fresh
|
|
64
|
+
|
|
65
|
+
# --- Content Generation ---
|
|
66
|
+
# LLM settings for draft generation. Supports Anthropic Claude, OpenAI GPT, and Google Gemini.
|
|
67
|
+
# Provider is auto-detected from model name if not set.
|
|
68
|
+
generation:
|
|
69
|
+
provider: "anthropic" # "anthropic", "openai", or "google" (auto-detected if omitted)
|
|
70
|
+
model: "claude-sonnet-4-5-20250929" # Anthropic: claude-sonnet-4-5-20250929, claude-opus-4-6
|
|
71
|
+
# OpenAI: gpt-4o, gpt-4o-mini, o1, o3-mini
|
|
72
|
+
# Google: gemini-2.0-flash, gemini-2.5-pro
|
|
73
|
+
max_tokens: 4096
|
|
74
|
+
temperature: 0.7 # Higher = more creative, lower = more focused
|
|
75
|
+
default_tone: "informative, thought-provoking, professional"
|
|
76
|
+
|
|
77
|
+
tweet:
|
|
78
|
+
max_length: 280
|
|
79
|
+
count_per_run: 1
|
|
80
|
+
style: "concise insight with relevant hashtag"
|
|
81
|
+
|
|
82
|
+
linkedin_post:
|
|
83
|
+
max_length: 3000
|
|
84
|
+
count_per_run: 1
|
|
85
|
+
style: "thought-leadership, conversational, uses line breaks, ends with a question"
|
|
86
|
+
|
|
87
|
+
# --- Content Safety ---
|
|
88
|
+
# Filters applied to all generated content before saving as drafts.
|
|
89
|
+
safety:
|
|
90
|
+
profanity_filter: true # Uses better-profanity library
|
|
91
|
+
blocked_words: [] # Add custom words to block
|
|
92
|
+
compliance_note: "No financial advice, no medical claims"
|
|
93
|
+
|
|
94
|
+
# --- Notifications ---
|
|
95
|
+
notifications:
|
|
96
|
+
slack:
|
|
97
|
+
enabled: true
|
|
98
|
+
webhook_url_env: "SLACK_WEBHOOK_URL" # Env var name containing the webhook URL
|
|
99
|
+
channel: "#social-content"
|
|
100
|
+
cli: true # Always show CLI output
|
|
101
|
+
|
|
102
|
+
# --- Trend Discovery ---
|
|
103
|
+
# RSS feeds for discovering trending topics. Google News RSS is free.
|
|
104
|
+
trends:
|
|
105
|
+
rss_feeds:
|
|
106
|
+
- "https://news.google.com/rss/search?q=physical+AI+robotics"
|
|
107
|
+
- "https://news.google.com/rss/search?q=physical+AI+robotics+site:twitter.com"
|
|
108
|
+
- "https://news.google.com/rss/search?q=physical+AI+robotics+site:linkedin.com"
|
|
109
|
+
- "https://feeds.feedburner.com/IeeeSpectrum"
|
|
110
|
+
max_results: 20
|
|
111
|
+
|
|
112
|
+
# --- Database ---
|
|
113
|
+
database:
|
|
114
|
+
path: "data/social_plugin.db" # SQLite file (entire state manager)
|
|
115
|
+
|
|
116
|
+
# --- Logging ---
|
|
117
|
+
logging:
|
|
118
|
+
level: "INFO" # DEBUG, INFO, WARNING, ERROR
|
|
119
|
+
file: "data/logs/social_plugin.log"
|
|
120
|
+
max_size_mb: 10
|
|
121
|
+
backup_count: 5
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
[build-system]
|
|
2
|
+
requires = ["setuptools>=68.0", "wheel"]
|
|
3
|
+
build-backend = "setuptools.build_meta"
|
|
4
|
+
|
|
5
|
+
[project]
|
|
6
|
+
name = "social-plugin"
|
|
7
|
+
version = "0.1.1"
|
|
8
|
+
description = "CLI tool for AI-powered social media content generation and publishing"
|
|
9
|
+
readme = "README.md"
|
|
10
|
+
license = "MIT"
|
|
11
|
+
requires-python = ">=3.11"
|
|
12
|
+
authors = [{name = "Nirmal Sharma"}]
|
|
13
|
+
keywords = ["social-media", "ai", "cli", "content-generation", "twitter", "linkedin", "claude", "gpt", "gemini"]
|
|
14
|
+
classifiers = [
|
|
15
|
+
"Development Status :: 4 - Beta",
|
|
16
|
+
"Environment :: Console",
|
|
17
|
+
"Intended Audience :: Developers",
|
|
18
|
+
"Intended Audience :: End Users/Desktop",
|
|
19
|
+
"Operating System :: OS Independent",
|
|
20
|
+
"Programming Language :: Python :: 3",
|
|
21
|
+
"Programming Language :: Python :: 3.11",
|
|
22
|
+
"Programming Language :: Python :: 3.12",
|
|
23
|
+
"Programming Language :: Python :: 3.13",
|
|
24
|
+
"Topic :: Internet",
|
|
25
|
+
"Topic :: Utilities",
|
|
26
|
+
]
|
|
27
|
+
dependencies = [
|
|
28
|
+
"click>=8.1",
|
|
29
|
+
"rich>=13.0",
|
|
30
|
+
"pyyaml>=6.0",
|
|
31
|
+
"python-dotenv>=1.0",
|
|
32
|
+
"anthropic>=0.40",
|
|
33
|
+
"openai>=1.0",
|
|
34
|
+
"google-generativeai>=0.8",
|
|
35
|
+
"tweepy>=4.14",
|
|
36
|
+
"google-api-python-client>=2.100",
|
|
37
|
+
"google-auth>=2.23",
|
|
38
|
+
"google-auth-oauthlib>=1.1",
|
|
39
|
+
"feedparser>=6.0",
|
|
40
|
+
"beautifulsoup4>=4.12",
|
|
41
|
+
"httpx>=0.25",
|
|
42
|
+
"pdfplumber>=0.10",
|
|
43
|
+
"Pillow>=10.0",
|
|
44
|
+
"tenacity>=8.2",
|
|
45
|
+
"python-dateutil>=2.8",
|
|
46
|
+
"better-profanity>=0.7",
|
|
47
|
+
"slack-sdk>=3.23",
|
|
48
|
+
"python-docx>=1.0",
|
|
49
|
+
]
|
|
50
|
+
|
|
51
|
+
[project.optional-dependencies]
|
|
52
|
+
dev = [
|
|
53
|
+
"pytest>=7.4",
|
|
54
|
+
"pytest-asyncio>=0.21",
|
|
55
|
+
"pytest-mock>=3.11",
|
|
56
|
+
"build>=1.0",
|
|
57
|
+
"twine>=5.0",
|
|
58
|
+
]
|
|
59
|
+
|
|
60
|
+
[project.urls]
|
|
61
|
+
Homepage = "https://github.com/nirmalsharma/social-plugin"
|
|
62
|
+
Repository = "https://github.com/nirmalsharma/social-plugin"
|
|
63
|
+
Issues = "https://github.com/nirmalsharma/social-plugin/issues"
|
|
64
|
+
|
|
65
|
+
[project.scripts]
|
|
66
|
+
social-plugin = "social_plugin.cli:cli"
|
|
67
|
+
|
|
68
|
+
[tool.setuptools.packages.find]
|
|
69
|
+
include = ["social_plugin*"]
|
|
70
|
+
|
|
71
|
+
[tool.setuptools.package-data]
|
|
72
|
+
"social_plugin.templates" = ["*.yaml"]
|
|
File without changes
|