forked from pollinations/pollinations
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathfeed.js
More file actions
107 lines (92 loc) · 3.71 KB
/
feed.js
File metadata and controls
107 lines (92 loc) · 3.71 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
import debug from "debug";
import dotenv from "dotenv";
// Load environment variables
dotenv.config();
const log = debug("pollinations:feed");
// Map to store connected clients
const connectedClients = new Map();
// Map to store authenticated clients (for private requests)
const authenticatedClients = new Map();
// Get feed password from environment, default to a placeholder if not set
const FEED_PASSWORD = process.env.FEED_PASSWORD;
function sendToFeedListeners(response, requestParams, ip) {
// Always log statistics for all requests (private and public)
const isPrivate = requestParams.isPrivate === true;
// For all regular clients, only send non-private requests
for (const [_, send] of connectedClients) {
if (!isPrivate) {
log("broadcasting public response to", connectedClients.size);
send(response, requestParams, ip);
}
}
// For authenticated clients, send all requests (including private ones)
for (const [_, send] of authenticatedClients) {
log(
"broadcasting " +
(isPrivate ? "private" : "public") +
" response to authenticated client",
);
send(response, requestParams, ip);
}
}
function setupFeedEndpoint(app) {
// Single feed endpoint with optional password parameter
app.get("/feed", (req, res) => {
const providedPassword = req.query.password;
const isAuthenticated = providedPassword === FEED_PASSWORD;
res.writeHead(200, {
"Content-Type": "text/event-stream; charset=utf-8",
"Cache-Control": "no-cache",
Connection: "keep-alive",
});
// Generate client ID
const clientId = Date.now();
if (isAuthenticated) {
// For authenticated clients - add to authenticated list and include private requests
log(
"Authenticated client connected, total:",
authenticatedClients.size + 1,
);
authenticatedClients.set(clientId, (response, parameters, ip) => {
const eventData = {
response,
parameters,
ip, // Include IP for authenticated clients
isPrivate: parameters.isPrivate === true,
};
// Properly encode the data for SSE
const encodedData = JSON.stringify(eventData)
.replace(/\n/g, "\\n")
.replace(/\r/g, "\\r");
res.write(`data: ${encodedData}\n\n`);
});
// Remove the client when they disconnect
req.on("close", () => {
authenticatedClients.delete(clientId);
log(
"Authenticated client disconnected, remaining:",
authenticatedClients.size,
);
});
} else {
// For regular clients - add to regular list and exclude private requests
connectedClients.set(clientId, (response, parameters, ip) => {
const eventData = {
response,
parameters,
// Don't include IP for non-authenticated clients
};
// Properly encode the data for SSE
const encodedData = JSON.stringify(eventData)
.replace(/\n/g, "\\n")
.replace(/\r/g, "\\r");
res.write(`data: ${encodedData}\n\n`);
});
// Remove the client when they disconnect
req.on("close", () => {
connectedClients.delete(clientId);
});
}
});
}
export { setupFeedEndpoint, sendToFeedListeners };