viruagent-cli 0.6.2 → 0.7.1
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.
- package/README.ko.md +17 -1
- package/README.md +17 -1
- package/bin/index.js +24 -1
- package/package.json +3 -2
- package/src/providers/insta/apiClient.js +4 -2
- package/src/providers/reddit/apiClient.js +584 -0
- package/src/providers/reddit/auth.js +454 -0
- package/src/providers/reddit/index.js +233 -0
- package/src/providers/reddit/session.js +174 -0
- package/src/providers/reddit/utils.js +49 -0
- package/src/providers/tistory/auth.js +11 -0
- package/src/providers/tistory/selectors.js +9 -0
- package/src/providers/x/apiClient.js +674 -0
- package/src/providers/x/auth.js +87 -0
- package/src/providers/x/graphqlSync.js +140 -0
- package/src/providers/x/index.js +251 -0
- package/src/providers/x/session.js +114 -0
- package/src/providers/x/utils.js +32 -0
- package/src/runner.js +50 -1
- package/src/services/providerManager.js +6 -2
package/README.ko.md
CHANGED
|
@@ -29,6 +29,7 @@
|
|
|
29
29
|
| **Tistory** | Playwright (카카오) | 글 발행, 임시저장, 카테고리, 이미지 업로드 | [가이드](docs/ko/guide-tistory.md) |
|
|
30
30
|
| **Naver Blog** | Playwright (네이버) | 글 발행, 카테고리, SE Editor, 이미지 업로드 | [가이드](docs/ko/guide-naver.md) |
|
|
31
31
|
| **Instagram** | HTTP (브라우저 불필요) | 좋아요, 댓글, 팔로우, 포스팅, 프로필, 피드 | [가이드](docs/ko/guide-instagram.md) |
|
|
32
|
+
| **X (Twitter)** | HTTP (쿠키 인증) | 트윗, 좋아요, 리트윗, 팔로우, 검색, 타임라인, 미디어 업로드 | [가이드](docs/ko/guide-x.md) |
|
|
32
33
|
|
|
33
34
|
## 동작 방식
|
|
34
35
|
|
|
@@ -50,7 +51,7 @@
|
|
|
50
51
|
|
|
51
52
|
## 빠른 시작
|
|
52
53
|
|
|
53
|
-

|
|
54
55
|
|
|
55
56
|
아래 내용을 AI 에이전트에게 그대로 복사해서 보여주세요.
|
|
56
57
|
|
|
@@ -95,6 +96,15 @@ npx viruagent-cli login --provider insta --username <인스타 ID> --password <
|
|
|
95
96
|
>
|
|
96
97
|
> 전체 API 레퍼런스와 rate limit 규칙은 [Instagram 가이드](docs/ko/guide-instagram.md)를 참고하세요.
|
|
97
98
|
|
|
99
|
+
### X (Twitter)
|
|
100
|
+
|
|
101
|
+
```bash
|
|
102
|
+
npx viruagent-cli login --provider x --auth-token <토큰> --ct0 <ct0>
|
|
103
|
+
```
|
|
104
|
+
> 브라우저에서 `auth_token`과 `ct0` 쿠키를 추출하세요. 비밀번호 로그인 없음 — 쿠키 기반 인증만 지원.
|
|
105
|
+
>
|
|
106
|
+
> 전체 API 레퍼런스, GraphQL 동기화, rate limit 규칙은 [X 가이드](docs/ko/guide-x.md)를 참고하세요.
|
|
107
|
+
|
|
98
108
|
## 사용법
|
|
99
109
|
|
|
100
110
|
| 이렇게 말하면 | 에이전트가 알아서 |
|
|
@@ -107,12 +117,17 @@ npx viruagent-cli login --provider insta --username <인스타 ID> --password <
|
|
|
107
117
|
| "이 사람 피드 분석해서 댓글 달아줘" | analyzePost → AI 댓글 생성 → comment |
|
|
108
118
|
| "@user 팔로우해줘" | 로그인 → follow (딜레이 자동 적용) |
|
|
109
119
|
| "인스타 rate limit 확인해줘" | rate-limit-status → 카운터 표시 |
|
|
120
|
+
| "이 내용으로 트윗해줘" | X 로그인 → publish (rate limit 자동 적용) |
|
|
121
|
+
| "X에서 AI 도구 검색해줘" | search → 결과 반환 |
|
|
122
|
+
| "X에서 IT 개발자 좋아요하고 팔로우해줘" | search → like + follow (딜레이 자동 적용) |
|
|
123
|
+
| "내 X 타임라인 보여줘" | getFeed → 최신 트윗 표시 |
|
|
110
124
|
|
|
111
125
|
## 플랫폼별 가이드
|
|
112
126
|
|
|
113
127
|
- **[Tistory 가이드](docs/ko/guide-tistory.md)** — 블로그 발행, 이미지 업로드, 카테고리
|
|
114
128
|
- **[Naver Blog 가이드](docs/ko/guide-naver.md)** — SE Editor, 블로그 발행, 이미지 업로드
|
|
115
129
|
- **[Instagram 가이드](docs/ko/guide-instagram.md)** — 18개 API 메서드, rate limit 규칙, AI 댓글
|
|
130
|
+
- **[X (Twitter) 가이드](docs/ko/guide-x.md)** — GraphQL API, queryId 동적 동기화, rate limit 규칙
|
|
116
131
|
|
|
117
132
|
## 지원 환경
|
|
118
133
|
|
|
@@ -129,6 +144,7 @@ npx viruagent-cli login --provider insta --username <인스타 ID> --password <
|
|
|
129
144
|
| CLI 프레임워크 | Commander.js |
|
|
130
145
|
| 브라우저 자동화 | Playwright (Tistory, Naver만 사용) |
|
|
131
146
|
| Instagram API | 순수 HTTP fetch (브라우저 불필요) |
|
|
147
|
+
| X (Twitter) API | 내부 GraphQL API + queryId 동적 추출 |
|
|
132
148
|
| 세션 관리 | JSON 파일 (`~/.viruagent-cli/`) |
|
|
133
149
|
| Rate Limiting | 유저별 영속 카운터 + 랜덤 딜레이 |
|
|
134
150
|
| 이미지 검색 | DuckDuckGo, Wikimedia Commons |
|
package/README.md
CHANGED
|
@@ -29,6 +29,7 @@ Designed not for humans, but for **AI agents**.
|
|
|
29
29
|
| **Tistory** | Playwright (Kakao) | Publish, Draft, Categories, Image Upload | [Guide](docs/en/guide-tistory.md) |
|
|
30
30
|
| **Naver Blog** | Playwright (Naver) | Publish, Categories, SE Editor, Image Upload | [Guide](docs/en/guide-naver.md) |
|
|
31
31
|
| **Instagram** | HTTP (No Browser) | Like, Comment, Follow, Post, Profile, Feed, Rate Limit | [Guide](docs/en/guide-instagram.md) |
|
|
32
|
+
| **X (Twitter)** | HTTP (Cookie Auth) | Tweet, Like, Retweet, Follow, Search, Timeline, Media Upload | [Guide](docs/en/guide-x.md) |
|
|
32
33
|
|
|
33
34
|
## How It Works
|
|
34
35
|
|
|
@@ -50,7 +51,7 @@ User: "Like and comment on all posts from @username"
|
|
|
50
51
|
|
|
51
52
|
## Quick Start
|
|
52
53
|
|
|
53
|
-

|
|
54
55
|
|
|
55
56
|
Copy the following to your AI agent:
|
|
56
57
|
|
|
@@ -95,6 +96,15 @@ npx viruagent-cli login --provider insta --username <id> --password <pw>
|
|
|
95
96
|
>
|
|
96
97
|
> See the [Instagram Guide](docs/en/guide-instagram.md) for full API reference and rate limit rules.
|
|
97
98
|
|
|
99
|
+
### X (Twitter)
|
|
100
|
+
|
|
101
|
+
```bash
|
|
102
|
+
npx viruagent-cli login --provider x --auth-token <token> --ct0 <ct0>
|
|
103
|
+
```
|
|
104
|
+
> Extract `auth_token` and `ct0` cookies from your browser. No password login — cookie-based auth only.
|
|
105
|
+
>
|
|
106
|
+
> See the [X Guide](docs/en/guide-x.md) for full API reference, GraphQL sync, and rate limit rules.
|
|
107
|
+
|
|
98
108
|
## Usage
|
|
99
109
|
|
|
100
110
|
| Say this | Agent handles |
|
|
@@ -107,12 +117,17 @@ npx viruagent-cli login --provider insta --username <id> --password <pw>
|
|
|
107
117
|
| "Analyze and comment on @user's feed" | analyzePost → AI generates comment → comment |
|
|
108
118
|
| "Follow @user" | Login → follow (with delay) |
|
|
109
119
|
| "Check Instagram rate limit" | rate-limit-status → show counters |
|
|
120
|
+
| "Tweet this text" | X login → publish (with rate limit) |
|
|
121
|
+
| "Search X for AI tools" | search → return results |
|
|
122
|
+
| "Like and follow IT devs on X" | search → like + follow (with delays) |
|
|
123
|
+
| "Show my X timeline" | getFeed → show latest tweets |
|
|
110
124
|
|
|
111
125
|
## Platform Guides
|
|
112
126
|
|
|
113
127
|
- **[Tistory Guide](docs/en/guide-tistory.md)** — Blog publishing, image upload, categories
|
|
114
128
|
- **[Naver Blog Guide](docs/en/guide-naver.md)** — SE Editor, blog publishing, image upload
|
|
115
129
|
- **[Instagram Guide](docs/en/guide-instagram.md)** — 18 API methods, rate limits, AI commenting
|
|
130
|
+
- **[X (Twitter) Guide](docs/en/guide-x.md)** — GraphQL API, dynamic queryId sync, rate limits
|
|
116
131
|
|
|
117
132
|
## Supported Environments
|
|
118
133
|
|
|
@@ -129,6 +144,7 @@ npx viruagent-cli login --provider insta --username <id> --password <pw>
|
|
|
129
144
|
| CLI Framework | Commander.js |
|
|
130
145
|
| Browser Automation | Playwright (Tistory, Naver only) |
|
|
131
146
|
| Instagram API | Pure HTTP fetch (no browser) |
|
|
147
|
+
| X (Twitter) API | Internal GraphQL API with dynamic queryId extraction |
|
|
132
148
|
| Session Management | JSON file (`~/.viruagent-cli/`) |
|
|
133
149
|
| Rate Limiting | Per-user persistent counters with random delays |
|
|
134
150
|
| Image Search | DuckDuckGo, Wikimedia Commons |
|
package/bin/index.js
CHANGED
|
@@ -18,7 +18,7 @@ program
|
|
|
18
18
|
|
|
19
19
|
// Global options
|
|
20
20
|
const addProviderOption = (cmd) =>
|
|
21
|
-
cmd.option('--provider <name>', 'Provider name (tistory, naver, insta)', 'tistory');
|
|
21
|
+
cmd.option('--provider <name>', 'Provider name (tistory, naver, insta, x, reddit)', 'tistory');
|
|
22
22
|
|
|
23
23
|
const addDryRunOption = (cmd) =>
|
|
24
24
|
cmd.option('--dry-run', 'Validate params without executing', false);
|
|
@@ -49,6 +49,10 @@ loginCmd
|
|
|
49
49
|
.option('--headless', 'Run browser in headless mode', false)
|
|
50
50
|
.option('--manual', 'Use manual login mode', false)
|
|
51
51
|
.option('--two-factor-code <code>', '2FA verification code')
|
|
52
|
+
.option('--auth-token <token>', 'Auth token (X provider)')
|
|
53
|
+
.option('--ct0 <ct0>', 'CT0 token (X provider)')
|
|
54
|
+
.option('--client-id <id>', 'OAuth Client ID (Reddit)')
|
|
55
|
+
.option('--client-secret <secret>', 'OAuth Client Secret (Reddit)')
|
|
52
56
|
.action((opts) => execute('login', opts));
|
|
53
57
|
|
|
54
58
|
const publishCmd = program
|
|
@@ -70,6 +74,9 @@ publishCmd
|
|
|
70
74
|
.option('--minimum-image-count <n>', 'Minimum required images', '1')
|
|
71
75
|
.option('--no-auto-upload-images', 'Disable automatic image uploading')
|
|
72
76
|
.option('--no-enforce-system-prompt', 'Disable system prompt enforcement')
|
|
77
|
+
.option('--subreddit <name>', 'Subreddit name (Reddit)')
|
|
78
|
+
.option('--kind <type>', 'Post kind: self or link (Reddit)', 'self')
|
|
79
|
+
.option('--flair <id>', 'Flair template ID (Reddit)')
|
|
73
80
|
.action((opts) => execute('publish', opts));
|
|
74
81
|
|
|
75
82
|
const saveDraftCmd = program
|
|
@@ -250,6 +257,22 @@ const rateLimitCmd = program
|
|
|
250
257
|
addProviderOption(rateLimitCmd);
|
|
251
258
|
rateLimitCmd.action((opts) => execute('rate-limit-status', opts));
|
|
252
259
|
|
|
260
|
+
const subscribeCmd = program
|
|
261
|
+
.command('subscribe')
|
|
262
|
+
.description('Subscribe to a subreddit (Reddit)');
|
|
263
|
+
addProviderOption(subscribeCmd);
|
|
264
|
+
subscribeCmd
|
|
265
|
+
.option('--subreddit <name>', 'Subreddit name')
|
|
266
|
+
.action((opts) => execute('subscribe', opts));
|
|
267
|
+
|
|
268
|
+
const unsubscribeCmd = program
|
|
269
|
+
.command('unsubscribe')
|
|
270
|
+
.description('Unsubscribe from a subreddit (Reddit)');
|
|
271
|
+
addProviderOption(unsubscribeCmd);
|
|
272
|
+
unsubscribeCmd
|
|
273
|
+
.option('--subreddit <name>', 'Subreddit name')
|
|
274
|
+
.action((opts) => execute('unsubscribe', opts));
|
|
275
|
+
|
|
253
276
|
// --- Utility commands ---
|
|
254
277
|
|
|
255
278
|
const installSkillCmd = program
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "viruagent-cli",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.7.1",
|
|
4
4
|
"description": "AI-agent-optimized CLI for blog publishing (Tistory, Naver) and Instagram automation",
|
|
5
5
|
"private": false,
|
|
6
6
|
"type": "commonjs",
|
|
@@ -42,6 +42,7 @@
|
|
|
42
42
|
},
|
|
43
43
|
"dependencies": {
|
|
44
44
|
"commander": "^14.0.3",
|
|
45
|
-
"playwright": "^1.58.2"
|
|
45
|
+
"playwright": "^1.58.2",
|
|
46
|
+
"x-client-transaction-id": "^0.2.0"
|
|
46
47
|
}
|
|
47
48
|
}
|
|
@@ -167,9 +167,10 @@ const createInstaApiClient = ({ sessionPath }) => {
|
|
|
167
167
|
...options.headers,
|
|
168
168
|
};
|
|
169
169
|
|
|
170
|
-
const
|
|
170
|
+
const redirectMode = options.followRedirect ? 'follow' : 'manual';
|
|
171
|
+
const res = await fetch(url, { ...options, headers, redirect: redirectMode });
|
|
171
172
|
|
|
172
|
-
if (res.status === 302 || res.status === 301) {
|
|
173
|
+
if (!options.followRedirect && (res.status === 302 || res.status === 301)) {
|
|
173
174
|
const location = res.headers.get('location') || '';
|
|
174
175
|
if (location.includes('/accounts/login')) {
|
|
175
176
|
throw new Error('Session expired. Please log in again.');
|
|
@@ -608,6 +609,7 @@ const createInstaApiClient = ({ sessionPath }) => {
|
|
|
608
609
|
Offset: '0',
|
|
609
610
|
},
|
|
610
611
|
body: imageBuffer,
|
|
612
|
+
followRedirect: true,
|
|
611
613
|
},
|
|
612
614
|
);
|
|
613
615
|
const data = await res.json();
|