@hardlydifficult/social 1.0.2 → 1.0.4
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.md +179 -3
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -12,13 +12,163 @@ This package is intentionally read-only for now:
|
|
|
12
12
|
|
|
13
13
|
Write operations (posting, liking, reposting) are intentionally not included yet.
|
|
14
14
|
|
|
15
|
-
##
|
|
15
|
+
## Installation
|
|
16
16
|
|
|
17
17
|
```bash
|
|
18
18
|
npm install @hardlydifficult/social
|
|
19
19
|
```
|
|
20
20
|
|
|
21
|
-
##
|
|
21
|
+
## Quick Start
|
|
22
|
+
|
|
23
|
+
```typescript
|
|
24
|
+
import { createXClient } from '@hardlydifficult/social';
|
|
25
|
+
|
|
26
|
+
const client = createXClient({
|
|
27
|
+
bearerToken: process.env.X_BEARER_TOKEN!,
|
|
28
|
+
});
|
|
29
|
+
|
|
30
|
+
const timeline = await client.getTimeline();
|
|
31
|
+
console.log(`Retrieved ${timeline.length} posts`);
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
## Core Client
|
|
35
|
+
|
|
36
|
+
### Social Client
|
|
37
|
+
|
|
38
|
+
The `SocialClient` wraps a `SocialProviderClient` implementation to provide a platform-agnostic interface for social operations.
|
|
39
|
+
|
|
40
|
+
```typescript
|
|
41
|
+
import { createXClient } from '@hardlydifficult/social';
|
|
42
|
+
|
|
43
|
+
const client = createXClient({ bearerToken: 'your-token' });
|
|
44
|
+
|
|
45
|
+
// Get timeline posts
|
|
46
|
+
const posts = await client.getTimeline();
|
|
47
|
+
|
|
48
|
+
// Get posts where the user was liked (via polling-like interface)
|
|
49
|
+
const likedPosts = await client.getLikedPosts();
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
### Social Provider Interface
|
|
53
|
+
|
|
54
|
+
All provider implementations must implement `SocialProviderClient`, which requires:
|
|
55
|
+
|
|
56
|
+
- `getTimeline()`: Fetch recent posts
|
|
57
|
+
- `getLikedPosts()`: Fetch posts the authenticated user has liked
|
|
58
|
+
- `getPost(postId: string)`: Fetch a specific post
|
|
59
|
+
|
|
60
|
+
```typescript
|
|
61
|
+
import type { SocialProviderClient } from '@hardlydifficult/social';
|
|
62
|
+
|
|
63
|
+
// Example interface contract
|
|
64
|
+
interface MyProvider implements SocialProviderClient {
|
|
65
|
+
getTimeline(): Promise<SocialPost[]>;
|
|
66
|
+
getLikedPosts(): Promise<SocialPost[]>;
|
|
67
|
+
getPost(id: string): Promise<SocialPost | undefined>;
|
|
68
|
+
}
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
## Types
|
|
72
|
+
|
|
73
|
+
### SocialPost
|
|
74
|
+
|
|
75
|
+
Standardized post type used across platforms:
|
|
76
|
+
|
|
77
|
+
```typescript
|
|
78
|
+
import type { SocialPost } from '@hardlydifficult/social';
|
|
79
|
+
|
|
80
|
+
interface SocialPost {
|
|
81
|
+
id: string;
|
|
82
|
+
text: string;
|
|
83
|
+
createdAt: Date;
|
|
84
|
+
author: {
|
|
85
|
+
username: string;
|
|
86
|
+
displayName?: string;
|
|
87
|
+
avatarUrl?: string;
|
|
88
|
+
};
|
|
89
|
+
media?: { url: string; type: 'image' | 'video' }[];
|
|
90
|
+
}
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
## X (Twitter) Client
|
|
94
|
+
|
|
95
|
+
The `XSocialClient` implements the provider interface against the X/Twitter API.
|
|
96
|
+
|
|
97
|
+
### Constructor Options
|
|
98
|
+
|
|
99
|
+
| Option | Type | Required | Description |
|
|
100
|
+
|--------|------|----------|-------------|
|
|
101
|
+
| `bearerToken` | `string` | ✅ | Twitter API bearer token |
|
|
102
|
+
| `userId` | `string` | ❌ | User ID; falls back to `/2/users/me` if not provided |
|
|
103
|
+
|
|
104
|
+
### Example Usage
|
|
105
|
+
|
|
106
|
+
```typescript
|
|
107
|
+
import { createXClient } from '@hardlydifficult/social';
|
|
108
|
+
|
|
109
|
+
const client = createXClient({
|
|
110
|
+
bearerToken: process.env.X_BEARER_TOKEN!,
|
|
111
|
+
});
|
|
112
|
+
|
|
113
|
+
// Fetch timeline
|
|
114
|
+
const posts = await client.getTimeline();
|
|
115
|
+
|
|
116
|
+
// Fetch liked posts for this user
|
|
117
|
+
const likedPosts = await client.getLikedPosts();
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
## Like Watching
|
|
121
|
+
|
|
122
|
+
`SocialLikeWatcher` polls the provider for new liked posts and emits events when new ones are detected.
|
|
123
|
+
|
|
124
|
+
### Constructor Options
|
|
125
|
+
|
|
126
|
+
| Option | Type | Required | Default | Description |
|
|
127
|
+
|--------|------|----------|---------|-------------|
|
|
128
|
+
| `client` | `SocialProviderClient` | ✅ | — | Provider client instance |
|
|
129
|
+
| `pollIntervalMs` | `number` | ❌ | `60_000` | Polling interval in milliseconds |
|
|
130
|
+
| `initialLikeIds` | `string[]` | ❌ | `[]` | Pre-known liked post IDs (for resume) |
|
|
131
|
+
|
|
132
|
+
### Event Emitter API
|
|
133
|
+
|
|
134
|
+
```typescript
|
|
135
|
+
import { createXClient, SocialLikeWatcher } from '@hardlydifficult/social';
|
|
136
|
+
|
|
137
|
+
const client = createXClient({ bearerToken: process.env.X_BEARER_TOKEN! });
|
|
138
|
+
const watcher = new SocialLikeWatcher(client, { pollIntervalMs: 30_000 });
|
|
139
|
+
|
|
140
|
+
watcher.on('newLike', (post) => {
|
|
141
|
+
console.log(`New like detected: ${post.text}`);
|
|
142
|
+
});
|
|
143
|
+
|
|
144
|
+
watcher.on('error', (err) => {
|
|
145
|
+
console.error('Watcher error:', err);
|
|
146
|
+
});
|
|
147
|
+
|
|
148
|
+
watcher.start();
|
|
149
|
+
// Wait for likes...
|
|
150
|
+
// watcher.stop();
|
|
151
|
+
```
|
|
152
|
+
|
|
153
|
+
## Factory Functions
|
|
154
|
+
|
|
155
|
+
The package exports convenience factory functions to construct platform-specific clients:
|
|
156
|
+
|
|
157
|
+
| Function | Returns | Description |
|
|
158
|
+
|---------|---------|-------------|
|
|
159
|
+
| `createXClient(options)` | `SocialClient` | Constructs X/Twitter client with default implementation |
|
|
160
|
+
| `createMastodonClient(options)` | `never` | Currently throws "not implemented" error |
|
|
161
|
+
|
|
162
|
+
```typescript
|
|
163
|
+
import { createXClient } from '@hardlydifficult/social';
|
|
164
|
+
|
|
165
|
+
// X client
|
|
166
|
+
const xClient = createXClient({ bearerToken: '...' });
|
|
167
|
+
```
|
|
168
|
+
|
|
169
|
+
## Usage with High-Level API
|
|
170
|
+
|
|
171
|
+
For a more opinionated interface, use `createSocial`:
|
|
22
172
|
|
|
23
173
|
```typescript
|
|
24
174
|
import { createSocial } from "@hardlydifficult/social";
|
|
@@ -38,7 +188,7 @@ const watcher = social.watchLikes({
|
|
|
38
188
|
watcher.start();
|
|
39
189
|
```
|
|
40
190
|
|
|
41
|
-
|
|
191
|
+
### X configuration
|
|
42
192
|
|
|
43
193
|
Set environment variables, or pass explicit config through `createSocialClient`.
|
|
44
194
|
|
|
@@ -53,3 +203,29 @@ const social = createSocialClient({
|
|
|
53
203
|
bearerToken: process.env.X_BEARER_TOKEN,
|
|
54
204
|
});
|
|
55
205
|
```
|
|
206
|
+
|
|
207
|
+
## Testing
|
|
208
|
+
|
|
209
|
+
Unit tests cover:
|
|
210
|
+
|
|
211
|
+
- Factory initialization
|
|
212
|
+
- Timeline retrieval via provider-agnostic interface
|
|
213
|
+
- Like watcher polling and stateful detection
|
|
214
|
+
|
|
215
|
+
Run tests with:
|
|
216
|
+
|
|
217
|
+
```bash
|
|
218
|
+
npm test
|
|
219
|
+
```
|
|
220
|
+
|
|
221
|
+
## Appendix
|
|
222
|
+
|
|
223
|
+
### Platform Support
|
|
224
|
+
|
|
225
|
+
| Feature | X (Twitter) | Mastodon |
|
|
226
|
+
|---------|-------------|----------|
|
|
227
|
+
| Timeline | ✅ | ❌ (stub) |
|
|
228
|
+
| Liked Posts | ✅ | ❌ (stub) |
|
|
229
|
+
| Like Watching | ✅ | ❌ (stub) |
|
|
230
|
+
|
|
231
|
+
Mastodon support is currently unimplemented and will throw errors on usage.
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@hardlydifficult/social",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.4",
|
|
4
4
|
"main": "./dist/index.js",
|
|
5
5
|
"types": "./dist/index.d.ts",
|
|
6
6
|
"files": [
|
|
@@ -21,7 +21,7 @@
|
|
|
21
21
|
},
|
|
22
22
|
"type": "commonjs",
|
|
23
23
|
"engines": {
|
|
24
|
-
"node": ">=
|
|
24
|
+
"node": ">=20.19.0"
|
|
25
25
|
},
|
|
26
26
|
"exports": {
|
|
27
27
|
".": {
|