deso-ag 1.0.0
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/LICENSE +21 -0
- package/README.md +272 -0
- package/dist/fetchers/bluesky.d.ts +3 -0
- package/dist/fetchers/bluesky.d.ts.map +1 -0
- package/dist/fetchers/bluesky.js +154 -0
- package/dist/fetchers/bluesky.js.map +1 -0
- package/dist/fetchers/farcaster.d.ts +3 -0
- package/dist/fetchers/farcaster.d.ts.map +1 -0
- package/dist/fetchers/farcaster.js +149 -0
- package/dist/fetchers/farcaster.js.map +1 -0
- package/dist/fetchers/lens.d.ts +3 -0
- package/dist/fetchers/lens.d.ts.map +1 -0
- package/dist/fetchers/lens.js +125 -0
- package/dist/fetchers/lens.js.map +1 -0
- package/dist/fetchers/nostr.d.ts +3 -0
- package/dist/fetchers/nostr.d.ts.map +1 -0
- package/dist/fetchers/nostr.js +307 -0
- package/dist/fetchers/nostr.js.map +1 -0
- package/dist/formatters/output.d.ts +5 -0
- package/dist/formatters/output.d.ts.map +1 -0
- package/dist/formatters/output.js +225 -0
- package/dist/formatters/output.js.map +1 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +193 -0
- package/dist/index.js.map +1 -0
- package/dist/lib.d.ts +20 -0
- package/dist/lib.d.ts.map +1 -0
- package/dist/lib.js +71 -0
- package/dist/lib.js.map +1 -0
- package/dist/pipeline.d.ts +12 -0
- package/dist/pipeline.d.ts.map +1 -0
- package/dist/pipeline.js +136 -0
- package/dist/pipeline.js.map +1 -0
- package/dist/terms.d.ts +20 -0
- package/dist/terms.d.ts.map +1 -0
- package/dist/terms.js +158 -0
- package/dist/terms.js.map +1 -0
- package/dist/types.d.ts +67 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +2 -0
- package/dist/types.js.map +1 -0
- package/dist/utils/search.d.ts +6 -0
- package/dist/utils/search.d.ts.map +1 -0
- package/dist/utils/search.js +13 -0
- package/dist/utils/search.js.map +1 -0
- package/dist/utils/time.d.ts +4 -0
- package/dist/utils/time.d.ts.map +1 -0
- package/dist/utils/time.js +24 -0
- package/dist/utils/time.js.map +1 -0
- package/package.json +62 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2025 Matthew Lee
|
|
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.
|
package/README.md
ADDED
|
@@ -0,0 +1,272 @@
|
|
|
1
|
+
# deso-ag
|
|
2
|
+
|
|
3
|
+
**Decentralized Social Aggregator** - A CLI tool and library for aggregating posts from decentralized social protocols.
|
|
4
|
+
|
|
5
|
+
Search and view content across **Farcaster**, **Lens**, **Nostr**, and **Bluesky** from your terminal or programmatically from your agent.
|
|
6
|
+
|
|
7
|
+
## Setup
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
git clone https://github.com/sphairetra/deso-ag
|
|
11
|
+
cd deso-ag
|
|
12
|
+
pnpm install
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
### Environment Variables
|
|
16
|
+
|
|
17
|
+
| Variable | Required | Default | Description |
|
|
18
|
+
|----------|----------|---------|-------------|
|
|
19
|
+
| `NEYNAR_API_KEY` | For Farcaster | None — Farcaster is skipped | Neynar API key. Get one free at [neynar.com](https://neynar.com) |
|
|
20
|
+
| `BLUESKY_IDENTIFIER` | For Bluesky search | None — Bluesky search is skipped, trending still works | Your Bluesky handle (e.g. `user.bsky.social`) |
|
|
21
|
+
| `BLUESKY_APP_PASSWORD` | For Bluesky search | None — Bluesky search is skipped, trending still works | App password from [bsky.app/settings/app-passwords](https://bsky.app/settings/app-passwords) |
|
|
22
|
+
|
|
23
|
+
Lens, Nostr, and Bluesky trending work without any keys. Bluesky search requires authentication.
|
|
24
|
+
|
|
25
|
+
Add keys to your shell profile so they persist across sessions:
|
|
26
|
+
|
|
27
|
+
```bash
|
|
28
|
+
# Add to ~/.zshrc or ~/.bashrc
|
|
29
|
+
export NEYNAR_API_KEY=your-key-here
|
|
30
|
+
export BLUESKY_IDENTIFIER=your-handle.bsky.social
|
|
31
|
+
export BLUESKY_APP_PASSWORD=your-app-password
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
Without a key, the respective source/feature is skipped and everything else still works normally.
|
|
35
|
+
|
|
36
|
+
## Commands
|
|
37
|
+
|
|
38
|
+
### `search [query]`
|
|
39
|
+
|
|
40
|
+
Search for posts across networks.
|
|
41
|
+
|
|
42
|
+
```bash
|
|
43
|
+
pnpm dev search "ethereum"
|
|
44
|
+
pnpm dev search "AI" --sources nostr
|
|
45
|
+
pnpm dev search --channel dev --sources farcaster
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
Multi-word queries use AND semantics (all terms must match):
|
|
49
|
+
|
|
50
|
+
```bash
|
|
51
|
+
pnpm dev search "AI crypto" # posts must contain both "AI" and "crypto"
|
|
52
|
+
pnpm dev search "ethereum layer2"
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
### `trending`
|
|
56
|
+
|
|
57
|
+
Get trending posts from all networks.
|
|
58
|
+
|
|
59
|
+
```bash
|
|
60
|
+
pnpm dev trending
|
|
61
|
+
pnpm dev trending --sources farcaster,lens
|
|
62
|
+
pnpm dev trending --format json --limit 50
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
### `terms`
|
|
66
|
+
|
|
67
|
+
Extract top discussion terms from posts via engagement-weighted frequency analysis.
|
|
68
|
+
|
|
69
|
+
```bash
|
|
70
|
+
pnpm dev terms # top 3 terms per platform, last 24h
|
|
71
|
+
pnpm dev terms -n 5 -s farcaster -t week # top 5, Farcaster only, last week
|
|
72
|
+
pnpm dev terms -f json # machine-readable output
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
### `channels`
|
|
76
|
+
|
|
77
|
+
Browse popular Farcaster channels.
|
|
78
|
+
|
|
79
|
+
```bash
|
|
80
|
+
pnpm dev channels
|
|
81
|
+
pnpm dev channels --limit 50
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
## Options
|
|
85
|
+
|
|
86
|
+
All commands accept the following options (except where noted):
|
|
87
|
+
|
|
88
|
+
| Option | Description | Values | Default |
|
|
89
|
+
|--------|-------------|--------|---------|
|
|
90
|
+
| `-s, --sources` | Networks to query | `farcaster`, `lens`, `nostr`, `bluesky` (comma-separated) | `farcaster,lens,nostr,bluesky` (all) |
|
|
91
|
+
| `-t, --timeframe` | Time range for posts | `24h`, `48h`, `week` | `24h` |
|
|
92
|
+
| `-c, --channel` | Filter by channel | Any channel ID (Farcaster only) | none |
|
|
93
|
+
| `-f, --format` | Output format | `json`, `markdown`, `summary`, `compact` | `markdown` (search), `summary` (trending) |
|
|
94
|
+
| `-l, --limit` | Max posts per source | Any positive integer | `25` |
|
|
95
|
+
| `-o, --sort` | Sort order | `engagement`, `recent`, `relevance` | `relevance` (search), `engagement` (trending) |
|
|
96
|
+
| `-n, --top` | Top terms per source | Any positive integer (terms command only) | `3` |
|
|
97
|
+
|
|
98
|
+
### Output Formats
|
|
99
|
+
|
|
100
|
+
- **`markdown`** - Human-readable with headers, author info, and engagement stats. Default for `search`.
|
|
101
|
+
- **`summary`** - Condensed overview with post counts and top content. Default for `trending`.
|
|
102
|
+
- **`json`** - Raw JSON array of post objects. Good for piping to other tools.
|
|
103
|
+
- **`compact`** - Single JSON object with metadata envelope, engagement scores, and full content. Designed for AI agents.
|
|
104
|
+
|
|
105
|
+
### Sort Orders
|
|
106
|
+
|
|
107
|
+
- **`engagement`** - By score (`likes + reposts*2 + replies`). Best for discovering high-signal content. Default for `trending`.
|
|
108
|
+
- **`recent`** - By timestamp descending. Best for monitoring.
|
|
109
|
+
- **`relevance`** - Query-matching posts first, then by engagement. Default for `search`.
|
|
110
|
+
|
|
111
|
+
## Agent Usage
|
|
112
|
+
|
|
113
|
+
deso-ag is designed for consumption by AI agents doing research across decentralized social networks.
|
|
114
|
+
|
|
115
|
+
### Compact Output Format
|
|
116
|
+
|
|
117
|
+
The `compact` format returns a single JSON object with a metadata envelope, pre-computed engagement scores, full untruncated content, and source health info:
|
|
118
|
+
|
|
119
|
+
```bash
|
|
120
|
+
pnpm dev trending -f compact -l 10
|
|
121
|
+
pnpm dev search "AI agents" -f compact -l 10
|
|
122
|
+
```
|
|
123
|
+
|
|
124
|
+
Output shape:
|
|
125
|
+
|
|
126
|
+
```json
|
|
127
|
+
{
|
|
128
|
+
"meta": {
|
|
129
|
+
"query": "AI agents",
|
|
130
|
+
"totalPosts": 42,
|
|
131
|
+
"sources": [
|
|
132
|
+
{"name": "farcaster", "count": 15},
|
|
133
|
+
{"name": "lens", "count": 12},
|
|
134
|
+
{"name": "nostr", "count": 15}
|
|
135
|
+
],
|
|
136
|
+
"timeframe": "24h",
|
|
137
|
+
"fetchedAt": "2025-01-01T00:00:00.000Z"
|
|
138
|
+
},
|
|
139
|
+
"posts": [
|
|
140
|
+
{
|
|
141
|
+
"id": "...",
|
|
142
|
+
"source": "farcaster",
|
|
143
|
+
"author": "dwr",
|
|
144
|
+
"content": "full untruncated content...",
|
|
145
|
+
"timestamp": "2025-01-01T00:00:00.000Z",
|
|
146
|
+
"url": "https://...",
|
|
147
|
+
"score": 523,
|
|
148
|
+
"engagement": {"likes": 400, "reposts": 50, "replies": 23},
|
|
149
|
+
"tags": []
|
|
150
|
+
}
|
|
151
|
+
]
|
|
152
|
+
}
|
|
153
|
+
```
|
|
154
|
+
|
|
155
|
+
### Library Import
|
|
156
|
+
|
|
157
|
+
For agents that run in Node.js, import `aggregate()` directly instead of shelling out:
|
|
158
|
+
|
|
159
|
+
```typescript
|
|
160
|
+
import { aggregate } from 'deso-ag';
|
|
161
|
+
|
|
162
|
+
const result = await aggregate({
|
|
163
|
+
sources: ['farcaster', 'lens', 'nostr', 'bluesky'],
|
|
164
|
+
timeframe: '24h',
|
|
165
|
+
query: 'AI agents',
|
|
166
|
+
limit: 20,
|
|
167
|
+
sort: 'relevance',
|
|
168
|
+
});
|
|
169
|
+
|
|
170
|
+
console.log(result.meta.totalPosts);
|
|
171
|
+
for (const post of result.posts) {
|
|
172
|
+
console.log(`[${post.source}] @${post.author.username}: ${post.content.slice(0, 100)}`);
|
|
173
|
+
}
|
|
174
|
+
```
|
|
175
|
+
|
|
176
|
+
The `terms()` function extracts top discussion terms:
|
|
177
|
+
|
|
178
|
+
```typescript
|
|
179
|
+
import { terms } from 'deso-ag';
|
|
180
|
+
|
|
181
|
+
const result = await terms({
|
|
182
|
+
sources: ['farcaster', 'nostr'],
|
|
183
|
+
timeframe: '24h',
|
|
184
|
+
limit: 20,
|
|
185
|
+
}, 5); // top 5 terms
|
|
186
|
+
|
|
187
|
+
for (const st of result.bySource) {
|
|
188
|
+
console.log(`${st.source}: ${st.terms.map(t => t.token).join(', ')}`);
|
|
189
|
+
}
|
|
190
|
+
```
|
|
191
|
+
|
|
192
|
+
Individual fetchers and utilities are also exported:
|
|
193
|
+
|
|
194
|
+
```typescript
|
|
195
|
+
import { fetchFarcaster, fetchLens, fetchNostr, fetchBluesky, computeEngagementScore, matchesQuery, extractTerms } from 'deso-ag';
|
|
196
|
+
```
|
|
197
|
+
|
|
198
|
+
## Examples
|
|
199
|
+
|
|
200
|
+
```bash
|
|
201
|
+
# Get a quick summary of trending content
|
|
202
|
+
pnpm dev trending -f summary -l 20
|
|
203
|
+
|
|
204
|
+
# Agent-optimized compact output sorted by engagement
|
|
205
|
+
pnpm dev trending -f compact -o engagement -l 10
|
|
206
|
+
|
|
207
|
+
# Search for AI discussions on Lens only
|
|
208
|
+
pnpm dev search "AI" -s lens -f json
|
|
209
|
+
|
|
210
|
+
# Multi-word search with compact output
|
|
211
|
+
pnpm dev search "AI crypto" -f compact -l 10
|
|
212
|
+
|
|
213
|
+
# Browse the /dev channel on Farcaster
|
|
214
|
+
pnpm dev search --channel dev -s farcaster
|
|
215
|
+
|
|
216
|
+
# Export trending Nostr posts as JSON
|
|
217
|
+
pnpm dev trending -s nostr -f json > nostr-trending.json
|
|
218
|
+
|
|
219
|
+
# Search Bluesky for discussions
|
|
220
|
+
pnpm dev search "ethereum" -s bluesky -l 5
|
|
221
|
+
|
|
222
|
+
# Trending on Bluesky
|
|
223
|
+
pnpm dev trending -s bluesky -f summary
|
|
224
|
+
|
|
225
|
+
# Sort search results by recency
|
|
226
|
+
pnpm dev search "ethereum" -o recent -f json -l 5
|
|
227
|
+
|
|
228
|
+
# Top 5 terms across all networks this week
|
|
229
|
+
pnpm dev terms -n 5 -t week
|
|
230
|
+
|
|
231
|
+
# Terms from Farcaster and Nostr as JSON
|
|
232
|
+
pnpm dev terms -f json -s farcaster,nostr -l 10
|
|
233
|
+
```
|
|
234
|
+
|
|
235
|
+
## Supported Networks
|
|
236
|
+
|
|
237
|
+
| Network | API | Auth |
|
|
238
|
+
|---------|-----|------|
|
|
239
|
+
| **Farcaster** | [Neynar API](https://neynar.com) - trending feed and full-text search | `NEYNAR_API_KEY` required |
|
|
240
|
+
| **Lens** | [Lens V3 GraphQL API](https://api.lens.xyz) - server-side search, recent posts | None |
|
|
241
|
+
| **Nostr** | [nostr.wine trending API](https://docs.nostr.wine/api/trending) + public relays (relay.damus.io, nos.lol, relay.snort.social) | None |
|
|
242
|
+
| **Bluesky** | [AT Protocol API](https://docs.bsky.app) - public "What's Hot" feed for trending, authenticated search via `app.bsky.feed.searchPosts` | None (trending), `BLUESKY_IDENTIFIER` + `BLUESKY_APP_PASSWORD` (search) |
|
|
243
|
+
|
|
244
|
+
All networks return engagement stats (likes, reposts, replies) and support timeframe filtering.
|
|
245
|
+
|
|
246
|
+
## Limitations
|
|
247
|
+
|
|
248
|
+
- **Farcaster**: Requires `NEYNAR_API_KEY`. Without it, Farcaster is skipped.
|
|
249
|
+
- **Nostr**: Relay responses can be slow or inconsistent depending on network conditions.
|
|
250
|
+
- **Rate limits**: All APIs have rate limits. For heavy usage, consider running your own infrastructure.
|
|
251
|
+
|
|
252
|
+
## Development
|
|
253
|
+
|
|
254
|
+
```bash
|
|
255
|
+
pnpm build # Build for production
|
|
256
|
+
pnpm test # Run tests
|
|
257
|
+
```
|
|
258
|
+
|
|
259
|
+
## Tech Stack
|
|
260
|
+
|
|
261
|
+
- TypeScript
|
|
262
|
+
- Commander.js for CLI
|
|
263
|
+
- nostr-tools for Nostr protocol
|
|
264
|
+
- Native fetch for HTTP requests
|
|
265
|
+
|
|
266
|
+
## License
|
|
267
|
+
|
|
268
|
+
MIT
|
|
269
|
+
|
|
270
|
+
## Author
|
|
271
|
+
|
|
272
|
+
[@mattlee.eth](https://farcaster.xyz/mattlee.eth)
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"bluesky.d.ts","sourceRoot":"","sources":["../../src/fetchers/bluesky.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAQ,aAAa,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAyKpE,wBAAsB,YAAY,CAAC,OAAO,EAAE,aAAa,GAAG,OAAO,CAAC,WAAW,CAAC,CAmD/E"}
|
|
@@ -0,0 +1,154 @@
|
|
|
1
|
+
import { getTimeframeCutoff } from '../utils/time.js';
|
|
2
|
+
import { matchesQuery } from '../utils/search.js';
|
|
3
|
+
const BSKY_PUBLIC = 'https://public.api.bsky.app/xrpc';
|
|
4
|
+
const BSKY_PDS = 'https://bsky.social/xrpc';
|
|
5
|
+
const BSKY_APPVIEW = 'https://api.bsky.app/xrpc';
|
|
6
|
+
// Bluesky's official "What's Hot" feed generator
|
|
7
|
+
const WHATS_HOT_URI = 'at://did:plc:z72i7hdynmk6r22z27h6tvur/app.bsky.feed.generator/whats-hot';
|
|
8
|
+
function bskyPostToPost(post) {
|
|
9
|
+
// Extract rkey from AT URI: at://did/app.bsky.feed.post/rkey
|
|
10
|
+
const rkey = post.uri.split('/').pop() || '';
|
|
11
|
+
return {
|
|
12
|
+
id: post.uri,
|
|
13
|
+
source: 'bluesky',
|
|
14
|
+
author: {
|
|
15
|
+
username: post.author.handle,
|
|
16
|
+
displayName: post.author.displayName,
|
|
17
|
+
profileUrl: `https://bsky.app/profile/${post.author.handle}`,
|
|
18
|
+
},
|
|
19
|
+
content: post.record.text,
|
|
20
|
+
timestamp: new Date(post.record.createdAt),
|
|
21
|
+
url: `https://bsky.app/profile/${post.author.handle}/post/${rkey}`,
|
|
22
|
+
engagement: {
|
|
23
|
+
likes: post.likeCount || 0,
|
|
24
|
+
reposts: (post.repostCount || 0) + (post.quoteCount || 0),
|
|
25
|
+
replies: post.replyCount || 0,
|
|
26
|
+
},
|
|
27
|
+
tags: post.record.tags,
|
|
28
|
+
};
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* Fetch trending posts via the public "What's Hot" feed generator.
|
|
32
|
+
* No auth required.
|
|
33
|
+
*/
|
|
34
|
+
async function fetchWhatsHot(limit) {
|
|
35
|
+
const params = new URLSearchParams({
|
|
36
|
+
feed: WHATS_HOT_URI,
|
|
37
|
+
limit: String(Math.min(limit, 100)),
|
|
38
|
+
});
|
|
39
|
+
const controller = new AbortController();
|
|
40
|
+
const timeout = setTimeout(() => controller.abort(), 10000);
|
|
41
|
+
try {
|
|
42
|
+
const response = await fetch(`${BSKY_PUBLIC}/app.bsky.feed.getFeed?${params}`, {
|
|
43
|
+
signal: controller.signal,
|
|
44
|
+
headers: { 'Accept': 'application/json' },
|
|
45
|
+
});
|
|
46
|
+
clearTimeout(timeout);
|
|
47
|
+
if (!response.ok) {
|
|
48
|
+
throw new Error(`Bluesky feed API: ${response.status}`);
|
|
49
|
+
}
|
|
50
|
+
const data = await response.json();
|
|
51
|
+
return (data.feed || []).map(item => bskyPostToPost(item.post));
|
|
52
|
+
}
|
|
53
|
+
catch (error) {
|
|
54
|
+
clearTimeout(timeout);
|
|
55
|
+
throw error;
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
async function createSession(identifier, password) {
|
|
59
|
+
const controller = new AbortController();
|
|
60
|
+
const timeout = setTimeout(() => controller.abort(), 10000);
|
|
61
|
+
try {
|
|
62
|
+
const response = await fetch(`${BSKY_PDS}/com.atproto.server.createSession`, {
|
|
63
|
+
method: 'POST',
|
|
64
|
+
signal: controller.signal,
|
|
65
|
+
headers: { 'Content-Type': 'application/json' },
|
|
66
|
+
body: JSON.stringify({ identifier, password }),
|
|
67
|
+
});
|
|
68
|
+
clearTimeout(timeout);
|
|
69
|
+
if (!response.ok) {
|
|
70
|
+
throw new Error(`Bluesky auth failed: ${response.status}`);
|
|
71
|
+
}
|
|
72
|
+
const data = await response.json();
|
|
73
|
+
return data;
|
|
74
|
+
}
|
|
75
|
+
catch (error) {
|
|
76
|
+
clearTimeout(timeout);
|
|
77
|
+
throw error;
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
async function searchBluesky(accessJwt, query, limit) {
|
|
81
|
+
const params = new URLSearchParams({
|
|
82
|
+
q: query,
|
|
83
|
+
limit: String(Math.min(limit, 100)),
|
|
84
|
+
sort: 'top',
|
|
85
|
+
});
|
|
86
|
+
const controller = new AbortController();
|
|
87
|
+
const timeout = setTimeout(() => controller.abort(), 10000);
|
|
88
|
+
try {
|
|
89
|
+
const response = await fetch(`${BSKY_APPVIEW}/app.bsky.feed.searchPosts?${params}`, {
|
|
90
|
+
signal: controller.signal,
|
|
91
|
+
headers: {
|
|
92
|
+
'Accept': 'application/json',
|
|
93
|
+
'Authorization': `Bearer ${accessJwt}`,
|
|
94
|
+
},
|
|
95
|
+
});
|
|
96
|
+
clearTimeout(timeout);
|
|
97
|
+
if (!response.ok) {
|
|
98
|
+
throw new Error(`Bluesky search API: ${response.status}`);
|
|
99
|
+
}
|
|
100
|
+
const data = await response.json();
|
|
101
|
+
const posts = data.posts || [];
|
|
102
|
+
return posts.map(bskyPostToPost);
|
|
103
|
+
}
|
|
104
|
+
catch (error) {
|
|
105
|
+
clearTimeout(timeout);
|
|
106
|
+
throw error;
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
export async function fetchBluesky(options) {
|
|
110
|
+
const limit = options.limit || 25;
|
|
111
|
+
const cutoff = getTimeframeCutoff(options.timeframe);
|
|
112
|
+
try {
|
|
113
|
+
let posts;
|
|
114
|
+
if (options.query) {
|
|
115
|
+
// Search requires authentication
|
|
116
|
+
const identifier = process.env.BLUESKY_IDENTIFIER;
|
|
117
|
+
const appPassword = process.env.BLUESKY_APP_PASSWORD;
|
|
118
|
+
if (!identifier || !appPassword) {
|
|
119
|
+
return {
|
|
120
|
+
posts: [],
|
|
121
|
+
source: 'bluesky',
|
|
122
|
+
error: 'Bluesky search requires BLUESKY_IDENTIFIER and BLUESKY_APP_PASSWORD. Create an app password at https://bsky.app/settings/app-passwords',
|
|
123
|
+
};
|
|
124
|
+
}
|
|
125
|
+
const session = await createSession(identifier, appPassword);
|
|
126
|
+
posts = await searchBluesky(session.accessJwt, options.query, limit);
|
|
127
|
+
}
|
|
128
|
+
else {
|
|
129
|
+
// Trending uses the public "What's Hot" feed — no auth needed
|
|
130
|
+
posts = await fetchWhatsHot(limit);
|
|
131
|
+
}
|
|
132
|
+
// Apply timeframe cutoff client-side
|
|
133
|
+
posts = posts.filter(p => p.timestamp >= cutoff);
|
|
134
|
+
// Filter by query if provided (AND semantics for multi-word queries)
|
|
135
|
+
if (options.query) {
|
|
136
|
+
posts = posts.filter(p => matchesQuery(p.content, p.tags || [], options.query));
|
|
137
|
+
}
|
|
138
|
+
// Filter empty content
|
|
139
|
+
posts = posts.filter(p => p.content.trim().length > 0);
|
|
140
|
+
return {
|
|
141
|
+
posts: posts.slice(0, limit),
|
|
142
|
+
source: 'bluesky',
|
|
143
|
+
};
|
|
144
|
+
}
|
|
145
|
+
catch (error) {
|
|
146
|
+
const message = error instanceof Error ? error.message : 'Unknown error';
|
|
147
|
+
return {
|
|
148
|
+
posts: [],
|
|
149
|
+
source: 'bluesky',
|
|
150
|
+
error: `Bluesky: ${message}`,
|
|
151
|
+
};
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
//# sourceMappingURL=bluesky.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"bluesky.js","sourceRoot":"","sources":["../../src/fetchers/bluesky.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,kBAAkB,EAAE,MAAM,kBAAkB,CAAC;AACtD,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAElD,MAAM,WAAW,GAAG,kCAAkC,CAAC;AACvD,MAAM,QAAQ,GAAG,0BAA0B,CAAC;AAC5C,MAAM,YAAY,GAAG,2BAA2B,CAAC;AAEjD,iDAAiD;AACjD,MAAM,aAAa,GAAG,yEAAyE,CAAC;AAsChG,SAAS,cAAc,CAAC,IAAc;IACpC,6DAA6D;IAC7D,MAAM,IAAI,GAAG,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,IAAI,EAAE,CAAC;IAE7C,OAAO;QACL,EAAE,EAAE,IAAI,CAAC,GAAG;QACZ,MAAM,EAAE,SAAkB;QAC1B,MAAM,EAAE;YACN,QAAQ,EAAE,IAAI,CAAC,MAAM,CAAC,MAAM;YAC5B,WAAW,EAAE,IAAI,CAAC,MAAM,CAAC,WAAW;YACpC,UAAU,EAAE,4BAA4B,IAAI,CAAC,MAAM,CAAC,MAAM,EAAE;SAC7D;QACD,OAAO,EAAE,IAAI,CAAC,MAAM,CAAC,IAAI;QACzB,SAAS,EAAE,IAAI,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC;QAC1C,GAAG,EAAE,4BAA4B,IAAI,CAAC,MAAM,CAAC,MAAM,SAAS,IAAI,EAAE;QAClE,UAAU,EAAE;YACV,KAAK,EAAE,IAAI,CAAC,SAAS,IAAI,CAAC;YAC1B,OAAO,EAAE,CAAC,IAAI,CAAC,WAAW,IAAI,CAAC,CAAC,GAAG,CAAC,IAAI,CAAC,UAAU,IAAI,CAAC,CAAC;YACzD,OAAO,EAAE,IAAI,CAAC,UAAU,IAAI,CAAC;SAC9B;QACD,IAAI,EAAE,IAAI,CAAC,MAAM,CAAC,IAAI;KACvB,CAAC;AACJ,CAAC;AAED;;;GAGG;AACH,KAAK,UAAU,aAAa,CAAC,KAAa;IACxC,MAAM,MAAM,GAAG,IAAI,eAAe,CAAC;QACjC,IAAI,EAAE,aAAa;QACnB,KAAK,EAAE,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC;KACpC,CAAC,CAAC;IAEH,MAAM,UAAU,GAAG,IAAI,eAAe,EAAE,CAAC;IACzC,MAAM,OAAO,GAAG,UAAU,CAAC,GAAG,EAAE,CAAC,UAAU,CAAC,KAAK,EAAE,EAAE,KAAK,CAAC,CAAC;IAE5D,IAAI,CAAC;QACH,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,GAAG,WAAW,0BAA0B,MAAM,EAAE,EAAE;YAC7E,MAAM,EAAE,UAAU,CAAC,MAAM;YACzB,OAAO,EAAE,EAAE,QAAQ,EAAE,kBAAkB,EAAE;SAC1C,CAAC,CAAC;QAEH,YAAY,CAAC,OAAO,CAAC,CAAC;QAEtB,IAAI,CAAC,QAAQ,CAAC,EAAE,EAAE,CAAC;YACjB,MAAM,IAAI,KAAK,CAAC,qBAAqB,QAAQ,CAAC,MAAM,EAAE,CAAC,CAAC;QAC1D,CAAC;QAED,MAAM,IAAI,GAAG,MAAM,QAAQ,CAAC,IAAI,EAAsB,CAAC;QACvD,OAAO,CAAC,IAAI,CAAC,IAAI,IAAI,EAAE,CAAC,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC,cAAc,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC;IAClE,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,YAAY,CAAC,OAAO,CAAC,CAAC;QACtB,MAAM,KAAK,CAAC;IACd,CAAC;AACH,CAAC;AAED,KAAK,UAAU,aAAa,CAAC,UAAkB,EAAE,QAAgB;IAC/D,MAAM,UAAU,GAAG,IAAI,eAAe,EAAE,CAAC;IACzC,MAAM,OAAO,GAAG,UAAU,CAAC,GAAG,EAAE,CAAC,UAAU,CAAC,KAAK,EAAE,EAAE,KAAK,CAAC,CAAC;IAE5D,IAAI,CAAC;QACH,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,GAAG,QAAQ,mCAAmC,EAAE;YAC3E,MAAM,EAAE,MAAM;YACd,MAAM,EAAE,UAAU,CAAC,MAAM;YACzB,OAAO,EAAE,EAAE,cAAc,EAAE,kBAAkB,EAAE;YAC/C,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,EAAE,UAAU,EAAE,QAAQ,EAAE,CAAC;SAC/C,CAAC,CAAC;QAEH,YAAY,CAAC,OAAO,CAAC,CAAC;QAEtB,IAAI,CAAC,QAAQ,CAAC,EAAE,EAAE,CAAC;YACjB,MAAM,IAAI,KAAK,CAAC,wBAAwB,QAAQ,CAAC,MAAM,EAAE,CAAC,CAAC;QAC7D,CAAC;QAED,MAAM,IAAI,GAAG,MAAM,QAAQ,CAAC,IAAI,EAAiB,CAAC;QAClD,OAAO,IAAI,CAAC;IACd,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,YAAY,CAAC,OAAO,CAAC,CAAC;QACtB,MAAM,KAAK,CAAC;IACd,CAAC;AACH,CAAC;AAED,KAAK,UAAU,aAAa,CAC1B,SAAiB,EACjB,KAAa,EACb,KAAa;IAEb,MAAM,MAAM,GAAG,IAAI,eAAe,CAAC;QACjC,CAAC,EAAE,KAAK;QACR,KAAK,EAAE,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC;QACnC,IAAI,EAAE,KAAK;KACZ,CAAC,CAAC;IAEH,MAAM,UAAU,GAAG,IAAI,eAAe,EAAE,CAAC;IACzC,MAAM,OAAO,GAAG,UAAU,CAAC,GAAG,EAAE,CAAC,UAAU,CAAC,KAAK,EAAE,EAAE,KAAK,CAAC,CAAC;IAE5D,IAAI,CAAC;QACH,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,GAAG,YAAY,8BAA8B,MAAM,EAAE,EAAE;YAClF,MAAM,EAAE,UAAU,CAAC,MAAM;YACzB,OAAO,EAAE;gBACP,QAAQ,EAAE,kBAAkB;gBAC5B,eAAe,EAAE,UAAU,SAAS,EAAE;aACvC;SACF,CAAC,CAAC;QAEH,YAAY,CAAC,OAAO,CAAC,CAAC;QAEtB,IAAI,CAAC,QAAQ,CAAC,EAAE,EAAE,CAAC;YACjB,MAAM,IAAI,KAAK,CAAC,uBAAuB,QAAQ,CAAC,MAAM,EAAE,CAAC,CAAC;QAC5D,CAAC;QAED,MAAM,IAAI,GAAG,MAAM,QAAQ,CAAC,IAAI,EAAwB,CAAC;QACzD,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,IAAI,EAAE,CAAC;QAE/B,OAAO,KAAK,CAAC,GAAG,CAAC,cAAc,CAAC,CAAC;IACnC,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,YAAY,CAAC,OAAO,CAAC,CAAC;QACtB,MAAM,KAAK,CAAC;IACd,CAAC;AACH,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,YAAY,CAAC,OAAsB;IACvD,MAAM,KAAK,GAAG,OAAO,CAAC,KAAK,IAAI,EAAE,CAAC;IAClC,MAAM,MAAM,GAAG,kBAAkB,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC;IAErD,IAAI,CAAC;QACH,IAAI,KAAa,CAAC;QAElB,IAAI,OAAO,CAAC,KAAK,EAAE,CAAC;YAClB,iCAAiC;YACjC,MAAM,UAAU,GAAG,OAAO,CAAC,GAAG,CAAC,kBAAkB,CAAC;YAClD,MAAM,WAAW,GAAG,OAAO,CAAC,GAAG,CAAC,oBAAoB,CAAC;YACrD,IAAI,CAAC,UAAU,IAAI,CAAC,WAAW,EAAE,CAAC;gBAChC,OAAO;oBACL,KAAK,EAAE,EAAE;oBACT,MAAM,EAAE,SAAS;oBACjB,KAAK,EAAE,wIAAwI;iBAChJ,CAAC;YACJ,CAAC;YAED,MAAM,OAAO,GAAG,MAAM,aAAa,CAAC,UAAU,EAAE,WAAW,CAAC,CAAC;YAC7D,KAAK,GAAG,MAAM,aAAa,CAAC,OAAO,CAAC,SAAS,EAAE,OAAO,CAAC,KAAK,EAAE,KAAK,CAAC,CAAC;QACvE,CAAC;aAAM,CAAC;YACN,8DAA8D;YAC9D,KAAK,GAAG,MAAM,aAAa,CAAC,KAAK,CAAC,CAAC;QACrC,CAAC;QAED,qCAAqC;QACrC,KAAK,GAAG,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,SAAS,IAAI,MAAM,CAAC,CAAC;QAEjD,qEAAqE;QACrE,IAAI,OAAO,CAAC,KAAK,EAAE,CAAC;YAClB,KAAK,GAAG,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CACvB,YAAY,CAAC,CAAC,CAAC,OAAO,EAAE,CAAC,CAAC,IAAI,IAAI,EAAE,EAAE,OAAO,CAAC,KAAM,CAAC,CACtD,CAAC;QACJ,CAAC;QAED,uBAAuB;QACvB,KAAK,GAAG,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC,IAAI,EAAE,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;QAEvD,OAAO;YACL,KAAK,EAAE,KAAK,CAAC,KAAK,CAAC,CAAC,EAAE,KAAK,CAAC;YAC5B,MAAM,EAAE,SAAS;SAClB,CAAC;IACJ,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,MAAM,OAAO,GAAG,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,eAAe,CAAC;QACzE,OAAO;YACL,KAAK,EAAE,EAAE;YACT,MAAM,EAAE,SAAS;YACjB,KAAK,EAAE,YAAY,OAAO,EAAE;SAC7B,CAAC;IACJ,CAAC;AACH,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"farcaster.d.ts","sourceRoot":"","sources":["../../src/fetchers/farcaster.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAQ,aAAa,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAiEpE,wBAAsB,cAAc,CAAC,OAAO,EAAE,aAAa,GAAG,OAAO,CAAC,WAAW,CAAC,CA+CjF"}
|
|
@@ -0,0 +1,149 @@
|
|
|
1
|
+
import { getTimeframeCutoff } from '../utils/time.js';
|
|
2
|
+
import { matchesQuery } from '../utils/search.js';
|
|
3
|
+
const NEYNAR_API = 'https://api.neynar.com/v2/farcaster';
|
|
4
|
+
function neynarCastToPost(cast) {
|
|
5
|
+
return {
|
|
6
|
+
id: cast.hash,
|
|
7
|
+
source: 'farcaster',
|
|
8
|
+
author: {
|
|
9
|
+
username: cast.author.username || `fid:${cast.author.fid}`,
|
|
10
|
+
displayName: cast.author.display_name,
|
|
11
|
+
profileUrl: `https://farcaster.xyz/${cast.author.username}`,
|
|
12
|
+
},
|
|
13
|
+
content: cast.text,
|
|
14
|
+
timestamp: new Date(cast.timestamp),
|
|
15
|
+
url: `https://farcaster.xyz/${cast.author.username}/${cast.hash.slice(0, 10)}`,
|
|
16
|
+
engagement: {
|
|
17
|
+
likes: cast.reactions?.likes_count || 0,
|
|
18
|
+
reposts: cast.reactions?.recasts_count || 0,
|
|
19
|
+
replies: cast.replies?.count || 0,
|
|
20
|
+
},
|
|
21
|
+
};
|
|
22
|
+
}
|
|
23
|
+
function mapTimeframeToWindow(timeframe) {
|
|
24
|
+
switch (timeframe) {
|
|
25
|
+
case '24h': return '24h';
|
|
26
|
+
case '48h': return '24h'; // closest available
|
|
27
|
+
case 'week': return '7d';
|
|
28
|
+
default: return '24h';
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
export async function fetchFarcaster(options) {
|
|
32
|
+
const apiKey = process.env.NEYNAR_API_KEY;
|
|
33
|
+
if (!apiKey) {
|
|
34
|
+
return {
|
|
35
|
+
posts: [],
|
|
36
|
+
source: 'farcaster',
|
|
37
|
+
error: 'Farcaster requires NEYNAR_API_KEY. Get one at https://neynar.com',
|
|
38
|
+
};
|
|
39
|
+
}
|
|
40
|
+
const limit = options.limit || 25;
|
|
41
|
+
const cutoff = getTimeframeCutoff(options.timeframe);
|
|
42
|
+
try {
|
|
43
|
+
let posts;
|
|
44
|
+
if (options.query) {
|
|
45
|
+
posts = await fetchNeynarSearch(apiKey, options.query, limit, options.channel);
|
|
46
|
+
}
|
|
47
|
+
else {
|
|
48
|
+
posts = await fetchNeynarTrending(apiKey, limit, options.timeframe, options.channel);
|
|
49
|
+
}
|
|
50
|
+
// Apply timeframe cutoff
|
|
51
|
+
posts = posts.filter(p => p.timestamp >= cutoff);
|
|
52
|
+
// Filter by query if provided (AND semantics for multi-word queries)
|
|
53
|
+
if (options.query) {
|
|
54
|
+
posts = posts.filter(p => matchesQuery(p.content, p.tags || [], options.query));
|
|
55
|
+
}
|
|
56
|
+
// Filter empty content
|
|
57
|
+
posts = posts.filter(p => p.content.trim().length > 0);
|
|
58
|
+
return {
|
|
59
|
+
posts: posts.slice(0, limit),
|
|
60
|
+
source: 'farcaster',
|
|
61
|
+
};
|
|
62
|
+
}
|
|
63
|
+
catch (error) {
|
|
64
|
+
const message = error instanceof Error ? error.message : 'Unknown error';
|
|
65
|
+
return {
|
|
66
|
+
posts: [],
|
|
67
|
+
source: 'farcaster',
|
|
68
|
+
error: `Farcaster: ${message}`,
|
|
69
|
+
};
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
async function fetchNeynarTrending(apiKey, limit, timeframe, channel) {
|
|
73
|
+
const timeWindow = mapTimeframeToWindow(timeframe);
|
|
74
|
+
const allPosts = [];
|
|
75
|
+
let cursor;
|
|
76
|
+
// Neynar trending limit is 1-10 per request, so paginate
|
|
77
|
+
while (allPosts.length < limit) {
|
|
78
|
+
const batchSize = Math.min(10, limit - allPosts.length);
|
|
79
|
+
const params = new URLSearchParams({
|
|
80
|
+
limit: String(batchSize),
|
|
81
|
+
time_window: timeWindow,
|
|
82
|
+
});
|
|
83
|
+
if (channel)
|
|
84
|
+
params.set('channel_id', channel);
|
|
85
|
+
if (cursor)
|
|
86
|
+
params.set('cursor', cursor);
|
|
87
|
+
const controller = new AbortController();
|
|
88
|
+
const timeout = setTimeout(() => controller.abort(), 10000);
|
|
89
|
+
try {
|
|
90
|
+
const response = await fetch(`${NEYNAR_API}/feed/trending?${params}`, {
|
|
91
|
+
signal: controller.signal,
|
|
92
|
+
headers: {
|
|
93
|
+
'Accept': 'application/json',
|
|
94
|
+
'x-api-key': apiKey,
|
|
95
|
+
},
|
|
96
|
+
});
|
|
97
|
+
clearTimeout(timeout);
|
|
98
|
+
if (!response.ok) {
|
|
99
|
+
throw new Error(`Neynar trending API: ${response.status}`);
|
|
100
|
+
}
|
|
101
|
+
const data = await response.json();
|
|
102
|
+
const casts = data.casts || [];
|
|
103
|
+
if (casts.length === 0)
|
|
104
|
+
break;
|
|
105
|
+
for (const cast of casts) {
|
|
106
|
+
allPosts.push(neynarCastToPost(cast));
|
|
107
|
+
}
|
|
108
|
+
cursor = data.next?.cursor;
|
|
109
|
+
if (!cursor)
|
|
110
|
+
break;
|
|
111
|
+
}
|
|
112
|
+
catch (error) {
|
|
113
|
+
clearTimeout(timeout);
|
|
114
|
+
throw error;
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
return allPosts;
|
|
118
|
+
}
|
|
119
|
+
async function fetchNeynarSearch(apiKey, query, limit, channel) {
|
|
120
|
+
const params = new URLSearchParams({
|
|
121
|
+
q: query,
|
|
122
|
+
limit: String(Math.min(limit, 100)),
|
|
123
|
+
});
|
|
124
|
+
if (channel)
|
|
125
|
+
params.set('channel_id', channel);
|
|
126
|
+
const controller = new AbortController();
|
|
127
|
+
const timeout = setTimeout(() => controller.abort(), 10000);
|
|
128
|
+
try {
|
|
129
|
+
const response = await fetch(`${NEYNAR_API}/cast/search?${params}`, {
|
|
130
|
+
signal: controller.signal,
|
|
131
|
+
headers: {
|
|
132
|
+
'Accept': 'application/json',
|
|
133
|
+
'x-api-key': apiKey,
|
|
134
|
+
},
|
|
135
|
+
});
|
|
136
|
+
clearTimeout(timeout);
|
|
137
|
+
if (!response.ok) {
|
|
138
|
+
throw new Error(`Neynar search API: ${response.status}`);
|
|
139
|
+
}
|
|
140
|
+
const data = await response.json();
|
|
141
|
+
const casts = data.result?.casts || [];
|
|
142
|
+
return casts.map(neynarCastToPost);
|
|
143
|
+
}
|
|
144
|
+
catch (error) {
|
|
145
|
+
clearTimeout(timeout);
|
|
146
|
+
throw error;
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
//# sourceMappingURL=farcaster.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"farcaster.js","sourceRoot":"","sources":["../../src/fetchers/farcaster.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"lens.d.ts","sourceRoot":"","sources":["../../src/fetchers/lens.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAQ,aAAa,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAiCpE,wBAAsB,SAAS,CAAC,OAAO,EAAE,aAAa,GAAG,OAAO,CAAC,WAAW,CAAC,CAqD5E"}
|