Skip to content

Commit 96da79d

Browse files
committed
[FEAT] X(Twitter) 프로바이더 추가 (v0.7.0)
- 순수 HTTP 기반 X 프로바이더 구현 (브라우저 불필요) - GraphQL queryId 동적 추출 (main.js 파싱, 166개 operation, 1시간 캐시) - X 배포 시에도 자동 재동기화로 깨지지 않음 - 16개 메서드: 트윗 발행/삭제, 좋아요, 리트윗, 팔로우, 검색, 타임라인, 미디어 업로드 - Rate limit: 트윗 2~5분, 좋아요 30~60초, 팔로우 2~3분 간격 (신규 계정 보수적) - 쿠키 기반 인증 (auth_token + ct0) - 영문/한국어 가이드 문서 추가 - README.md, README.ko.md, CLAUDE.md 업데이트
1 parent cc6ebf3 commit 96da79d

File tree

15 files changed

+1592
-13
lines changed

15 files changed

+1592
-13
lines changed

CLAUDE.md

Lines changed: 38 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -33,12 +33,19 @@ src/
3333
│ │ ├── selectors.js
3434
│ │ ├── editorConvert.js
3535
│ │ └── imageUpload.js
36-
│ └── insta/ # Instagram 프로바이더 (순수 HTTP, 브라우저 불필요)
37-
│ ├── index.js # 메인 (18개 메서드)
38-
│ ├── auth.js # HTTP 로그인 (fetch 기반)
39-
│ ├── session.js # 세션 + rate limit 영속화 (userId별)
40-
│ ├── apiClient.js # Instagram API 클라이언트 + 안전 규칙
41-
│ ├── smartComment.js # 게시물 분석 (썸네일 base64 + 캡션)
36+
│ ├── insta/ # Instagram 프로바이더 (순수 HTTP, 브라우저 불필요)
37+
│ │ ├── index.js # 메인 (18개 메서드)
38+
│ │ ├── auth.js # HTTP 로그인 (fetch 기반)
39+
│ │ ├── session.js # 세션 + rate limit 영속화 (userId별)
40+
│ │ ├── apiClient.js # Instagram API 클라이언트 + 안전 규칙
41+
│ │ ├── smartComment.js # 게시물 분석 (썸네일 base64 + 캡션)
42+
│ │ └── utils.js
43+
│ └── x/ # X (Twitter) 프로바이더 (비공식 GraphQL API, 브라우저 불필요)
44+
│ ├── index.js # 메인 (16개 메서드)
45+
│ ├── auth.js # 쿠키 기반 인증 (auth_token + ct0)
46+
│ ├── session.js # 세션 + rate limit 영속화
47+
│ ├── apiClient.js # GraphQL API 클라이언트 + 안전 규칙
48+
│ ├── graphqlSync.js # main.js에서 queryId 동적 추출 + 캐싱
4249
│ └── utils.js
4350
├── bin/
4451
│ └── index.js # CLI 엔트리포인트
@@ -53,7 +60,9 @@ src/
5360
├── sessions/
5461
│ ├── tistory-session.json # Tistory 쿠키
5562
│ ├── naver-session.json # Naver 쿠키
56-
│ └── insta-session.json # Instagram 쿠키 + rate limit 카운터 (userId별)
63+
│ ├── insta-session.json # Instagram 쿠키 + rate limit 카운터 (userId별)
64+
│ └── x-session.json # X (Twitter) 쿠키 (auth_token + ct0)
65+
├── x-graphql-cache.json # X GraphQL queryId 캐시 (1시간 TTL)
5766
└── providers.json # 프로바이더 메타 정보
5867
```
5968

@@ -64,6 +73,7 @@ src/
6473
| tistory | Playwright 브라우저 | playwright | 블로그 글 발행, 임시저장, 이미지 업로드 |
6574
| naver | Playwright 브라우저 | playwright | 블로그 글 발행, 에디터 컴포넌트 변환 |
6675
| insta | 순수 HTTP (fetch) | 없음 | 로그인, 프로필, 피드, 좋아요, 댓글, 팔로우, 포스팅 |
76+
| x | 쿠키 기반 (auth_token + ct0) | 없음 | 트윗 발행, 타임라인, 검색, 좋아요, 리트윗, 미디어 업로드 |
6777

6878
## Instagram Rate Limit 규칙
6979

@@ -82,6 +92,23 @@ src/
8292
- 카운터는 세션 파일에 userId별로 영속화
8393
- challenge 발생 시 브라우저에서 본인 인증 필요
8494

95+
## X (Twitter) Rate Limit 규칙
96+
97+
신규 계정 (0~30일) 기준:
98+
99+
| 액션 | 딜레이 | 시간당 | 일일 |
100+
|------|--------|--------|------|
101+
| 트윗 | 120~300초 (2~5분) | 10 | 50 |
102+
| 좋아요 | 30~60초 | 15 | 200 |
103+
| 리트윗 | 60~120초 | 10 | 50 |
104+
| 팔로우 | 120~180초 | 10 | 100 |
105+
| 언팔로우 | 120~180초 | 8 | 80 |
106+
107+
- 트윗/답글/인용 합산 하드캡: 2,400/일 (성숙 계정)
108+
- 226 에러 발생 시 12~48시간 쿨다운 필수
109+
- 읽기(프로필/타임라인/검색)는 HTTP API, 쓰기(발행)는 브라우저 경유 권장 (신규 계정)
110+
- queryId는 `~/.viruagent-cli/x-graphql-cache.json`에 캐싱 (1시간 TTL, 자동 갱신)
111+
85112
## 환경변수
86113

87114
```
@@ -96,6 +123,10 @@ NAVER_PASSWORD=
96123
# Instagram
97124
INSTA_USERNAME=
98125
INSTA_PASSWORD=
126+
127+
# X (Twitter) — 브라우저에서 쿠키 추출 필요
128+
X_AUTH_TOKEN=
129+
X_CT0=
99130
```
100131

101132
## 배포

README.ko.md

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@
2929
| **Tistory** | Playwright (카카오) | 글 발행, 임시저장, 카테고리, 이미지 업로드 | [가이드](docs/ko/guide-tistory.md) |
3030
| **Naver Blog** | Playwright (네이버) | 글 발행, 카테고리, SE Editor, 이미지 업로드 | [가이드](docs/ko/guide-naver.md) |
3131
| **Instagram** | HTTP (브라우저 불필요) | 좋아요, 댓글, 팔로우, 포스팅, 프로필, 피드 | [가이드](docs/ko/guide-instagram.md) |
32+
| **X (Twitter)** | HTTP (쿠키 인증) | 트윗, 좋아요, 리트윗, 팔로우, 검색, 타임라인, 미디어 업로드 | [가이드](docs/ko/guide-x.md) |
3233

3334
## 동작 방식
3435

@@ -95,6 +96,15 @@ npx viruagent-cli login --provider insta --username <인스타 ID> --password <
9596
>
9697
> 전체 API 레퍼런스와 rate limit 규칙은 [Instagram 가이드](docs/ko/guide-instagram.md)를 참고하세요.
9798
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+
98108
## 사용법
99109

100110
| 이렇게 말하면 | 에이전트가 알아서 |
@@ -107,12 +117,17 @@ npx viruagent-cli login --provider insta --username <인스타 ID> --password <
107117
| "이 사람 피드 분석해서 댓글 달아줘" | analyzePost → AI 댓글 생성 → comment |
108118
| "@user 팔로우해줘" | 로그인 → follow (딜레이 자동 적용) |
109119
| "인스타 rate limit 확인해줘" | rate-limit-status → 카운터 표시 |
120+
| "이 내용으로 트윗해줘" | X 로그인 → publish (rate limit 자동 적용) |
121+
| "X에서 AI 도구 검색해줘" | search → 결과 반환 |
122+
| "X에서 IT 개발자 좋아요하고 팔로우해줘" | search → like + follow (딜레이 자동 적용) |
123+
| "내 X 타임라인 보여줘" | getFeed → 최신 트윗 표시 |
110124

111125
## 플랫폼별 가이드
112126

113127
- **[Tistory 가이드](docs/ko/guide-tistory.md)** — 블로그 발행, 이미지 업로드, 카테고리
114128
- **[Naver Blog 가이드](docs/ko/guide-naver.md)** — SE Editor, 블로그 발행, 이미지 업로드
115129
- **[Instagram 가이드](docs/ko/guide-instagram.md)** — 18개 API 메서드, rate limit 규칙, AI 댓글
130+
- **[X (Twitter) 가이드](docs/ko/guide-x.md)** — GraphQL API, queryId 동적 동기화, rate limit 규칙
116131

117132
## 지원 환경
118133

@@ -129,6 +144,7 @@ npx viruagent-cli login --provider insta --username <인스타 ID> --password <
129144
| CLI 프레임워크 | Commander.js |
130145
| 브라우저 자동화 | Playwright (Tistory, Naver만 사용) |
131146
| Instagram API | 순수 HTTP fetch (브라우저 불필요) |
147+
| X (Twitter) API | 내부 GraphQL API + queryId 동적 추출 |
132148
| 세션 관리 | JSON 파일 (`~/.viruagent-cli/`) |
133149
| Rate Limiting | 유저별 영속 카운터 + 랜덤 딜레이 |
134150
| 이미지 검색 | DuckDuckGo, Wikimedia Commons |

README.md

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ Designed not for humans, but for **AI agents**.
2929
| **Tistory** | Playwright (Kakao) | Publish, Draft, Categories, Image Upload | [Guide](docs/en/guide-tistory.md) |
3030
| **Naver Blog** | Playwright (Naver) | Publish, Categories, SE Editor, Image Upload | [Guide](docs/en/guide-naver.md) |
3131
| **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) |
3233

3334
## How It Works
3435

@@ -95,6 +96,15 @@ npx viruagent-cli login --provider insta --username <id> --password <pw>
9596
>
9697
> See the [Instagram Guide](docs/en/guide-instagram.md) for full API reference and rate limit rules.
9798
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+
98108
## Usage
99109

100110
| Say this | Agent handles |
@@ -107,12 +117,17 @@ npx viruagent-cli login --provider insta --username <id> --password <pw>
107117
| "Analyze and comment on @user's feed" | analyzePost → AI generates comment → comment |
108118
| "Follow @user" | Login → follow (with delay) |
109119
| "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 |
110124

111125
## Platform Guides
112126

113127
- **[Tistory Guide](docs/en/guide-tistory.md)** — Blog publishing, image upload, categories
114128
- **[Naver Blog Guide](docs/en/guide-naver.md)** — SE Editor, blog publishing, image upload
115129
- **[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
116131

117132
## Supported Environments
118133

@@ -129,6 +144,7 @@ npx viruagent-cli login --provider insta --username <id> --password <pw>
129144
| CLI Framework | Commander.js |
130145
| Browser Automation | Playwright (Tistory, Naver only) |
131146
| Instagram API | Pure HTTP fetch (no browser) |
147+
| X (Twitter) API | Internal GraphQL API with dynamic queryId extraction |
132148
| Session Management | JSON file (`~/.viruagent-cli/`) |
133149
| Rate Limiting | Per-user persistent counters with random delays |
134150
| Image Search | DuckDuckGo, Wikimedia Commons |

docs/en/guide-x.md

Lines changed: 116 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,116 @@
1+
# X (Twitter) Guide
2+
3+
X automation via internal GraphQL API. Works via pure HTTP — no browser needed for reads. Cookie-based authentication.
4+
5+
## Login
6+
7+
Extract `auth_token` and `ct0` cookies from your browser (DevTools → Application → Cookies → x.com).
8+
9+
```bash
10+
npx viruagent-cli login --provider x --auth-token <auth_token> --ct0 <ct0>
11+
```
12+
13+
### Environment Variables
14+
15+
```bash
16+
export X_AUTH_TOKEN=<auth_token cookie>
17+
export X_CT0=<ct0 cookie>
18+
19+
# With env vars set, flags can be omitted
20+
npx viruagent-cli login --provider x
21+
```
22+
23+
### Session Duration
24+
25+
The `auth_token` cookie is valid for **~1 year**. The `ct0` (CSRF token) may rotate but is auto-refreshed.
26+
27+
## Features (16 Methods)
28+
29+
### Authentication
30+
| Command | Description |
31+
|---------|-------------|
32+
| `login` | Set auth_token + ct0 cookies, verify via Viewer query |
33+
| `auth-status` | Check login status, show username and metadata |
34+
| `logout` | Clear session and provider metadata |
35+
36+
### Read Operations
37+
| Command | Description |
38+
|---------|-------------|
39+
| `get-profile --username <name>` | User profile (followers, tweets, bio, etc.) |
40+
| `get-feed` | Home timeline (latest tweets from followed accounts) |
41+
| `list-posts --username <name>` | User's tweets |
42+
| `read-post --post-id <id>` | Tweet detail (likes, retweets, replies, media) |
43+
| `search --query <text>` | Search tweets |
44+
45+
### Write Operations
46+
| Command | Description |
47+
|---------|-------------|
48+
| `publish --content <text>` | Post a tweet (with optional media) |
49+
| `delete --post-id <id>` | Delete a tweet |
50+
51+
### Interactions
52+
| Command | Description |
53+
|---------|-------------|
54+
| `like --post-id <id>` | Like a tweet |
55+
| `unlike --post-id <id>` | Unlike a tweet |
56+
| `retweet --post-id <id>` | Retweet |
57+
| `unretweet --post-id <id>` | Undo retweet |
58+
| `follow --username <name>` | Follow a user |
59+
| `unfollow --username <name>` | Unfollow a user |
60+
61+
### Utilities
62+
| Command | Description |
63+
|---------|-------------|
64+
| `rate-limit-status` | Show current rate limit counters |
65+
| `sync-operations` | Force re-sync GraphQL queryIds from x.com |
66+
67+
## GraphQL QueryId Dynamic Sync
68+
69+
X uses internal GraphQL APIs where each operation has a `queryId` that **changes on every X deployment**. viruagent-cli handles this automatically:
70+
71+
1. Fetches `https://x.com` HTML → extracts `main.{hash}.js` URL
72+
2. Downloads main.js → parses all `queryId` / `operationName` / `featureSwitches` mappings
73+
3. Caches to `~/.viruagent-cli/x-graphql-cache.json` (1-hour TTL)
74+
4. On API failure (stale queryId) → auto re-syncs and retries
75+
76+
Currently extracts **166 GraphQL operations** including CreateTweet, DeleteTweet, FavoriteTweet, UserByScreenName, SearchTimeline, HomeLatestTimeline, etc.
77+
78+
## Rate Limits
79+
80+
New account (0–30 days):
81+
82+
| Action | Delay | Hourly | Daily |
83+
|--------|-------|--------|-------|
84+
| Tweet | 120–300s (2–5min) | 10 | 50 |
85+
| Like | 30–60s | 15 | 200 |
86+
| Retweet | 60–120s | 10 | 50 |
87+
| Follow | 120–180s | 10 | 100 |
88+
| Unfollow | 120–180s | 8 | 80 |
89+
90+
- Hard cap: 2,400 tweets/day (includes replies and quotes)
91+
- **226 error** = automated behavior detected → wait 12–48 hours
92+
- Counters persist in session file across CLI restarts
93+
- Random jitter applied to all delays (±30%)
94+
95+
### 226 Error Triggers
96+
97+
- Burst actions without human-like variance
98+
- Repetitive content
99+
- Write-only patterns (no read behavior)
100+
- New account + high volume
101+
- Fixed intervals between actions
102+
103+
## Media Upload
104+
105+
Supports image upload via chunked upload to `upload.x.com`:
106+
107+
```bash
108+
npx viruagent-cli publish --provider x --content "Hello world" --media /path/to/image.jpg
109+
```
110+
111+
## Notes
112+
113+
- **Read operations** (profile, timeline, search) work reliably via HTTP API
114+
- **Write operations** (tweet, retweet) may trigger 226 on new accounts — use browser fallback if needed
115+
- **Like/unlike, follow/unfollow** work via HTTP API even on new accounts
116+
- GraphQL queryIds are automatically refreshed — no manual maintenance needed

0 commit comments

Comments
 (0)