@hardlydifficult/social 1.0.60 → 1.0.62
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 +47 -64
- package/dist/index.d.ts +5 -13
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +4 -18
- package/dist/index.js.map +1 -1
- package/dist/types.d.ts +18 -6
- package/dist/types.d.ts.map +1 -1
- package/dist/x/createXSocial.d.ts +4 -0
- package/dist/x/createXSocial.d.ts.map +1 -0
- package/dist/x/createXSocial.js +183 -0
- package/dist/x/createXSocial.js.map +1 -0
- package/package.json +2 -2
- package/dist/SocialClient.d.ts +0 -22
- package/dist/SocialClient.d.ts.map +0 -1
- package/dist/SocialClient.js +0 -51
- package/dist/SocialClient.js.map +0 -1
- package/dist/SocialLikeWatcher.d.ts +0 -20
- package/dist/SocialLikeWatcher.d.ts.map +0 -1
- package/dist/SocialLikeWatcher.js +0 -81
- package/dist/SocialLikeWatcher.js.map +0 -1
- package/dist/SocialProviderClient.d.ts +0 -7
- package/dist/SocialProviderClient.d.ts.map +0 -1
- package/dist/SocialProviderClient.js +0 -3
- package/dist/SocialProviderClient.js.map +0 -1
- package/dist/mastodon/MastodonSocialClient.d.ts +0 -15
- package/dist/mastodon/MastodonSocialClient.d.ts.map +0 -1
- package/dist/mastodon/MastodonSocialClient.js +0 -29
- package/dist/mastodon/MastodonSocialClient.js.map +0 -1
- package/dist/x/XSocialClient.d.ts +0 -23
- package/dist/x/XSocialClient.d.ts.map +0 -1
- package/dist/x/XSocialClient.js +0 -104
- package/dist/x/XSocialClient.js.map +0 -1
- package/dist/x/index.d.ts +0 -2
- package/dist/x/index.d.ts.map +0 -1
- package/dist/x/index.js +0 -6
- package/dist/x/index.js.map +0 -1
package/README.md
CHANGED
|
@@ -4,10 +4,10 @@ Opinionated social read client for X.
|
|
|
4
4
|
|
|
5
5
|
This package is intentionally narrow:
|
|
6
6
|
|
|
7
|
-
- One provider: X
|
|
8
7
|
- One factory: `createSocial()`
|
|
9
|
-
-
|
|
10
|
-
-
|
|
8
|
+
- One authenticated account: `me`
|
|
9
|
+
- Small resource tree: `posts.get()`, `me.timeline()`, `me.likes()`
|
|
10
|
+
- Like watching as an async stream
|
|
11
11
|
|
|
12
12
|
## Installation
|
|
13
13
|
|
|
@@ -21,127 +21,110 @@ npm install @hardlydifficult/social
|
|
|
21
21
|
import { createSocial } from "@hardlydifficult/social";
|
|
22
22
|
|
|
23
23
|
const social = createSocial({
|
|
24
|
-
|
|
24
|
+
token: process.env.X_BEARER_TOKEN,
|
|
25
25
|
});
|
|
26
26
|
|
|
27
|
-
const
|
|
28
|
-
const liked = await social.likes(
|
|
29
|
-
const post = await social.
|
|
27
|
+
const timeline = await social.me.timeline({ limit: 10 });
|
|
28
|
+
const liked = await social.me.likes();
|
|
29
|
+
const post = await social.posts.get("1234567890");
|
|
30
30
|
```
|
|
31
31
|
|
|
32
|
-
If you omit `
|
|
32
|
+
If you omit `token`, the client reads `X_BEARER_TOKEN` from the environment.
|
|
33
|
+
`bearerToken` is accepted as a compatibility alias.
|
|
33
34
|
|
|
34
35
|
## API
|
|
35
36
|
|
|
36
37
|
### `createSocial(options?)`
|
|
37
38
|
|
|
38
|
-
Creates the
|
|
39
|
+
Creates the social client.
|
|
39
40
|
|
|
40
41
|
```ts
|
|
41
42
|
const social = createSocial({
|
|
42
|
-
|
|
43
|
-
|
|
43
|
+
token: process.env.X_BEARER_TOKEN,
|
|
44
|
+
defaultLimit: 25,
|
|
44
45
|
});
|
|
45
46
|
```
|
|
46
47
|
|
|
47
48
|
Options:
|
|
48
49
|
|
|
50
|
+
- `token?: string`
|
|
49
51
|
- `bearerToken?: string`
|
|
52
|
+
- `defaultLimit?: number`
|
|
50
53
|
- `limit?: number`
|
|
54
|
+
- `maxResults?: number`
|
|
55
|
+
- `type?: "x"`
|
|
51
56
|
|
|
52
|
-
`maxResults`
|
|
57
|
+
`bearerToken`, `limit`, and `maxResults` are accepted as compatibility aliases.
|
|
58
|
+
`type` is optional because X is the only supported provider.
|
|
53
59
|
|
|
54
|
-
### `social.
|
|
60
|
+
### `social.posts.get(id)`
|
|
55
61
|
|
|
56
62
|
Fetch a single post.
|
|
57
63
|
|
|
58
64
|
```ts
|
|
59
|
-
const post = await social.
|
|
65
|
+
const post = await social.posts.get("123");
|
|
60
66
|
```
|
|
61
67
|
|
|
62
|
-
### `social.timeline(
|
|
68
|
+
### `social.me.timeline(options?)`
|
|
63
69
|
|
|
64
70
|
Fetch the authenticated user timeline.
|
|
65
71
|
|
|
66
72
|
```ts
|
|
67
|
-
const recent = await social.timeline();
|
|
68
|
-
const firstTen = await social.timeline(10);
|
|
69
|
-
const custom = await social.timeline({ limit: 5 });
|
|
73
|
+
const recent = await social.me.timeline();
|
|
74
|
+
const firstTen = await social.me.timeline({ limit: 10 });
|
|
70
75
|
```
|
|
71
76
|
|
|
72
|
-
### `social.likes(
|
|
77
|
+
### `social.me.likes(options?)`
|
|
73
78
|
|
|
74
79
|
Fetch posts liked by the authenticated user.
|
|
75
80
|
|
|
76
81
|
```ts
|
|
77
|
-
const liked = await social.likes();
|
|
78
|
-
const latestLiked = await social.likes(20);
|
|
82
|
+
const liked = await social.me.likes();
|
|
83
|
+
const latestLiked = await social.me.likes({ limit: 20 });
|
|
79
84
|
```
|
|
80
85
|
|
|
81
|
-
### `social.watchLikes(
|
|
86
|
+
### `social.me.watchLikes(options?)`
|
|
82
87
|
|
|
83
|
-
|
|
88
|
+
Returns an async stream of newly liked posts. The first poll seeds the current
|
|
89
|
+
likes and emits nothing, so iteration only yields likes discovered after the
|
|
90
|
+
stream starts.
|
|
84
91
|
|
|
85
92
|
```ts
|
|
86
|
-
const
|
|
87
|
-
({ post, seenAt }) => {
|
|
88
|
-
console.log(`[${seenAt}] ${post.url}`);
|
|
89
|
-
},
|
|
90
|
-
{ everyMs: 30_000 }
|
|
91
|
-
);
|
|
92
|
-
|
|
93
|
-
// later
|
|
94
|
-
watcher.stop();
|
|
95
|
-
```
|
|
96
|
-
|
|
97
|
-
Options:
|
|
98
|
-
|
|
99
|
-
- `everyMs?: number`
|
|
100
|
-
- `onError?: (error: Error) => void`
|
|
101
|
-
|
|
102
|
-
You can also use the object form if you prefer:
|
|
93
|
+
const controller = new AbortController();
|
|
103
94
|
|
|
104
|
-
|
|
105
|
-
const watcher = social.watchLikes({
|
|
95
|
+
for await (const like of social.me.watchLikes({
|
|
106
96
|
everyMs: 30_000,
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
}
|
|
110
|
-
}
|
|
97
|
+
signal: controller.signal,
|
|
98
|
+
})) {
|
|
99
|
+
console.log(`[${like.seenAt}] ${like.post.url}`);
|
|
100
|
+
}
|
|
111
101
|
```
|
|
112
102
|
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
`watchLikes()` returns a `SocialLikeWatcher`.
|
|
116
|
-
|
|
117
|
-
Methods:
|
|
103
|
+
Options:
|
|
118
104
|
|
|
119
|
-
- `
|
|
120
|
-
- `
|
|
121
|
-
- `
|
|
105
|
+
- `everyMs?: number`
|
|
106
|
+
- `pollIntervalMs?: number`
|
|
107
|
+
- `signal?: AbortSignal`
|
|
122
108
|
|
|
123
|
-
|
|
109
|
+
`pollIntervalMs` is accepted as a compatibility alias for `everyMs`.
|
|
124
110
|
|
|
125
111
|
## Types
|
|
126
112
|
|
|
127
113
|
Core types exported by the package:
|
|
128
114
|
|
|
115
|
+
- `CreateSocialOptions`
|
|
116
|
+
- `Provider`
|
|
117
|
+
- `XConfig`
|
|
129
118
|
- `SocialOptions`
|
|
119
|
+
- `SocialConfig`
|
|
120
|
+
- `Social`
|
|
130
121
|
- `SocialListOptions`
|
|
131
122
|
- `SocialPost`
|
|
132
123
|
- `SocialAuthor`
|
|
133
124
|
- `SocialPostMetrics`
|
|
134
125
|
- `LikeNotification`
|
|
135
126
|
- `WatchLikesOptions`
|
|
136
|
-
|
|
137
|
-
## Compatibility Aliases
|
|
138
|
-
|
|
139
|
-
These still exist, but they are no longer the preferred style:
|
|
140
|
-
|
|
141
|
-
- `createSocialClient()` delegates to `createSocial()`
|
|
142
|
-
- `client.getPost()` delegates to `client.post()`
|
|
143
|
-
- `client.likedPosts()` delegates to `client.likes()`
|
|
144
|
-
- `pollIntervalMs` is accepted as an alias for `everyMs`
|
|
127
|
+
- `LikeWatcherOptions`
|
|
145
128
|
|
|
146
129
|
## Scope
|
|
147
130
|
|
package/dist/index.d.ts
CHANGED
|
@@ -1,16 +1,8 @@
|
|
|
1
|
-
export type { Provider,
|
|
2
|
-
|
|
3
|
-
export { SocialLikeWatcher, type SocialLikeWatcherOptions, } from "./SocialLikeWatcher.js";
|
|
4
|
-
import { SocialClient } from "./SocialClient.js";
|
|
5
|
-
import type { SocialOptions } from "./types.js";
|
|
1
|
+
export type { CreateSocialOptions, LikeNotification, LikeWatcherOptions, Provider, Social, SocialAuthor, SocialConfig, SocialListOptions, SocialOptions, SocialPost, SocialPostMetrics, WatchLikesOptions, XConfig, } from "./types.js";
|
|
2
|
+
import type { CreateSocialOptions, Social } from "./types.js";
|
|
6
3
|
/**
|
|
7
|
-
* Create the opinionated social client. X is the only provider
|
|
8
|
-
*
|
|
9
|
-
* X_BEARER_TOKEN from the environment.
|
|
4
|
+
* Create the opinionated social client. X is the only supported provider and
|
|
5
|
+
* token lookup falls back to X_BEARER_TOKEN automatically.
|
|
10
6
|
*/
|
|
11
|
-
export declare function createSocial(config?:
|
|
12
|
-
/**
|
|
13
|
-
* Backwards-compatible alias for older call sites.
|
|
14
|
-
*/
|
|
15
|
-
export declare function createSocialClient(config?: SocialOptions): SocialClient;
|
|
7
|
+
export declare function createSocial(config?: CreateSocialOptions): Social;
|
|
16
8
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,YAAY,EACV,QAAQ,EACR,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,YAAY,EACV,mBAAmB,EACnB,gBAAgB,EAChB,kBAAkB,EAClB,QAAQ,EACR,MAAM,EACN,YAAY,EACZ,YAAY,EACZ,iBAAiB,EACjB,aAAa,EACb,UAAU,EACV,iBAAiB,EACjB,iBAAiB,EACjB,OAAO,GACR,MAAM,YAAY,CAAC;AAEpB,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,EAAE,MAAM,YAAY,CAAC;AAG9D;;;GAGG;AACH,wBAAgB,YAAY,CAAC,MAAM,GAAE,mBAAwB,GAAG,MAAM,CAErE"}
|
package/dist/index.js
CHANGED
|
@@ -1,26 +1,12 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.SocialLikeWatcher = exports.SocialClient = void 0;
|
|
4
3
|
exports.createSocial = createSocial;
|
|
5
|
-
|
|
6
|
-
var SocialClient_js_1 = require("./SocialClient.js");
|
|
7
|
-
Object.defineProperty(exports, "SocialClient", { enumerable: true, get: function () { return SocialClient_js_1.SocialClient; } });
|
|
8
|
-
var SocialLikeWatcher_js_1 = require("./SocialLikeWatcher.js");
|
|
9
|
-
Object.defineProperty(exports, "SocialLikeWatcher", { enumerable: true, get: function () { return SocialLikeWatcher_js_1.SocialLikeWatcher; } });
|
|
10
|
-
const SocialClient_js_2 = require("./SocialClient.js");
|
|
11
|
-
const x_1 = require("./x");
|
|
4
|
+
const createXSocial_js_1 = require("./x/createXSocial.js");
|
|
12
5
|
/**
|
|
13
|
-
* Create the opinionated social client. X is the only provider
|
|
14
|
-
*
|
|
15
|
-
* X_BEARER_TOKEN from the environment.
|
|
6
|
+
* Create the opinionated social client. X is the only supported provider and
|
|
7
|
+
* token lookup falls back to X_BEARER_TOKEN automatically.
|
|
16
8
|
*/
|
|
17
9
|
function createSocial(config = {}) {
|
|
18
|
-
return
|
|
19
|
-
}
|
|
20
|
-
/**
|
|
21
|
-
* Backwards-compatible alias for older call sites.
|
|
22
|
-
*/
|
|
23
|
-
function createSocialClient(config = {}) {
|
|
24
|
-
return createSocial(config);
|
|
10
|
+
return (0, createXSocial_js_1.createXSocial)(config);
|
|
25
11
|
}
|
|
26
12
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;AAuBA,oCAEC;AARD,2DAAqD;AAErD;;;GAGG;AACH,SAAgB,YAAY,CAAC,SAA8B,EAAE;IAC3D,OAAO,IAAA,gCAAa,EAAC,MAAM,CAAC,CAAC;AAC/B,CAAC"}
|
package/dist/types.d.ts
CHANGED
|
@@ -1,12 +1,15 @@
|
|
|
1
|
-
export
|
|
2
|
-
export interface SocialOptions {
|
|
1
|
+
export interface CreateSocialOptions {
|
|
3
2
|
readonly type?: "x";
|
|
3
|
+
readonly token?: string;
|
|
4
4
|
readonly bearerToken?: string;
|
|
5
|
+
readonly defaultLimit?: number;
|
|
5
6
|
readonly limit?: number;
|
|
6
7
|
readonly maxResults?: number;
|
|
7
8
|
}
|
|
8
|
-
export type
|
|
9
|
-
export type
|
|
9
|
+
export type Provider = "x";
|
|
10
|
+
export type SocialOptions = CreateSocialOptions;
|
|
11
|
+
export type XConfig = CreateSocialOptions;
|
|
12
|
+
export type SocialConfig = CreateSocialOptions;
|
|
10
13
|
export interface SocialListOptions {
|
|
11
14
|
readonly limit?: number;
|
|
12
15
|
}
|
|
@@ -35,8 +38,17 @@ export interface LikeNotification {
|
|
|
35
38
|
export interface WatchLikesOptions {
|
|
36
39
|
readonly everyMs?: number;
|
|
37
40
|
readonly pollIntervalMs?: number;
|
|
38
|
-
readonly
|
|
39
|
-
|
|
41
|
+
readonly signal?: AbortSignal;
|
|
42
|
+
}
|
|
43
|
+
export interface Social {
|
|
44
|
+
readonly posts: {
|
|
45
|
+
get(postId: string): Promise<SocialPost | null>;
|
|
46
|
+
};
|
|
47
|
+
readonly me: {
|
|
48
|
+
timeline(options?: SocialListOptions): Promise<readonly SocialPost[]>;
|
|
49
|
+
likes(options?: SocialListOptions): Promise<readonly SocialPost[]>;
|
|
50
|
+
watchLikes(options?: WatchLikesOptions): AsyncIterable<LikeNotification>;
|
|
51
|
+
};
|
|
40
52
|
}
|
|
41
53
|
export type LikeWatcherOptions = WatchLikesOptions;
|
|
42
54
|
//# sourceMappingURL=types.d.ts.map
|
package/dist/types.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,MAAM,
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,mBAAmB;IAClC,QAAQ,CAAC,IAAI,CAAC,EAAE,GAAG,CAAC;IACpB,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,WAAW,CAAC,EAAE,MAAM,CAAC;IAC9B,QAAQ,CAAC,YAAY,CAAC,EAAE,MAAM,CAAC;IAC/B,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,UAAU,CAAC,EAAE,MAAM,CAAC;CAC9B;AAED,MAAM,MAAM,QAAQ,GAAG,GAAG,CAAC;AAC3B,MAAM,MAAM,aAAa,GAAG,mBAAmB,CAAC;AAChD,MAAM,MAAM,OAAO,GAAG,mBAAmB,CAAC;AAC1C,MAAM,MAAM,YAAY,GAAG,mBAAmB,CAAC;AAE/C,MAAM,WAAW,iBAAiB;IAChC,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,CAAC;CACzB;AAED,MAAM,WAAW,YAAY;IAC3B,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;CAC9B;AAED,MAAM,WAAW,iBAAiB;IAChC,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;CAC1B;AAED,MAAM,WAAW,UAAU;IACzB,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,MAAM,EAAE,YAAY,CAAC;IAC9B,QAAQ,CAAC,OAAO,EAAE,iBAAiB,CAAC;CACrC;AAED,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,CAAC,IAAI,EAAE,UAAU,CAAC;IAC1B,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;CACzB;AAED,MAAM,WAAW,iBAAiB;IAChC,QAAQ,CAAC,OAAO,CAAC,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,cAAc,CAAC,EAAE,MAAM,CAAC;IACjC,QAAQ,CAAC,MAAM,CAAC,EAAE,WAAW,CAAC;CAC/B;AAED,MAAM,WAAW,MAAM;IACrB,QAAQ,CAAC,KAAK,EAAE;QACd,GAAG,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,GAAG,IAAI,CAAC,CAAC;KACjD,CAAC;IACF,QAAQ,CAAC,EAAE,EAAE;QACX,QAAQ,CAAC,OAAO,CAAC,EAAE,iBAAiB,GAAG,OAAO,CAAC,SAAS,UAAU,EAAE,CAAC,CAAC;QACtE,KAAK,CAAC,OAAO,CAAC,EAAE,iBAAiB,GAAG,OAAO,CAAC,SAAS,UAAU,EAAE,CAAC,CAAC;QACnE,UAAU,CAAC,OAAO,CAAC,EAAE,iBAAiB,GAAG,aAAa,CAAC,gBAAgB,CAAC,CAAC;KAC1E,CAAC;CACH;AAED,MAAM,MAAM,kBAAkB,GAAG,iBAAiB,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"createXSocial.d.ts","sourceRoot":"","sources":["../../src/x/createXSocial.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EACV,mBAAmB,EAEnB,MAAM,EAIP,MAAM,aAAa,CAAC;AA8BrB,8EAA8E;AAC9E,wBAAgB,aAAa,CAAC,OAAO,GAAE,mBAAwB,GAAG,MAAM,CA8EvE"}
|
|
@@ -0,0 +1,183 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.createXSocial = createXSocial;
|
|
4
|
+
const date_time_1 = require("@hardlydifficult/date-time");
|
|
5
|
+
const DEFAULT_LIMIT = 25;
|
|
6
|
+
const DEFAULT_WATCH_INTERVAL_MS = (0, date_time_1.duration)({ minutes: 1 });
|
|
7
|
+
/** Creates the X-backed social read client with token and limit fallbacks. */
|
|
8
|
+
function createXSocial(options = {}) {
|
|
9
|
+
const token = options.token ?? options.bearerToken ?? process.env.X_BEARER_TOKEN ?? "";
|
|
10
|
+
const defaultLimit = options.defaultLimit ??
|
|
11
|
+
options.limit ??
|
|
12
|
+
options.maxResults ??
|
|
13
|
+
DEFAULT_LIMIT;
|
|
14
|
+
if (token.length === 0) {
|
|
15
|
+
throw new Error("X bearer token is required. Set X_BEARER_TOKEN.");
|
|
16
|
+
}
|
|
17
|
+
async function request(path) {
|
|
18
|
+
const response = await fetch(`https://api.x.com/2${path}`, {
|
|
19
|
+
headers: {
|
|
20
|
+
Authorization: `Bearer ${token}`,
|
|
21
|
+
"Content-Type": "application/json",
|
|
22
|
+
},
|
|
23
|
+
});
|
|
24
|
+
if (!response.ok) {
|
|
25
|
+
const status = String(response.status);
|
|
26
|
+
throw new Error(`X API request failed: ${status} ${response.statusText}`);
|
|
27
|
+
}
|
|
28
|
+
return (await response.json());
|
|
29
|
+
}
|
|
30
|
+
async function getPost(postId) {
|
|
31
|
+
const response = await request(`/tweets/${postId}${buildPostQuery()}`);
|
|
32
|
+
const tweet = readSingleTweet(response.data);
|
|
33
|
+
if (!tweet) {
|
|
34
|
+
return null;
|
|
35
|
+
}
|
|
36
|
+
return normalizeTweet(tweet, response.includes?.users ?? []);
|
|
37
|
+
}
|
|
38
|
+
async function listTimeline(options) {
|
|
39
|
+
const response = await request(`/users/me/timelines/reverse_chronological${buildListQuery(resolveLimit(options, defaultLimit))}`);
|
|
40
|
+
return normalizeTweets(response);
|
|
41
|
+
}
|
|
42
|
+
async function listLikes(options) {
|
|
43
|
+
const response = await request(`/users/me/liked_tweets${buildListQuery(resolveLimit(options, defaultLimit))}`);
|
|
44
|
+
return normalizeTweets(response);
|
|
45
|
+
}
|
|
46
|
+
return {
|
|
47
|
+
posts: {
|
|
48
|
+
get: getPost,
|
|
49
|
+
},
|
|
50
|
+
me: {
|
|
51
|
+
timeline: listTimeline,
|
|
52
|
+
likes: listLikes,
|
|
53
|
+
watchLikes(watchOptions = {}) {
|
|
54
|
+
return watchLikesStream({
|
|
55
|
+
everyMs: watchOptions.everyMs ??
|
|
56
|
+
watchOptions.pollIntervalMs ??
|
|
57
|
+
DEFAULT_WATCH_INTERVAL_MS,
|
|
58
|
+
signal: watchOptions.signal,
|
|
59
|
+
listLikes,
|
|
60
|
+
});
|
|
61
|
+
},
|
|
62
|
+
},
|
|
63
|
+
};
|
|
64
|
+
}
|
|
65
|
+
function resolveLimit(options, defaultLimit) {
|
|
66
|
+
return options?.limit ?? defaultLimit;
|
|
67
|
+
}
|
|
68
|
+
function buildPostQuery() {
|
|
69
|
+
const params = new URLSearchParams({
|
|
70
|
+
expansions: "author_id",
|
|
71
|
+
"tweet.fields": "created_at,public_metrics",
|
|
72
|
+
"user.fields": "name,username",
|
|
73
|
+
});
|
|
74
|
+
return `?${params.toString()}`;
|
|
75
|
+
}
|
|
76
|
+
function buildListQuery(limit) {
|
|
77
|
+
const params = new URLSearchParams({
|
|
78
|
+
expansions: "author_id",
|
|
79
|
+
"tweet.fields": "created_at,public_metrics",
|
|
80
|
+
"user.fields": "name,username",
|
|
81
|
+
max_results: String(limit),
|
|
82
|
+
});
|
|
83
|
+
return `?${params.toString()}`;
|
|
84
|
+
}
|
|
85
|
+
function normalizeTweets(response) {
|
|
86
|
+
return readTweetList(response.data).map((tweet) => normalizeTweet(tweet, response.includes?.users ?? []));
|
|
87
|
+
}
|
|
88
|
+
function readSingleTweet(data) {
|
|
89
|
+
if (!isTweet(data)) {
|
|
90
|
+
return null;
|
|
91
|
+
}
|
|
92
|
+
return data;
|
|
93
|
+
}
|
|
94
|
+
function readTweetList(data) {
|
|
95
|
+
if (!Array.isArray(data)) {
|
|
96
|
+
return [];
|
|
97
|
+
}
|
|
98
|
+
return data.filter((item) => isTweet(item));
|
|
99
|
+
}
|
|
100
|
+
function isTweet(value) {
|
|
101
|
+
if (typeof value !== "object" || value === null) {
|
|
102
|
+
return false;
|
|
103
|
+
}
|
|
104
|
+
const candidate = value;
|
|
105
|
+
return typeof candidate.id === "string" && typeof candidate.text === "string";
|
|
106
|
+
}
|
|
107
|
+
function normalizeTweet(tweet, users) {
|
|
108
|
+
const author = users.find((user) => user.id === tweet.author_id);
|
|
109
|
+
return {
|
|
110
|
+
id: tweet.id,
|
|
111
|
+
text: tweet.text,
|
|
112
|
+
createdAt: tweet.created_at ?? new Date(0).toISOString(),
|
|
113
|
+
url: `https://x.com/${author?.username ?? "i"}/status/${tweet.id}`,
|
|
114
|
+
author: {
|
|
115
|
+
id: author?.id ?? tweet.author_id ?? "unknown",
|
|
116
|
+
username: author?.username ?? "unknown",
|
|
117
|
+
displayName: author?.name ?? author?.username ?? "Unknown",
|
|
118
|
+
},
|
|
119
|
+
metrics: {
|
|
120
|
+
likes: tweet.public_metrics?.like_count ?? 0,
|
|
121
|
+
replies: tweet.public_metrics?.reply_count ?? 0,
|
|
122
|
+
reposts: tweet.public_metrics?.retweet_count ?? 0,
|
|
123
|
+
},
|
|
124
|
+
};
|
|
125
|
+
}
|
|
126
|
+
async function* watchLikesStream({ everyMs, signal, listLikes, }) {
|
|
127
|
+
const knownLikeIds = new Set();
|
|
128
|
+
let seeded = false;
|
|
129
|
+
while (signal?.aborted !== true) {
|
|
130
|
+
const liked = await listLikes();
|
|
131
|
+
const seenAt = new Date().toISOString();
|
|
132
|
+
if (!seeded) {
|
|
133
|
+
for (const post of liked) {
|
|
134
|
+
knownLikeIds.add(post.id);
|
|
135
|
+
}
|
|
136
|
+
seeded = true;
|
|
137
|
+
}
|
|
138
|
+
else {
|
|
139
|
+
const notifications = [];
|
|
140
|
+
for (const post of liked) {
|
|
141
|
+
if (!knownLikeIds.has(post.id)) {
|
|
142
|
+
knownLikeIds.add(post.id);
|
|
143
|
+
notifications.push({ post, seenAt });
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
for (const notification of notifications.reverse()) {
|
|
147
|
+
yield notification;
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
if (!(await sleep(everyMs, signal))) {
|
|
151
|
+
return;
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
function sleep(ms, signal) {
|
|
156
|
+
if (signal?.aborted === true) {
|
|
157
|
+
return Promise.resolve(false);
|
|
158
|
+
}
|
|
159
|
+
if (signal === undefined) {
|
|
160
|
+
return new Promise((resolve) => {
|
|
161
|
+
const timer = setTimeout(() => {
|
|
162
|
+
resolve(true);
|
|
163
|
+
}, ms);
|
|
164
|
+
timer.unref();
|
|
165
|
+
});
|
|
166
|
+
}
|
|
167
|
+
const abortSignal = signal;
|
|
168
|
+
return new Promise((resolve) => {
|
|
169
|
+
const timer = setTimeout(onTimeout, ms);
|
|
170
|
+
timer.unref();
|
|
171
|
+
abortSignal.addEventListener("abort", onAbort, { once: true });
|
|
172
|
+
function onTimeout() {
|
|
173
|
+
abortSignal.removeEventListener("abort", onAbort);
|
|
174
|
+
resolve(true);
|
|
175
|
+
}
|
|
176
|
+
function onAbort() {
|
|
177
|
+
clearTimeout(timer);
|
|
178
|
+
abortSignal.removeEventListener("abort", onAbort);
|
|
179
|
+
resolve(false);
|
|
180
|
+
}
|
|
181
|
+
});
|
|
182
|
+
}
|
|
183
|
+
//# sourceMappingURL=createXSocial.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"createXSocial.js","sourceRoot":"","sources":["../../src/x/createXSocial.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@hardlydifficult/social",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.62",
|
|
4
4
|
"main": "./dist/index.js",
|
|
5
5
|
"types": "./dist/index.d.ts",
|
|
6
6
|
"files": [
|
|
@@ -33,6 +33,6 @@
|
|
|
33
33
|
}
|
|
34
34
|
},
|
|
35
35
|
"dependencies": {
|
|
36
|
-
"@hardlydifficult/date-time": "1.0.
|
|
36
|
+
"@hardlydifficult/date-time": "1.0.25"
|
|
37
37
|
}
|
|
38
38
|
}
|
package/dist/SocialClient.d.ts
DELETED
|
@@ -1,22 +0,0 @@
|
|
|
1
|
-
import { SocialLikeWatcher, type SocialLikeWatcherOptions } from "./SocialLikeWatcher.js";
|
|
2
|
-
import type { SocialProviderClient } from "./SocialProviderClient.js";
|
|
3
|
-
import type { LikeNotification, SocialListOptions, SocialPost } from "./types.js";
|
|
4
|
-
type SocialListInput = number | SocialListOptions | {
|
|
5
|
-
readonly maxResults?: number;
|
|
6
|
-
};
|
|
7
|
-
/**
|
|
8
|
-
*
|
|
9
|
-
*/
|
|
10
|
-
export declare class SocialClient {
|
|
11
|
-
private readonly provider;
|
|
12
|
-
constructor(provider: SocialProviderClient);
|
|
13
|
-
post(postId: string): Promise<SocialPost | null>;
|
|
14
|
-
getPost(postId: string): Promise<SocialPost | null>;
|
|
15
|
-
timeline(options?: SocialListInput): Promise<readonly SocialPost[]>;
|
|
16
|
-
likes(options?: SocialListInput): Promise<readonly SocialPost[]>;
|
|
17
|
-
likedPosts(options?: SocialListInput): Promise<readonly SocialPost[]>;
|
|
18
|
-
watchLikes(options: SocialLikeWatcherOptions): SocialLikeWatcher;
|
|
19
|
-
watchLikes(onLike: (notification: LikeNotification) => void, options?: Omit<SocialLikeWatcherOptions, "onLike">): SocialLikeWatcher;
|
|
20
|
-
}
|
|
21
|
-
export {};
|
|
22
|
-
//# sourceMappingURL=SocialClient.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"SocialClient.d.ts","sourceRoot":"","sources":["../src/SocialClient.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,iBAAiB,EACjB,KAAK,wBAAwB,EAC9B,MAAM,wBAAwB,CAAC;AAChC,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,2BAA2B,CAAC;AACtE,OAAO,KAAK,EACV,gBAAgB,EAChB,iBAAiB,EACjB,UAAU,EACX,MAAM,YAAY,CAAC;AAEpB,KAAK,eAAe,GAChB,MAAM,GACN,iBAAiB,GACjB;IACE,QAAQ,CAAC,UAAU,CAAC,EAAE,MAAM,CAAC;CAC9B,CAAC;AAwBN;;GAEG;AACH,qBAAa,YAAY;IACX,OAAO,CAAC,QAAQ,CAAC,QAAQ;gBAAR,QAAQ,EAAE,oBAAoB;IAE3D,IAAI,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,GAAG,IAAI,CAAC;IAIhD,OAAO,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,GAAG,IAAI,CAAC;IAInD,QAAQ,CAAC,OAAO,CAAC,EAAE,eAAe,GAAG,OAAO,CAAC,SAAS,UAAU,EAAE,CAAC;IAInE,KAAK,CAAC,OAAO,CAAC,EAAE,eAAe,GAAG,OAAO,CAAC,SAAS,UAAU,EAAE,CAAC;IAIhE,UAAU,CAAC,OAAO,CAAC,EAAE,eAAe,GAAG,OAAO,CAAC,SAAS,UAAU,EAAE,CAAC;IAIrE,UAAU,CAAC,OAAO,EAAE,wBAAwB,GAAG,iBAAiB;IAChE,UAAU,CACR,MAAM,EAAE,CAAC,YAAY,EAAE,gBAAgB,KAAK,IAAI,EAChD,OAAO,CAAC,EAAE,IAAI,CAAC,wBAAwB,EAAE,QAAQ,CAAC,GACjD,iBAAiB;CAerB"}
|
package/dist/SocialClient.js
DELETED
|
@@ -1,51 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.SocialClient = void 0;
|
|
4
|
-
const SocialLikeWatcher_js_1 = require("./SocialLikeWatcher.js");
|
|
5
|
-
function normalizeListOptions(options) {
|
|
6
|
-
if (typeof options === "number") {
|
|
7
|
-
return { limit: options };
|
|
8
|
-
}
|
|
9
|
-
if (!options) {
|
|
10
|
-
return undefined;
|
|
11
|
-
}
|
|
12
|
-
return {
|
|
13
|
-
limit: ("limit" in options ? options.limit : undefined) ??
|
|
14
|
-
("maxResults" in options ? options.maxResults : undefined),
|
|
15
|
-
};
|
|
16
|
-
}
|
|
17
|
-
/**
|
|
18
|
-
*
|
|
19
|
-
*/
|
|
20
|
-
class SocialClient {
|
|
21
|
-
provider;
|
|
22
|
-
constructor(provider) {
|
|
23
|
-
this.provider = provider;
|
|
24
|
-
}
|
|
25
|
-
post(postId) {
|
|
26
|
-
return this.provider.post(postId);
|
|
27
|
-
}
|
|
28
|
-
getPost(postId) {
|
|
29
|
-
return this.post(postId);
|
|
30
|
-
}
|
|
31
|
-
timeline(options) {
|
|
32
|
-
return this.provider.timeline(normalizeListOptions(options));
|
|
33
|
-
}
|
|
34
|
-
likes(options) {
|
|
35
|
-
return this.provider.likes(normalizeListOptions(options));
|
|
36
|
-
}
|
|
37
|
-
likedPosts(options) {
|
|
38
|
-
return this.likes(options);
|
|
39
|
-
}
|
|
40
|
-
watchLikes(optionsOrHandler, options) {
|
|
41
|
-
const watcherOptions = typeof optionsOrHandler === "function"
|
|
42
|
-
? {
|
|
43
|
-
...options,
|
|
44
|
-
onLike: optionsOrHandler,
|
|
45
|
-
}
|
|
46
|
-
: optionsOrHandler;
|
|
47
|
-
return SocialLikeWatcher_js_1.SocialLikeWatcher.create(this.provider, watcherOptions).start();
|
|
48
|
-
}
|
|
49
|
-
}
|
|
50
|
-
exports.SocialClient = SocialClient;
|
|
51
|
-
//# sourceMappingURL=SocialClient.js.map
|
package/dist/SocialClient.js.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"SocialClient.js","sourceRoot":"","sources":["../src/SocialClient.ts"],"names":[],"mappings":";;;AAAA,iEAGgC;AAmBhC,SAAS,oBAAoB,CAC3B,OAAyB;IAEzB,IAAI,OAAO,OAAO,KAAK,QAAQ,EAAE,CAAC;QAChC,OAAO,EAAE,KAAK,EAAE,OAAO,EAAE,CAAC;IAC5B,CAAC;IAED,IAAI,CAAC,OAAO,EAAE,CAAC;QACb,OAAO,SAAS,CAAC;IACnB,CAAC;IAED,OAAO;QACL,KAAK,EACH,CAAC,OAAO,IAAI,OAAO,CAAC,CAAC,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC,SAAS,CAAC;YAChD,CAAC,YAAY,IAAI,OAAO,CAAC,CAAC,CAAC,OAAO,CAAC,UAAU,CAAC,CAAC,CAAC,SAAS,CAAC;KAC7D,CAAC;AACJ,CAAC;AAED;;GAEG;AACH,MAAa,YAAY;IACM;IAA7B,YAA6B,QAA8B;QAA9B,aAAQ,GAAR,QAAQ,CAAsB;IAAG,CAAC;IAE/D,IAAI,CAAC,MAAc;QACjB,OAAO,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;IACpC,CAAC;IAED,OAAO,CAAC,MAAc;QACpB,OAAO,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;IAC3B,CAAC;IAED,QAAQ,CAAC,OAAyB;QAChC,OAAO,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,oBAAoB,CAAC,OAAO,CAAC,CAAC,CAAC;IAC/D,CAAC;IAED,KAAK,CAAC,OAAyB;QAC7B,OAAO,IAAI,CAAC,QAAQ,CAAC,KAAK,CAAC,oBAAoB,CAAC,OAAO,CAAC,CAAC,CAAC;IAC5D,CAAC;IAED,UAAU,CAAC,OAAyB;QAClC,OAAO,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;IAC7B,CAAC;IAOD,UAAU,CACR,gBAAiC,EACjC,OAAkD;QAElD,MAAM,cAAc,GAClB,OAAO,gBAAgB,KAAK,UAAU;YACpC,CAAC,CAAC;gBACE,GAAG,OAAO;gBACV,MAAM,EAAE,gBAAgB;aACzB;YACH,CAAC,CAAC,gBAAgB,CAAC;QAEvB,OAAO,wCAAiB,CAAC,MAAM,CAAC,IAAI,CAAC,QAAQ,EAAE,cAAc,CAAC,CAAC,KAAK,EAAE,CAAC;IACzE,CAAC;CACF;AA1CD,oCA0CC"}
|
|
@@ -1,20 +0,0 @@
|
|
|
1
|
-
import type { SocialProviderClient } from "./SocialProviderClient.js";
|
|
2
|
-
import type { WatchLikesOptions } from "./types.js";
|
|
3
|
-
export type SocialLikeWatcherOptions = WatchLikesOptions;
|
|
4
|
-
/**
|
|
5
|
-
*
|
|
6
|
-
*/
|
|
7
|
-
export declare class SocialLikeWatcher {
|
|
8
|
-
private readonly provider;
|
|
9
|
-
private readonly options;
|
|
10
|
-
private timer;
|
|
11
|
-
private polling;
|
|
12
|
-
private seeded;
|
|
13
|
-
private readonly knownLikeIds;
|
|
14
|
-
constructor(provider: SocialProviderClient, options: Required<Pick<WatchLikesOptions, "everyMs">> & Pick<WatchLikesOptions, "onLike" | "onError">);
|
|
15
|
-
static create(provider: SocialProviderClient, options: WatchLikesOptions): SocialLikeWatcher;
|
|
16
|
-
start(): this;
|
|
17
|
-
stop(): void;
|
|
18
|
-
poll(): Promise<void>;
|
|
19
|
-
}
|
|
20
|
-
//# sourceMappingURL=SocialLikeWatcher.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"SocialLikeWatcher.d.ts","sourceRoot":"","sources":["../src/SocialLikeWatcher.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,2BAA2B,CAAC;AACtE,OAAO,KAAK,EAAoB,iBAAiB,EAAE,MAAM,YAAY,CAAC;AAEtE,MAAM,MAAM,wBAAwB,GAAG,iBAAiB,CAAC;AAEzD;;GAEG;AACH,qBAAa,iBAAiB;IAO1B,OAAO,CAAC,QAAQ,CAAC,QAAQ;IACzB,OAAO,CAAC,QAAQ,CAAC,OAAO;IAP1B,OAAO,CAAC,KAAK,CAA+C;IAC5D,OAAO,CAAC,OAAO,CAAS;IACxB,OAAO,CAAC,MAAM,CAAS;IACvB,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAqB;gBAG/B,QAAQ,EAAE,oBAAoB,EAC9B,OAAO,EAAE,QAAQ,CAAC,IAAI,CAAC,iBAAiB,EAAE,SAAS,CAAC,CAAC,GACpE,IAAI,CAAC,iBAAiB,EAAE,QAAQ,GAAG,SAAS,CAAC;IAGjD,MAAM,CAAC,MAAM,CACX,QAAQ,EAAE,oBAAoB,EAC9B,OAAO,EAAE,iBAAiB,GACzB,iBAAiB;IAQpB,KAAK,IAAI,IAAI;IAWb,IAAI,IAAI,IAAI;IAON,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;CA6C5B"}
|
|
@@ -1,81 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.SocialLikeWatcher = void 0;
|
|
4
|
-
const date_time_1 = require("@hardlydifficult/date-time");
|
|
5
|
-
/**
|
|
6
|
-
*
|
|
7
|
-
*/
|
|
8
|
-
class SocialLikeWatcher {
|
|
9
|
-
provider;
|
|
10
|
-
options;
|
|
11
|
-
timer = null;
|
|
12
|
-
polling = false;
|
|
13
|
-
seeded = false;
|
|
14
|
-
knownLikeIds = new Set();
|
|
15
|
-
constructor(provider, options) {
|
|
16
|
-
this.provider = provider;
|
|
17
|
-
this.options = options;
|
|
18
|
-
}
|
|
19
|
-
static create(provider, options) {
|
|
20
|
-
return new SocialLikeWatcher(provider, {
|
|
21
|
-
...options,
|
|
22
|
-
everyMs: options.everyMs ?? options.pollIntervalMs ?? date_time_1.MILLISECONDS_PER_MINUTE,
|
|
23
|
-
});
|
|
24
|
-
}
|
|
25
|
-
start() {
|
|
26
|
-
if (this.timer !== null) {
|
|
27
|
-
return this;
|
|
28
|
-
}
|
|
29
|
-
void this.poll();
|
|
30
|
-
this.timer = setInterval(() => void this.poll(), this.options.everyMs);
|
|
31
|
-
this.timer.unref();
|
|
32
|
-
return this;
|
|
33
|
-
}
|
|
34
|
-
stop() {
|
|
35
|
-
if (this.timer !== null) {
|
|
36
|
-
clearInterval(this.timer);
|
|
37
|
-
this.timer = null;
|
|
38
|
-
}
|
|
39
|
-
}
|
|
40
|
-
async poll() {
|
|
41
|
-
if (this.polling) {
|
|
42
|
-
return;
|
|
43
|
-
}
|
|
44
|
-
this.polling = true;
|
|
45
|
-
try {
|
|
46
|
-
const liked = await this.provider.likes();
|
|
47
|
-
const now = new Date().toISOString();
|
|
48
|
-
if (!this.seeded) {
|
|
49
|
-
for (const post of liked) {
|
|
50
|
-
this.knownLikeIds.add(post.id);
|
|
51
|
-
}
|
|
52
|
-
this.seeded = true;
|
|
53
|
-
return;
|
|
54
|
-
}
|
|
55
|
-
const notifications = [];
|
|
56
|
-
for (const post of liked) {
|
|
57
|
-
if (!this.knownLikeIds.has(post.id)) {
|
|
58
|
-
this.knownLikeIds.add(post.id);
|
|
59
|
-
notifications.push({ post, seenAt: now });
|
|
60
|
-
}
|
|
61
|
-
}
|
|
62
|
-
for (const notification of notifications.reverse()) {
|
|
63
|
-
this.options.onLike(notification);
|
|
64
|
-
}
|
|
65
|
-
}
|
|
66
|
-
catch (error) {
|
|
67
|
-
const normalizedError = error instanceof Error ? error : new Error(String(error));
|
|
68
|
-
if (this.options.onError) {
|
|
69
|
-
this.options.onError(normalizedError);
|
|
70
|
-
}
|
|
71
|
-
else {
|
|
72
|
-
console.error("SocialLikeWatcher: poll failed:", normalizedError.message);
|
|
73
|
-
}
|
|
74
|
-
}
|
|
75
|
-
finally {
|
|
76
|
-
this.polling = false;
|
|
77
|
-
}
|
|
78
|
-
}
|
|
79
|
-
}
|
|
80
|
-
exports.SocialLikeWatcher = SocialLikeWatcher;
|
|
81
|
-
//# sourceMappingURL=SocialLikeWatcher.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"SocialLikeWatcher.js","sourceRoot":"","sources":["../src/SocialLikeWatcher.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,7 +0,0 @@
|
|
|
1
|
-
import type { SocialListOptions, SocialPost } from "./types.js";
|
|
2
|
-
export interface SocialProviderClient {
|
|
3
|
-
post(postId: string): Promise<SocialPost | null>;
|
|
4
|
-
timeline(options?: SocialListOptions): Promise<readonly SocialPost[]>;
|
|
5
|
-
likes(options?: SocialListOptions): Promise<readonly SocialPost[]>;
|
|
6
|
-
}
|
|
7
|
-
//# sourceMappingURL=SocialProviderClient.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"SocialProviderClient.d.ts","sourceRoot":"","sources":["../src/SocialProviderClient.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,iBAAiB,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAEhE,MAAM,WAAW,oBAAoB;IACnC,IAAI,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,GAAG,IAAI,CAAC,CAAC;IACjD,QAAQ,CAAC,OAAO,CAAC,EAAE,iBAAiB,GAAG,OAAO,CAAC,SAAS,UAAU,EAAE,CAAC,CAAC;IACtE,KAAK,CAAC,OAAO,CAAC,EAAE,iBAAiB,GAAG,OAAO,CAAC,SAAS,UAAU,EAAE,CAAC,CAAC;CACpE"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"SocialProviderClient.js","sourceRoot":"","sources":["../src/SocialProviderClient.ts"],"names":[],"mappings":""}
|
|
@@ -1,15 +0,0 @@
|
|
|
1
|
-
import type { SocialProviderClient } from "../SocialProviderClient.js";
|
|
2
|
-
import type { SocialListOptions, SocialPost } from "../types.js";
|
|
3
|
-
/**
|
|
4
|
-
*
|
|
5
|
-
*/
|
|
6
|
-
export declare class MastodonSocialClient implements SocialProviderClient {
|
|
7
|
-
private readonly message;
|
|
8
|
-
post(_postId: string): Promise<SocialPost | null>;
|
|
9
|
-
getPost(postId: string): Promise<SocialPost | null>;
|
|
10
|
-
timeline(_options?: SocialListOptions): Promise<readonly SocialPost[]>;
|
|
11
|
-
getTimeline(options?: SocialListOptions): Promise<readonly SocialPost[]>;
|
|
12
|
-
likes(_options?: SocialListOptions): Promise<readonly SocialPost[]>;
|
|
13
|
-
getLikedPosts(options?: SocialListOptions): Promise<readonly SocialPost[]>;
|
|
14
|
-
}
|
|
15
|
-
//# sourceMappingURL=MastodonSocialClient.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"MastodonSocialClient.d.ts","sourceRoot":"","sources":["../../src/mastodon/MastodonSocialClient.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,4BAA4B,CAAC;AACvE,OAAO,KAAK,EAAE,iBAAiB,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAEjE;;GAEG;AACH,qBAAa,oBAAqB,YAAW,oBAAoB;IAC/D,OAAO,CAAC,QAAQ,CAAC,OAAO,CACiF;IAEzG,IAAI,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,GAAG,IAAI,CAAC;IAIjD,OAAO,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,GAAG,IAAI,CAAC;IAInD,QAAQ,CAAC,QAAQ,CAAC,EAAE,iBAAiB,GAAG,OAAO,CAAC,SAAS,UAAU,EAAE,CAAC;IAItE,WAAW,CAAC,OAAO,CAAC,EAAE,iBAAiB,GAAG,OAAO,CAAC,SAAS,UAAU,EAAE,CAAC;IAIxE,KAAK,CAAC,QAAQ,CAAC,EAAE,iBAAiB,GAAG,OAAO,CAAC,SAAS,UAAU,EAAE,CAAC;IAInE,aAAa,CAAC,OAAO,CAAC,EAAE,iBAAiB,GAAG,OAAO,CAAC,SAAS,UAAU,EAAE,CAAC;CAG3E"}
|
|
@@ -1,29 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.MastodonSocialClient = void 0;
|
|
4
|
-
/**
|
|
5
|
-
*
|
|
6
|
-
*/
|
|
7
|
-
class MastodonSocialClient {
|
|
8
|
-
message = 'MastodonSocialClient is not yet supported in @hardlydifficult/social. Use provider type "x" for now.';
|
|
9
|
-
post(_postId) {
|
|
10
|
-
throw new Error(this.message);
|
|
11
|
-
}
|
|
12
|
-
getPost(postId) {
|
|
13
|
-
return this.post(postId);
|
|
14
|
-
}
|
|
15
|
-
timeline(_options) {
|
|
16
|
-
throw new Error(this.message);
|
|
17
|
-
}
|
|
18
|
-
getTimeline(options) {
|
|
19
|
-
return this.timeline(options);
|
|
20
|
-
}
|
|
21
|
-
likes(_options) {
|
|
22
|
-
throw new Error(this.message);
|
|
23
|
-
}
|
|
24
|
-
getLikedPosts(options) {
|
|
25
|
-
return this.likes(options);
|
|
26
|
-
}
|
|
27
|
-
}
|
|
28
|
-
exports.MastodonSocialClient = MastodonSocialClient;
|
|
29
|
-
//# sourceMappingURL=MastodonSocialClient.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"MastodonSocialClient.js","sourceRoot":"","sources":["../../src/mastodon/MastodonSocialClient.ts"],"names":[],"mappings":";;;AAGA;;GAEG;AACH,MAAa,oBAAoB;IACd,OAAO,GACtB,sGAAsG,CAAC;IAEzG,IAAI,CAAC,OAAe;QAClB,MAAM,IAAI,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;IAChC,CAAC;IAED,OAAO,CAAC,MAAc;QACpB,OAAO,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;IAC3B,CAAC;IAED,QAAQ,CAAC,QAA4B;QACnC,MAAM,IAAI,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;IAChC,CAAC;IAED,WAAW,CAAC,OAA2B;QACrC,OAAO,IAAI,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC;IAChC,CAAC;IAED,KAAK,CAAC,QAA4B;QAChC,MAAM,IAAI,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;IAChC,CAAC;IAED,aAAa,CAAC,OAA2B;QACvC,OAAO,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;IAC7B,CAAC;CACF;AA3BD,oDA2BC"}
|
|
@@ -1,23 +0,0 @@
|
|
|
1
|
-
import type { SocialProviderClient } from "../SocialProviderClient.js";
|
|
2
|
-
import type { SocialListOptions, SocialPost, XConfig } from "../types.js";
|
|
3
|
-
/**
|
|
4
|
-
*
|
|
5
|
-
*/
|
|
6
|
-
export declare class XSocialClient implements SocialProviderClient {
|
|
7
|
-
private readonly bearerToken;
|
|
8
|
-
private readonly limit;
|
|
9
|
-
constructor(config: XConfig);
|
|
10
|
-
post(postId: string): Promise<SocialPost | null>;
|
|
11
|
-
getPost(postId: string): Promise<SocialPost | null>;
|
|
12
|
-
timeline(options?: SocialListOptions): Promise<readonly SocialPost[]>;
|
|
13
|
-
getTimeline(options?: SocialListOptions): Promise<readonly SocialPost[]>;
|
|
14
|
-
likes(options?: SocialListOptions): Promise<readonly SocialPost[]>;
|
|
15
|
-
getLikedPosts(options?: SocialListOptions): Promise<readonly SocialPost[]>;
|
|
16
|
-
private buildQuery;
|
|
17
|
-
private request;
|
|
18
|
-
private readSingleTweet;
|
|
19
|
-
private readTweetList;
|
|
20
|
-
private isTweet;
|
|
21
|
-
private normalizeTweet;
|
|
22
|
-
}
|
|
23
|
-
//# sourceMappingURL=XSocialClient.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"XSocialClient.d.ts","sourceRoot":"","sources":["../../src/x/XSocialClient.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,4BAA4B,CAAC;AACvE,OAAO,KAAK,EAAE,iBAAiB,EAAE,UAAU,EAAE,OAAO,EAAE,MAAM,aAAa,CAAC;AA2B1E;;GAEG;AACH,qBAAa,aAAc,YAAW,oBAAoB;IACxD,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAS;IACrC,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAS;gBAEnB,MAAM,EAAE,OAAO;IASrB,IAAI,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,GAAG,IAAI,CAAC;IAYtD,OAAO,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,GAAG,IAAI,CAAC;IAI7C,QAAQ,CAAC,OAAO,CAAC,EAAE,iBAAiB,GAAG,OAAO,CAAC,SAAS,UAAU,EAAE,CAAC;IAU3E,WAAW,CAAC,OAAO,CAAC,EAAE,iBAAiB,GAAG,OAAO,CAAC,SAAS,UAAU,EAAE,CAAC;IAIlE,KAAK,CAAC,OAAO,CAAC,EAAE,iBAAiB,GAAG,OAAO,CAAC,SAAS,UAAU,EAAE,CAAC;IAUxE,aAAa,CAAC,OAAO,CAAC,EAAE,iBAAiB,GAAG,OAAO,CAAC,SAAS,UAAU,EAAE,CAAC;IAI1E,OAAO,CAAC,UAAU;YAWJ,OAAO;IAgBrB,OAAO,CAAC,eAAe;IAQvB,OAAO,CAAC,aAAa;IAQrB,OAAO,CAAC,OAAO;IAWf,OAAO,CAAC,cAAc;CAoBvB"}
|
package/dist/x/XSocialClient.js
DELETED
|
@@ -1,104 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.XSocialClient = void 0;
|
|
4
|
-
/**
|
|
5
|
-
*
|
|
6
|
-
*/
|
|
7
|
-
class XSocialClient {
|
|
8
|
-
bearerToken;
|
|
9
|
-
limit;
|
|
10
|
-
constructor(config) {
|
|
11
|
-
this.bearerToken = config.bearerToken ?? process.env.X_BEARER_TOKEN ?? "";
|
|
12
|
-
this.limit = config.limit ?? config.maxResults ?? 25;
|
|
13
|
-
if (this.bearerToken.length === 0) {
|
|
14
|
-
throw new Error("X bearer token is required. Set X_BEARER_TOKEN.");
|
|
15
|
-
}
|
|
16
|
-
}
|
|
17
|
-
async post(postId) {
|
|
18
|
-
const response = await this.request(`/tweets/${postId}${this.buildQuery()}`);
|
|
19
|
-
const tweet = this.readSingleTweet(response.data);
|
|
20
|
-
if (!tweet) {
|
|
21
|
-
return null;
|
|
22
|
-
}
|
|
23
|
-
return this.normalizeTweet(tweet, response.includes?.users ?? []);
|
|
24
|
-
}
|
|
25
|
-
getPost(postId) {
|
|
26
|
-
return this.post(postId);
|
|
27
|
-
}
|
|
28
|
-
async timeline(options) {
|
|
29
|
-
const response = await this.request(`/users/me/timelines/reverse_chronological${this.buildQuery(options?.limit)}`);
|
|
30
|
-
return this.readTweetList(response.data).map((tweet) => this.normalizeTweet(tweet, response.includes?.users ?? []));
|
|
31
|
-
}
|
|
32
|
-
getTimeline(options) {
|
|
33
|
-
return this.timeline(options);
|
|
34
|
-
}
|
|
35
|
-
async likes(options) {
|
|
36
|
-
const response = await this.request(`/users/me/liked_tweets${this.buildQuery(options?.limit)}`);
|
|
37
|
-
return this.readTweetList(response.data).map((tweet) => this.normalizeTweet(tweet, response.includes?.users ?? []));
|
|
38
|
-
}
|
|
39
|
-
getLikedPosts(options) {
|
|
40
|
-
return this.likes(options);
|
|
41
|
-
}
|
|
42
|
-
buildQuery(limit) {
|
|
43
|
-
const params = new URLSearchParams({
|
|
44
|
-
expansions: "author_id",
|
|
45
|
-
"tweet.fields": "created_at,public_metrics",
|
|
46
|
-
"user.fields": "name,username",
|
|
47
|
-
max_results: String(limit ?? this.limit),
|
|
48
|
-
});
|
|
49
|
-
return `?${params.toString()}`;
|
|
50
|
-
}
|
|
51
|
-
async request(path) {
|
|
52
|
-
const response = await fetch(`https://api.x.com/2${path}`, {
|
|
53
|
-
headers: {
|
|
54
|
-
Authorization: `Bearer ${this.bearerToken}`,
|
|
55
|
-
"Content-Type": "application/json",
|
|
56
|
-
},
|
|
57
|
-
});
|
|
58
|
-
if (!response.ok) {
|
|
59
|
-
const status = String(response.status);
|
|
60
|
-
throw new Error(`X API request failed: ${status} ${response.statusText}`);
|
|
61
|
-
}
|
|
62
|
-
return (await response.json());
|
|
63
|
-
}
|
|
64
|
-
readSingleTweet(data) {
|
|
65
|
-
if (!this.isTweet(data)) {
|
|
66
|
-
return null;
|
|
67
|
-
}
|
|
68
|
-
return data;
|
|
69
|
-
}
|
|
70
|
-
readTweetList(data) {
|
|
71
|
-
if (!Array.isArray(data)) {
|
|
72
|
-
return [];
|
|
73
|
-
}
|
|
74
|
-
return data.filter((item) => this.isTweet(item));
|
|
75
|
-
}
|
|
76
|
-
isTweet(value) {
|
|
77
|
-
if (typeof value !== "object" || value === null) {
|
|
78
|
-
return false;
|
|
79
|
-
}
|
|
80
|
-
const candidate = value;
|
|
81
|
-
return (typeof candidate.id === "string" && typeof candidate.text === "string");
|
|
82
|
-
}
|
|
83
|
-
normalizeTweet(tweet, users) {
|
|
84
|
-
const author = users.find((user) => user.id === tweet.author_id);
|
|
85
|
-
return {
|
|
86
|
-
id: tweet.id,
|
|
87
|
-
text: tweet.text,
|
|
88
|
-
createdAt: tweet.created_at ?? new Date(0).toISOString(),
|
|
89
|
-
url: `https://x.com/${author?.username ?? "i"}/status/${tweet.id}`,
|
|
90
|
-
author: {
|
|
91
|
-
id: author?.id ?? tweet.author_id ?? "unknown",
|
|
92
|
-
username: author?.username ?? "unknown",
|
|
93
|
-
displayName: author?.name ?? author?.username ?? "Unknown",
|
|
94
|
-
},
|
|
95
|
-
metrics: {
|
|
96
|
-
likes: tweet.public_metrics?.like_count ?? 0,
|
|
97
|
-
replies: tweet.public_metrics?.reply_count ?? 0,
|
|
98
|
-
reposts: tweet.public_metrics?.retweet_count ?? 0,
|
|
99
|
-
},
|
|
100
|
-
};
|
|
101
|
-
}
|
|
102
|
-
}
|
|
103
|
-
exports.XSocialClient = XSocialClient;
|
|
104
|
-
//# sourceMappingURL=XSocialClient.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"XSocialClient.js","sourceRoot":"","sources":["../../src/x/XSocialClient.ts"],"names":[],"mappings":"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"}
|
package/dist/x/index.d.ts
DELETED
package/dist/x/index.d.ts.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/x/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC"}
|
package/dist/x/index.js
DELETED
|
@@ -1,6 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.XSocialClient = void 0;
|
|
4
|
-
var XSocialClient_js_1 = require("./XSocialClient.js");
|
|
5
|
-
Object.defineProperty(exports, "XSocialClient", { enumerable: true, get: function () { return XSocialClient_js_1.XSocialClient; } });
|
|
6
|
-
//# sourceMappingURL=index.js.map
|
package/dist/x/index.js.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/x/index.ts"],"names":[],"mappings":";;;AAAA,uDAAmD;AAA1C,iHAAA,aAAa,OAAA"}
|