gh-social 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.
- gh_social-1.0.0/LICENSE +21 -0
- gh_social-1.0.0/PKG-INFO +219 -0
- gh_social-1.0.0/README.md +189 -0
- gh_social-1.0.0/gh_social.egg-info/PKG-INFO +219 -0
- gh_social-1.0.0/gh_social.egg-info/SOURCES.txt +21 -0
- gh_social-1.0.0/gh_social.egg-info/dependency_links.txt +1 -0
- gh_social-1.0.0/gh_social.egg-info/entry_points.txt +2 -0
- gh_social-1.0.0/gh_social.egg-info/requires.txt +8 -0
- gh_social-1.0.0/gh_social.egg-info/top_level.txt +1 -0
- gh_social-1.0.0/github_toolkit/__init__.py +3 -0
- gh_social-1.0.0/github_toolkit/__main__.py +6 -0
- gh_social-1.0.0/github_toolkit/api.py +137 -0
- gh_social-1.0.0/github_toolkit/cli.py +199 -0
- gh_social-1.0.0/github_toolkit/formatting.py +173 -0
- gh_social-1.0.0/github_toolkit/models.py +97 -0
- gh_social-1.0.0/github_toolkit/py.typed +0 -0
- gh_social-1.0.0/github_toolkit/tools/__init__.py +1 -0
- gh_social-1.0.0/github_toolkit/tools/social.py +338 -0
- gh_social-1.0.0/pyproject.toml +105 -0
- gh_social-1.0.0/setup.cfg +4 -0
- gh_social-1.0.0/tests/test_formatting.py +35 -0
- gh_social-1.0.0/tests/test_models.py +118 -0
- gh_social-1.0.0/tests/test_social.py +58 -0
gh_social-1.0.0/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Ajang Supardi
|
|
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.
|
gh_social-1.0.0/PKG-INFO
ADDED
|
@@ -0,0 +1,219 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: gh-social
|
|
3
|
+
Version: 1.0.0
|
|
4
|
+
Summary: CLI tools for GitHub — follow back, unfollow, and more.
|
|
5
|
+
Author: Ajang Supardi
|
|
6
|
+
License-Expression: MIT
|
|
7
|
+
Project-URL: Homepage, https://github.com/ajangsupardi/github-toolkit
|
|
8
|
+
Project-URL: Repository, https://github.com/ajangsupardi/github-toolkit
|
|
9
|
+
Keywords: github,cli,follow,unfollow,toolkit
|
|
10
|
+
Classifier: Development Status :: 4 - Beta
|
|
11
|
+
Classifier: Environment :: Console
|
|
12
|
+
Classifier: Intended Audience :: Developers
|
|
13
|
+
Classifier: Operating System :: OS Independent
|
|
14
|
+
Classifier: Programming Language :: Python :: 3
|
|
15
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
16
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
17
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
18
|
+
Classifier: Topic :: Software Development :: Version Control :: Git
|
|
19
|
+
Requires-Python: >=3.10
|
|
20
|
+
Description-Content-Type: text/markdown
|
|
21
|
+
License-File: LICENSE
|
|
22
|
+
Requires-Dist: requests>=2.28.0
|
|
23
|
+
Requires-Dist: rich>=13.0
|
|
24
|
+
Provides-Extra: dev
|
|
25
|
+
Requires-Dist: pytest>=7.0; extra == "dev"
|
|
26
|
+
Requires-Dist: pytest-cov>=4.0; extra == "dev"
|
|
27
|
+
Requires-Dist: ruff>=0.4.0; extra == "dev"
|
|
28
|
+
Requires-Dist: pyright>=1.1.350; extra == "dev"
|
|
29
|
+
Dynamic: license-file
|
|
30
|
+
|
|
31
|
+
# GitHub Toolkit
|
|
32
|
+
|
|
33
|
+
CLI tools for GitHub — follow back, unfollow, and more.
|
|
34
|
+
|
|
35
|
+
A fast, modular toolkit for common GitHub operations. Currently includes **Follow Back** and **Unfollow** tools, with more coming soon.
|
|
36
|
+
|
|
37
|
+
## Tools
|
|
38
|
+
|
|
39
|
+
| Tool | Description |
|
|
40
|
+
|------|-------------|
|
|
41
|
+
| `follow` | Follow all followers of any GitHub user |
|
|
42
|
+
| `unfollow` | Unfollow users who don't follow you back |
|
|
43
|
+
|
|
44
|
+
### Features
|
|
45
|
+
|
|
46
|
+
- **Interactive Menu** — Run without arguments for a guided menu experience
|
|
47
|
+
- **Concurrent Execution** — Uses `ThreadPoolExecutor` with 16 workers for fast API operations
|
|
48
|
+
- **Smart Bot Detection** — Identifies spam/bot accounts using a 2-of-3 heuristic
|
|
49
|
+
- **Dry-Run Mode** — Preview targets before executing any actions
|
|
50
|
+
- **Rate Limit Aware** — Checks GitHub API rate limits before proceeding
|
|
51
|
+
- **JSON Output** — Machine-readable output for scripting and automation
|
|
52
|
+
|
|
53
|
+
## Requirements
|
|
54
|
+
|
|
55
|
+
- Python 3.10+
|
|
56
|
+
- [GitHub CLI](https://cli.github.com/) (`gh`) — must be installed and authenticated
|
|
57
|
+
- `rich` >= 13.0 — modern terminal output
|
|
58
|
+
|
|
59
|
+
### Authentication
|
|
60
|
+
|
|
61
|
+
The toolkit uses your `gh` CLI credentials:
|
|
62
|
+
|
|
63
|
+
```bash
|
|
64
|
+
gh auth login
|
|
65
|
+
gh auth refresh -h github.com -s user
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
## Installation
|
|
69
|
+
|
|
70
|
+
> **Note:** On Debian/Ubuntu 23.04+ the system Python is externally managed (PEP 668).
|
|
71
|
+
> Use a virtual environment or `pipx` to avoid installation errors.
|
|
72
|
+
|
|
73
|
+
### With pipx (Recommended)
|
|
74
|
+
|
|
75
|
+
```bash
|
|
76
|
+
pipx install git+https://github.com/ajangsupardi/github-toolkit.git
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
### From Source (Development)
|
|
80
|
+
|
|
81
|
+
```bash
|
|
82
|
+
git clone https://github.com/ajangsupardi/github-toolkit.git
|
|
83
|
+
cd github-toolkit
|
|
84
|
+
python3 -m venv .venv
|
|
85
|
+
source .venv/bin/activate
|
|
86
|
+
pip install -e .
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
### As Library (with venv)
|
|
90
|
+
|
|
91
|
+
```bash
|
|
92
|
+
python3 -m venv .venv
|
|
93
|
+
source .venv/bin/activate
|
|
94
|
+
pip install git+https://github.com/ajangsupardi/github-toolkit.git
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
## Usage
|
|
98
|
+
|
|
99
|
+
### Interactive Mode
|
|
100
|
+
|
|
101
|
+
Run without arguments to see the menu:
|
|
102
|
+
|
|
103
|
+
```bash
|
|
104
|
+
python3 -m github_toolkit
|
|
105
|
+
# or after pip install:
|
|
106
|
+
github-toolkit
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
```
|
|
110
|
+
╭──────────────────────────────────────────────╮
|
|
111
|
+
│ 🔍 GitHub Toolkit v1.0.0 │
|
|
112
|
+
╰──────────────────────────────────────────────╯
|
|
113
|
+
|
|
114
|
+
Choose a tool:
|
|
115
|
+
|
|
116
|
+
1. Follow Back — Follow all followers of a target user
|
|
117
|
+
2. Unfollow — Unfollow users who don't follow you back
|
|
118
|
+
|
|
119
|
+
0. Exit
|
|
120
|
+
|
|
121
|
+
→ Choice (0-2):
|
|
122
|
+
```
|
|
123
|
+
|
|
124
|
+
### CLI Mode
|
|
125
|
+
|
|
126
|
+
```bash
|
|
127
|
+
# Follow Back
|
|
128
|
+
python3 -m github_toolkit follow ajangsupardi # Dry-run
|
|
129
|
+
python3 -m github_toolkit follow ajangsupardi --execute # Execute
|
|
130
|
+
python3 -m github_toolkit follow ajangsupardi --limit 100 # Limit
|
|
131
|
+
|
|
132
|
+
# Unfollow
|
|
133
|
+
python3 -m github_toolkit unfollow # Dry-run
|
|
134
|
+
python3 -m github_toolkit unfollow --execute # Execute
|
|
135
|
+
python3 -m github_toolkit unfollow --limit 100 # Limit
|
|
136
|
+
|
|
137
|
+
# Common flags
|
|
138
|
+
python3 -m github_toolkit follow ajangsupardi --json # JSON output
|
|
139
|
+
python3 -m github_toolkit follow ajangsupardi --execute --include-bots
|
|
140
|
+
```
|
|
141
|
+
|
|
142
|
+
### As Library
|
|
143
|
+
|
|
144
|
+
```python
|
|
145
|
+
from github_toolkit.api import get_session, api_paginate, follow_user
|
|
146
|
+
from github_toolkit.models import enrich_users_concurrent
|
|
147
|
+
|
|
148
|
+
# Initialize session
|
|
149
|
+
get_session()
|
|
150
|
+
|
|
151
|
+
# Use API functions directly
|
|
152
|
+
followers = api_paginate("users/octocat/followers")
|
|
153
|
+
follow_user("octocat")
|
|
154
|
+
```
|
|
155
|
+
|
|
156
|
+
## Flags
|
|
157
|
+
|
|
158
|
+
| Flag | Description | Default |
|
|
159
|
+
|------|-------------|---------|
|
|
160
|
+
| `--execute` | Execute action (otherwise dry-run) | `false` |
|
|
161
|
+
| `--limit N` | Limit number of users processed | `0` (all) |
|
|
162
|
+
| `--include-bots` | Include bot accounts | `false` |
|
|
163
|
+
| `--json` | Output in JSON format | `false` |
|
|
164
|
+
|
|
165
|
+
## Project Structure
|
|
166
|
+
|
|
167
|
+
```
|
|
168
|
+
github-toolkit/
|
|
169
|
+
├── github_toolkit/ # Package
|
|
170
|
+
│ ├── __init__.py # Version
|
|
171
|
+
│ ├── __main__.py # Entry point
|
|
172
|
+
│ ├── cli.py # CLI dispatcher + interactive menu
|
|
173
|
+
│ ├── api.py # GitHub API (auth, pagination)
|
|
174
|
+
│ ├── models.py # Data models & bot detection
|
|
175
|
+
│ ├── formatting.py # Output formatting
|
|
176
|
+
│ └── tools/
|
|
177
|
+
│ └── social.py # Follow back & unfollow logic
|
|
178
|
+
├── pyproject.toml # Pip installable config
|
|
179
|
+
├── README.md
|
|
180
|
+
└── LICENSE
|
|
181
|
+
```
|
|
182
|
+
|
|
183
|
+
## How It Works
|
|
184
|
+
|
|
185
|
+
### Follow Back
|
|
186
|
+
|
|
187
|
+
```
|
|
188
|
+
1. Authenticate via gh CLI token
|
|
189
|
+
2. Fetch target user's followers (paginated, concurrent)
|
|
190
|
+
3. Fetch your following list to identify already-followed users
|
|
191
|
+
4. Filter out: yourself, already-followed, and optionally bots
|
|
192
|
+
5. Enrich user details concurrently (name, bio, repos)
|
|
193
|
+
6. Display table preview (dry-run) or execute follows concurrently
|
|
194
|
+
```
|
|
195
|
+
|
|
196
|
+
### Unfollow
|
|
197
|
+
|
|
198
|
+
```
|
|
199
|
+
1. Authenticate via gh CLI token
|
|
200
|
+
2. Fetch your followers & following lists (concurrent)
|
|
201
|
+
3. Find: users you follow who DON'T follow you back
|
|
202
|
+
4. Filter out: optionally bots
|
|
203
|
+
5. Enrich user details concurrently (name, bio, repos)
|
|
204
|
+
6. Display table preview (dry-run) or execute unfollows concurrently
|
|
205
|
+
```
|
|
206
|
+
|
|
207
|
+
## Bot Detection
|
|
208
|
+
|
|
209
|
+
Accounts are flagged as potential bots when **2 out of 3** conditions are met:
|
|
210
|
+
|
|
211
|
+
| Condition | Description |
|
|
212
|
+
|-----------|-------------|
|
|
213
|
+
| Default avatar | Uses GitHub's default identicon |
|
|
214
|
+
| Empty bio | No bio or whitespace only |
|
|
215
|
+
| Zero repos | No public repositories |
|
|
216
|
+
|
|
217
|
+
## License
|
|
218
|
+
|
|
219
|
+
MIT License — see [LICENSE](LICENSE) for details.
|
|
@@ -0,0 +1,189 @@
|
|
|
1
|
+
# GitHub Toolkit
|
|
2
|
+
|
|
3
|
+
CLI tools for GitHub — follow back, unfollow, and more.
|
|
4
|
+
|
|
5
|
+
A fast, modular toolkit for common GitHub operations. Currently includes **Follow Back** and **Unfollow** tools, with more coming soon.
|
|
6
|
+
|
|
7
|
+
## Tools
|
|
8
|
+
|
|
9
|
+
| Tool | Description |
|
|
10
|
+
|------|-------------|
|
|
11
|
+
| `follow` | Follow all followers of any GitHub user |
|
|
12
|
+
| `unfollow` | Unfollow users who don't follow you back |
|
|
13
|
+
|
|
14
|
+
### Features
|
|
15
|
+
|
|
16
|
+
- **Interactive Menu** — Run without arguments for a guided menu experience
|
|
17
|
+
- **Concurrent Execution** — Uses `ThreadPoolExecutor` with 16 workers for fast API operations
|
|
18
|
+
- **Smart Bot Detection** — Identifies spam/bot accounts using a 2-of-3 heuristic
|
|
19
|
+
- **Dry-Run Mode** — Preview targets before executing any actions
|
|
20
|
+
- **Rate Limit Aware** — Checks GitHub API rate limits before proceeding
|
|
21
|
+
- **JSON Output** — Machine-readable output for scripting and automation
|
|
22
|
+
|
|
23
|
+
## Requirements
|
|
24
|
+
|
|
25
|
+
- Python 3.10+
|
|
26
|
+
- [GitHub CLI](https://cli.github.com/) (`gh`) — must be installed and authenticated
|
|
27
|
+
- `rich` >= 13.0 — modern terminal output
|
|
28
|
+
|
|
29
|
+
### Authentication
|
|
30
|
+
|
|
31
|
+
The toolkit uses your `gh` CLI credentials:
|
|
32
|
+
|
|
33
|
+
```bash
|
|
34
|
+
gh auth login
|
|
35
|
+
gh auth refresh -h github.com -s user
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
## Installation
|
|
39
|
+
|
|
40
|
+
> **Note:** On Debian/Ubuntu 23.04+ the system Python is externally managed (PEP 668).
|
|
41
|
+
> Use a virtual environment or `pipx` to avoid installation errors.
|
|
42
|
+
|
|
43
|
+
### With pipx (Recommended)
|
|
44
|
+
|
|
45
|
+
```bash
|
|
46
|
+
pipx install git+https://github.com/ajangsupardi/github-toolkit.git
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
### From Source (Development)
|
|
50
|
+
|
|
51
|
+
```bash
|
|
52
|
+
git clone https://github.com/ajangsupardi/github-toolkit.git
|
|
53
|
+
cd github-toolkit
|
|
54
|
+
python3 -m venv .venv
|
|
55
|
+
source .venv/bin/activate
|
|
56
|
+
pip install -e .
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
### As Library (with venv)
|
|
60
|
+
|
|
61
|
+
```bash
|
|
62
|
+
python3 -m venv .venv
|
|
63
|
+
source .venv/bin/activate
|
|
64
|
+
pip install git+https://github.com/ajangsupardi/github-toolkit.git
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
## Usage
|
|
68
|
+
|
|
69
|
+
### Interactive Mode
|
|
70
|
+
|
|
71
|
+
Run without arguments to see the menu:
|
|
72
|
+
|
|
73
|
+
```bash
|
|
74
|
+
python3 -m github_toolkit
|
|
75
|
+
# or after pip install:
|
|
76
|
+
github-toolkit
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
```
|
|
80
|
+
╭──────────────────────────────────────────────╮
|
|
81
|
+
│ 🔍 GitHub Toolkit v1.0.0 │
|
|
82
|
+
╰──────────────────────────────────────────────╯
|
|
83
|
+
|
|
84
|
+
Choose a tool:
|
|
85
|
+
|
|
86
|
+
1. Follow Back — Follow all followers of a target user
|
|
87
|
+
2. Unfollow — Unfollow users who don't follow you back
|
|
88
|
+
|
|
89
|
+
0. Exit
|
|
90
|
+
|
|
91
|
+
→ Choice (0-2):
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
### CLI Mode
|
|
95
|
+
|
|
96
|
+
```bash
|
|
97
|
+
# Follow Back
|
|
98
|
+
python3 -m github_toolkit follow ajangsupardi # Dry-run
|
|
99
|
+
python3 -m github_toolkit follow ajangsupardi --execute # Execute
|
|
100
|
+
python3 -m github_toolkit follow ajangsupardi --limit 100 # Limit
|
|
101
|
+
|
|
102
|
+
# Unfollow
|
|
103
|
+
python3 -m github_toolkit unfollow # Dry-run
|
|
104
|
+
python3 -m github_toolkit unfollow --execute # Execute
|
|
105
|
+
python3 -m github_toolkit unfollow --limit 100 # Limit
|
|
106
|
+
|
|
107
|
+
# Common flags
|
|
108
|
+
python3 -m github_toolkit follow ajangsupardi --json # JSON output
|
|
109
|
+
python3 -m github_toolkit follow ajangsupardi --execute --include-bots
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
### As Library
|
|
113
|
+
|
|
114
|
+
```python
|
|
115
|
+
from github_toolkit.api import get_session, api_paginate, follow_user
|
|
116
|
+
from github_toolkit.models import enrich_users_concurrent
|
|
117
|
+
|
|
118
|
+
# Initialize session
|
|
119
|
+
get_session()
|
|
120
|
+
|
|
121
|
+
# Use API functions directly
|
|
122
|
+
followers = api_paginate("users/octocat/followers")
|
|
123
|
+
follow_user("octocat")
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
## Flags
|
|
127
|
+
|
|
128
|
+
| Flag | Description | Default |
|
|
129
|
+
|------|-------------|---------|
|
|
130
|
+
| `--execute` | Execute action (otherwise dry-run) | `false` |
|
|
131
|
+
| `--limit N` | Limit number of users processed | `0` (all) |
|
|
132
|
+
| `--include-bots` | Include bot accounts | `false` |
|
|
133
|
+
| `--json` | Output in JSON format | `false` |
|
|
134
|
+
|
|
135
|
+
## Project Structure
|
|
136
|
+
|
|
137
|
+
```
|
|
138
|
+
github-toolkit/
|
|
139
|
+
├── github_toolkit/ # Package
|
|
140
|
+
│ ├── __init__.py # Version
|
|
141
|
+
│ ├── __main__.py # Entry point
|
|
142
|
+
│ ├── cli.py # CLI dispatcher + interactive menu
|
|
143
|
+
│ ├── api.py # GitHub API (auth, pagination)
|
|
144
|
+
│ ├── models.py # Data models & bot detection
|
|
145
|
+
│ ├── formatting.py # Output formatting
|
|
146
|
+
│ └── tools/
|
|
147
|
+
│ └── social.py # Follow back & unfollow logic
|
|
148
|
+
├── pyproject.toml # Pip installable config
|
|
149
|
+
├── README.md
|
|
150
|
+
└── LICENSE
|
|
151
|
+
```
|
|
152
|
+
|
|
153
|
+
## How It Works
|
|
154
|
+
|
|
155
|
+
### Follow Back
|
|
156
|
+
|
|
157
|
+
```
|
|
158
|
+
1. Authenticate via gh CLI token
|
|
159
|
+
2. Fetch target user's followers (paginated, concurrent)
|
|
160
|
+
3. Fetch your following list to identify already-followed users
|
|
161
|
+
4. Filter out: yourself, already-followed, and optionally bots
|
|
162
|
+
5. Enrich user details concurrently (name, bio, repos)
|
|
163
|
+
6. Display table preview (dry-run) or execute follows concurrently
|
|
164
|
+
```
|
|
165
|
+
|
|
166
|
+
### Unfollow
|
|
167
|
+
|
|
168
|
+
```
|
|
169
|
+
1. Authenticate via gh CLI token
|
|
170
|
+
2. Fetch your followers & following lists (concurrent)
|
|
171
|
+
3. Find: users you follow who DON'T follow you back
|
|
172
|
+
4. Filter out: optionally bots
|
|
173
|
+
5. Enrich user details concurrently (name, bio, repos)
|
|
174
|
+
6. Display table preview (dry-run) or execute unfollows concurrently
|
|
175
|
+
```
|
|
176
|
+
|
|
177
|
+
## Bot Detection
|
|
178
|
+
|
|
179
|
+
Accounts are flagged as potential bots when **2 out of 3** conditions are met:
|
|
180
|
+
|
|
181
|
+
| Condition | Description |
|
|
182
|
+
|-----------|-------------|
|
|
183
|
+
| Default avatar | Uses GitHub's default identicon |
|
|
184
|
+
| Empty bio | No bio or whitespace only |
|
|
185
|
+
| Zero repos | No public repositories |
|
|
186
|
+
|
|
187
|
+
## License
|
|
188
|
+
|
|
189
|
+
MIT License — see [LICENSE](LICENSE) for details.
|
|
@@ -0,0 +1,219 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: gh-social
|
|
3
|
+
Version: 1.0.0
|
|
4
|
+
Summary: CLI tools for GitHub — follow back, unfollow, and more.
|
|
5
|
+
Author: Ajang Supardi
|
|
6
|
+
License-Expression: MIT
|
|
7
|
+
Project-URL: Homepage, https://github.com/ajangsupardi/github-toolkit
|
|
8
|
+
Project-URL: Repository, https://github.com/ajangsupardi/github-toolkit
|
|
9
|
+
Keywords: github,cli,follow,unfollow,toolkit
|
|
10
|
+
Classifier: Development Status :: 4 - Beta
|
|
11
|
+
Classifier: Environment :: Console
|
|
12
|
+
Classifier: Intended Audience :: Developers
|
|
13
|
+
Classifier: Operating System :: OS Independent
|
|
14
|
+
Classifier: Programming Language :: Python :: 3
|
|
15
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
16
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
17
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
18
|
+
Classifier: Topic :: Software Development :: Version Control :: Git
|
|
19
|
+
Requires-Python: >=3.10
|
|
20
|
+
Description-Content-Type: text/markdown
|
|
21
|
+
License-File: LICENSE
|
|
22
|
+
Requires-Dist: requests>=2.28.0
|
|
23
|
+
Requires-Dist: rich>=13.0
|
|
24
|
+
Provides-Extra: dev
|
|
25
|
+
Requires-Dist: pytest>=7.0; extra == "dev"
|
|
26
|
+
Requires-Dist: pytest-cov>=4.0; extra == "dev"
|
|
27
|
+
Requires-Dist: ruff>=0.4.0; extra == "dev"
|
|
28
|
+
Requires-Dist: pyright>=1.1.350; extra == "dev"
|
|
29
|
+
Dynamic: license-file
|
|
30
|
+
|
|
31
|
+
# GitHub Toolkit
|
|
32
|
+
|
|
33
|
+
CLI tools for GitHub — follow back, unfollow, and more.
|
|
34
|
+
|
|
35
|
+
A fast, modular toolkit for common GitHub operations. Currently includes **Follow Back** and **Unfollow** tools, with more coming soon.
|
|
36
|
+
|
|
37
|
+
## Tools
|
|
38
|
+
|
|
39
|
+
| Tool | Description |
|
|
40
|
+
|------|-------------|
|
|
41
|
+
| `follow` | Follow all followers of any GitHub user |
|
|
42
|
+
| `unfollow` | Unfollow users who don't follow you back |
|
|
43
|
+
|
|
44
|
+
### Features
|
|
45
|
+
|
|
46
|
+
- **Interactive Menu** — Run without arguments for a guided menu experience
|
|
47
|
+
- **Concurrent Execution** — Uses `ThreadPoolExecutor` with 16 workers for fast API operations
|
|
48
|
+
- **Smart Bot Detection** — Identifies spam/bot accounts using a 2-of-3 heuristic
|
|
49
|
+
- **Dry-Run Mode** — Preview targets before executing any actions
|
|
50
|
+
- **Rate Limit Aware** — Checks GitHub API rate limits before proceeding
|
|
51
|
+
- **JSON Output** — Machine-readable output for scripting and automation
|
|
52
|
+
|
|
53
|
+
## Requirements
|
|
54
|
+
|
|
55
|
+
- Python 3.10+
|
|
56
|
+
- [GitHub CLI](https://cli.github.com/) (`gh`) — must be installed and authenticated
|
|
57
|
+
- `rich` >= 13.0 — modern terminal output
|
|
58
|
+
|
|
59
|
+
### Authentication
|
|
60
|
+
|
|
61
|
+
The toolkit uses your `gh` CLI credentials:
|
|
62
|
+
|
|
63
|
+
```bash
|
|
64
|
+
gh auth login
|
|
65
|
+
gh auth refresh -h github.com -s user
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
## Installation
|
|
69
|
+
|
|
70
|
+
> **Note:** On Debian/Ubuntu 23.04+ the system Python is externally managed (PEP 668).
|
|
71
|
+
> Use a virtual environment or `pipx` to avoid installation errors.
|
|
72
|
+
|
|
73
|
+
### With pipx (Recommended)
|
|
74
|
+
|
|
75
|
+
```bash
|
|
76
|
+
pipx install git+https://github.com/ajangsupardi/github-toolkit.git
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
### From Source (Development)
|
|
80
|
+
|
|
81
|
+
```bash
|
|
82
|
+
git clone https://github.com/ajangsupardi/github-toolkit.git
|
|
83
|
+
cd github-toolkit
|
|
84
|
+
python3 -m venv .venv
|
|
85
|
+
source .venv/bin/activate
|
|
86
|
+
pip install -e .
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
### As Library (with venv)
|
|
90
|
+
|
|
91
|
+
```bash
|
|
92
|
+
python3 -m venv .venv
|
|
93
|
+
source .venv/bin/activate
|
|
94
|
+
pip install git+https://github.com/ajangsupardi/github-toolkit.git
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
## Usage
|
|
98
|
+
|
|
99
|
+
### Interactive Mode
|
|
100
|
+
|
|
101
|
+
Run without arguments to see the menu:
|
|
102
|
+
|
|
103
|
+
```bash
|
|
104
|
+
python3 -m github_toolkit
|
|
105
|
+
# or after pip install:
|
|
106
|
+
github-toolkit
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
```
|
|
110
|
+
╭──────────────────────────────────────────────╮
|
|
111
|
+
│ 🔍 GitHub Toolkit v1.0.0 │
|
|
112
|
+
╰──────────────────────────────────────────────╯
|
|
113
|
+
|
|
114
|
+
Choose a tool:
|
|
115
|
+
|
|
116
|
+
1. Follow Back — Follow all followers of a target user
|
|
117
|
+
2. Unfollow — Unfollow users who don't follow you back
|
|
118
|
+
|
|
119
|
+
0. Exit
|
|
120
|
+
|
|
121
|
+
→ Choice (0-2):
|
|
122
|
+
```
|
|
123
|
+
|
|
124
|
+
### CLI Mode
|
|
125
|
+
|
|
126
|
+
```bash
|
|
127
|
+
# Follow Back
|
|
128
|
+
python3 -m github_toolkit follow ajangsupardi # Dry-run
|
|
129
|
+
python3 -m github_toolkit follow ajangsupardi --execute # Execute
|
|
130
|
+
python3 -m github_toolkit follow ajangsupardi --limit 100 # Limit
|
|
131
|
+
|
|
132
|
+
# Unfollow
|
|
133
|
+
python3 -m github_toolkit unfollow # Dry-run
|
|
134
|
+
python3 -m github_toolkit unfollow --execute # Execute
|
|
135
|
+
python3 -m github_toolkit unfollow --limit 100 # Limit
|
|
136
|
+
|
|
137
|
+
# Common flags
|
|
138
|
+
python3 -m github_toolkit follow ajangsupardi --json # JSON output
|
|
139
|
+
python3 -m github_toolkit follow ajangsupardi --execute --include-bots
|
|
140
|
+
```
|
|
141
|
+
|
|
142
|
+
### As Library
|
|
143
|
+
|
|
144
|
+
```python
|
|
145
|
+
from github_toolkit.api import get_session, api_paginate, follow_user
|
|
146
|
+
from github_toolkit.models import enrich_users_concurrent
|
|
147
|
+
|
|
148
|
+
# Initialize session
|
|
149
|
+
get_session()
|
|
150
|
+
|
|
151
|
+
# Use API functions directly
|
|
152
|
+
followers = api_paginate("users/octocat/followers")
|
|
153
|
+
follow_user("octocat")
|
|
154
|
+
```
|
|
155
|
+
|
|
156
|
+
## Flags
|
|
157
|
+
|
|
158
|
+
| Flag | Description | Default |
|
|
159
|
+
|------|-------------|---------|
|
|
160
|
+
| `--execute` | Execute action (otherwise dry-run) | `false` |
|
|
161
|
+
| `--limit N` | Limit number of users processed | `0` (all) |
|
|
162
|
+
| `--include-bots` | Include bot accounts | `false` |
|
|
163
|
+
| `--json` | Output in JSON format | `false` |
|
|
164
|
+
|
|
165
|
+
## Project Structure
|
|
166
|
+
|
|
167
|
+
```
|
|
168
|
+
github-toolkit/
|
|
169
|
+
├── github_toolkit/ # Package
|
|
170
|
+
│ ├── __init__.py # Version
|
|
171
|
+
│ ├── __main__.py # Entry point
|
|
172
|
+
│ ├── cli.py # CLI dispatcher + interactive menu
|
|
173
|
+
│ ├── api.py # GitHub API (auth, pagination)
|
|
174
|
+
│ ├── models.py # Data models & bot detection
|
|
175
|
+
│ ├── formatting.py # Output formatting
|
|
176
|
+
│ └── tools/
|
|
177
|
+
│ └── social.py # Follow back & unfollow logic
|
|
178
|
+
├── pyproject.toml # Pip installable config
|
|
179
|
+
├── README.md
|
|
180
|
+
└── LICENSE
|
|
181
|
+
```
|
|
182
|
+
|
|
183
|
+
## How It Works
|
|
184
|
+
|
|
185
|
+
### Follow Back
|
|
186
|
+
|
|
187
|
+
```
|
|
188
|
+
1. Authenticate via gh CLI token
|
|
189
|
+
2. Fetch target user's followers (paginated, concurrent)
|
|
190
|
+
3. Fetch your following list to identify already-followed users
|
|
191
|
+
4. Filter out: yourself, already-followed, and optionally bots
|
|
192
|
+
5. Enrich user details concurrently (name, bio, repos)
|
|
193
|
+
6. Display table preview (dry-run) or execute follows concurrently
|
|
194
|
+
```
|
|
195
|
+
|
|
196
|
+
### Unfollow
|
|
197
|
+
|
|
198
|
+
```
|
|
199
|
+
1. Authenticate via gh CLI token
|
|
200
|
+
2. Fetch your followers & following lists (concurrent)
|
|
201
|
+
3. Find: users you follow who DON'T follow you back
|
|
202
|
+
4. Filter out: optionally bots
|
|
203
|
+
5. Enrich user details concurrently (name, bio, repos)
|
|
204
|
+
6. Display table preview (dry-run) or execute unfollows concurrently
|
|
205
|
+
```
|
|
206
|
+
|
|
207
|
+
## Bot Detection
|
|
208
|
+
|
|
209
|
+
Accounts are flagged as potential bots when **2 out of 3** conditions are met:
|
|
210
|
+
|
|
211
|
+
| Condition | Description |
|
|
212
|
+
|-----------|-------------|
|
|
213
|
+
| Default avatar | Uses GitHub's default identicon |
|
|
214
|
+
| Empty bio | No bio or whitespace only |
|
|
215
|
+
| Zero repos | No public repositories |
|
|
216
|
+
|
|
217
|
+
## License
|
|
218
|
+
|
|
219
|
+
MIT License — see [LICENSE](LICENSE) for details.
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
LICENSE
|
|
2
|
+
README.md
|
|
3
|
+
pyproject.toml
|
|
4
|
+
gh_social.egg-info/PKG-INFO
|
|
5
|
+
gh_social.egg-info/SOURCES.txt
|
|
6
|
+
gh_social.egg-info/dependency_links.txt
|
|
7
|
+
gh_social.egg-info/entry_points.txt
|
|
8
|
+
gh_social.egg-info/requires.txt
|
|
9
|
+
gh_social.egg-info/top_level.txt
|
|
10
|
+
github_toolkit/__init__.py
|
|
11
|
+
github_toolkit/__main__.py
|
|
12
|
+
github_toolkit/api.py
|
|
13
|
+
github_toolkit/cli.py
|
|
14
|
+
github_toolkit/formatting.py
|
|
15
|
+
github_toolkit/models.py
|
|
16
|
+
github_toolkit/py.typed
|
|
17
|
+
github_toolkit/tools/__init__.py
|
|
18
|
+
github_toolkit/tools/social.py
|
|
19
|
+
tests/test_formatting.py
|
|
20
|
+
tests/test_models.py
|
|
21
|
+
tests/test_social.py
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
github_toolkit
|