antenna-fyi 1.2.4 ā 1.2.6
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/lib/cli.js +39 -9
- package/lib/core.js +31 -1
- package/lib/hermes-plugin/__init__.py +6 -0
- package/lib/hermes-plugin/schemas.py +33 -1
- package/lib/hermes-plugin/tools.py +39 -0
- package/lib/mcp.js +44 -2
- package/package.json +1 -1
- package/skill/SKILL.md +16 -2
package/lib/cli.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
// antenna CLI command handlers
|
|
2
2
|
|
|
3
|
-
import { scan, getProfile, setProfile, accept, checkMatches, checkin, createBindToken, discover, createEvent, joinEvent, eventScan, pass as passUser } from "./core.js";
|
|
3
|
+
import { scan, getProfile, setProfile, accept, checkMatches, checkin, createBindToken, discover, createEvent, endEvent, eventCheckin, joinEvent, eventScan, pass as passUser } from "./core.js";
|
|
4
4
|
import { createInterface } from "readline";
|
|
5
5
|
import { existsSync, mkdirSync, copyFileSync } from "fs";
|
|
6
6
|
import { join, dirname } from "path";
|
|
@@ -47,8 +47,18 @@ export async function handleScan(f) {
|
|
|
47
47
|
if (p.line1) console.log(` ${p.line1}`);
|
|
48
48
|
if (p.line2) console.log(` ${p.line2}`);
|
|
49
49
|
if (p.line3) console.log(` ${p.line3}`);
|
|
50
|
-
console.log(`
|
|
50
|
+
console.log(` ref: ${p.ref}\n`);
|
|
51
51
|
});
|
|
52
|
+
|
|
53
|
+
// Show nearby events
|
|
54
|
+
if (result.nearby_events?.length) {
|
|
55
|
+
console.log(`š Nearby events:\n`);
|
|
56
|
+
result.nearby_events.forEach((e) => {
|
|
57
|
+
console.log(` ${e.name} ā ${e.participants} people`);
|
|
58
|
+
if (e.description) console.log(` ${e.description}`);
|
|
59
|
+
console.log(` Join: antenna event --join --code ${e.code}\n`);
|
|
60
|
+
});
|
|
61
|
+
}
|
|
52
62
|
}
|
|
53
63
|
|
|
54
64
|
export async function handleProfile(f) {
|
|
@@ -131,11 +141,29 @@ export async function handleDiscover(f) {
|
|
|
131
141
|
}
|
|
132
142
|
|
|
133
143
|
export async function handleEvent(f) {
|
|
134
|
-
const sub = f._?.[0] || Object.keys(f).find(k => ["create", "join", "scan"].includes(k));
|
|
144
|
+
const sub = f._?.[0] || Object.keys(f).find(k => ["create", "join", "scan", "end", "checkin"].includes(k));
|
|
145
|
+
|
|
146
|
+
if (f.end) {
|
|
147
|
+
if (!f.code || !f.id) return console.error("Usage: antenna event --end --code abc123 --id telegram:123");
|
|
148
|
+
const result = await endEvent({ code: f.code, device_id: f.id });
|
|
149
|
+
if (result.ended) {
|
|
150
|
+
console.log(`\nā
Event ended.\n`);
|
|
151
|
+
} else {
|
|
152
|
+
console.log(`\nā ${result.error || 'Failed to end event'}\n`);
|
|
153
|
+
}
|
|
154
|
+
return;
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
if (f.checkin) {
|
|
158
|
+
if (!f.code || !f.id) return console.error("Usage: antenna event --checkin --code abc123 --id telegram:123 [--lat 34.05 --lng -118.24]");
|
|
159
|
+
const result = await eventCheckin({ code: f.code, device_id: f.id, lat: f.lat ? +f.lat : undefined, lng: f.lng ? +f.lng : undefined });
|
|
160
|
+
console.log(`\nā
Checked in to event.\n`);
|
|
161
|
+
return;
|
|
162
|
+
}
|
|
135
163
|
|
|
136
|
-
if (f.create || (!f.join && !f.scan && f.name)) {
|
|
137
|
-
if (!f.name) return console.error("Usage: antenna event --create --name 'AI Meetup'");
|
|
138
|
-
const result = await createEvent({ name: f.name, device_id: f.id || null, lat: f.lat ? +f.lat : undefined, lng: f.lng ? +f.lng : undefined });
|
|
164
|
+
if (f.create || (!f.join && !f.scan && !f.end && f.name)) {
|
|
165
|
+
if (!f.name) return console.error("Usage: antenna event --create --name 'AI Meetup' [--desc 'description'] [--og-image 'url']");
|
|
166
|
+
const result = await createEvent({ name: f.name, device_id: f.id || null, lat: f.lat ? +f.lat : undefined, lng: f.lng ? +f.lng : undefined, description: f.desc || undefined, og_image: f['og-image'] || undefined });
|
|
139
167
|
console.log(`\nš Event created!\n`);
|
|
140
168
|
console.log(` Name: ${result.name}`);
|
|
141
169
|
console.log(` Code: ${result.code}`);
|
|
@@ -169,9 +197,11 @@ export async function handleEvent(f) {
|
|
|
169
197
|
}
|
|
170
198
|
|
|
171
199
|
console.log(`Usage:
|
|
172
|
-
antenna event --create --name 'AI Meetup' [--id telegram:123]
|
|
200
|
+
antenna event --create --name 'AI Meetup' [--id telegram:123] [--desc 'description'] [--og-image 'url']
|
|
173
201
|
antenna event --join --code abc123 --id telegram:123
|
|
174
|
-
antenna event --scan --code abc123 [--id telegram:123]
|
|
202
|
+
antenna event --scan --code abc123 [--id telegram:123]
|
|
203
|
+
antenna event --checkin --code abc123 --id telegram:123 [--lat 34.05 --lng -118.24]
|
|
204
|
+
antenna event --end --code abc123 --id telegram:123`);
|
|
175
205
|
}
|
|
176
206
|
|
|
177
207
|
export async function handleBind(f) {
|
|
@@ -366,7 +396,7 @@ Usage:
|
|
|
366
396
|
antenna pass --id telegram:123 --target telegram:789 (or --ref 1)
|
|
367
397
|
antenna matches --id telegram:123
|
|
368
398
|
antenna discover --id telegram:123
|
|
369
|
-
antenna event --create --name 'AI Meetup' | --join --code abc123 | --scan --code abc123
|
|
399
|
+
antenna event --create --name 'AI Meetup' [--desc '...'] [--og-image 'url'] | --join --code abc123 | --scan --code abc123 | --end --code abc123 --id telegram:123
|
|
370
400
|
antenna bind --id telegram:123
|
|
371
401
|
antenna serve Start MCP server (stdio transport)
|
|
372
402
|
antenna setup Interactive profile setup [--id telegram:123]
|
package/lib/core.js
CHANGED
|
@@ -161,11 +161,21 @@ export async function scan({ lat, lng, radius_m = 500, device_id, supabaseUrl, s
|
|
|
161
161
|
const profs = buildProfiles(others);
|
|
162
162
|
await saveRefs(_refMap);
|
|
163
163
|
|
|
164
|
+
// Fetch nearby events
|
|
165
|
+
let nearby_events = [];
|
|
166
|
+
if (lat != null && lng != null) {
|
|
167
|
+
try {
|
|
168
|
+
const { data: evts } = await sb.rpc("nearby_events", { p_lat: lat, p_lng: lng, p_radius_m: 5000 });
|
|
169
|
+
nearby_events = evts || [];
|
|
170
|
+
} catch { /* best effort */ }
|
|
171
|
+
}
|
|
172
|
+
|
|
164
173
|
return {
|
|
165
174
|
count: others.length,
|
|
166
175
|
radius_m,
|
|
167
176
|
profiles: profs,
|
|
168
177
|
_ref_map: _refMap,
|
|
178
|
+
nearby_events,
|
|
169
179
|
};
|
|
170
180
|
}
|
|
171
181
|
|
|
@@ -469,7 +479,7 @@ export async function pass({ device_id, target_device_id, ref, supabaseUrl, supa
|
|
|
469
479
|
|
|
470
480
|
// āāā events āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā
|
|
471
481
|
|
|
472
|
-
export async function createEvent({ name, lat, lng, device_id, starts_at, ends_at, supabaseUrl, supabaseKey }) {
|
|
482
|
+
export async function createEvent({ name, lat, lng, device_id, starts_at, ends_at, description, og_image, supabaseUrl, supabaseKey }) {
|
|
473
483
|
const sb = getClient(supabaseUrl, supabaseKey);
|
|
474
484
|
const { data, error } = await sb.rpc("create_event", {
|
|
475
485
|
p_name: name,
|
|
@@ -478,6 +488,26 @@ export async function createEvent({ name, lat, lng, device_id, starts_at, ends_a
|
|
|
478
488
|
p_created_by: device_id || null,
|
|
479
489
|
p_starts_at: starts_at || new Date().toISOString(),
|
|
480
490
|
p_ends_at: ends_at || new Date(Date.now() + 12 * 60 * 60 * 1000).toISOString(),
|
|
491
|
+
p_description: description || null,
|
|
492
|
+
p_og_image: og_image || null,
|
|
493
|
+
});
|
|
494
|
+
if (error) throw new Error(error.message);
|
|
495
|
+
return data;
|
|
496
|
+
}
|
|
497
|
+
|
|
498
|
+
export async function endEvent({ code, device_id, supabaseUrl, supabaseKey }) {
|
|
499
|
+
const sb = getClient(supabaseUrl, supabaseKey);
|
|
500
|
+
const { data, error } = await sb.rpc("end_event", { p_code: code, p_device_id: device_id });
|
|
501
|
+
if (error) throw new Error(error.message);
|
|
502
|
+
return data;
|
|
503
|
+
}
|
|
504
|
+
|
|
505
|
+
export async function eventCheckin({ code, device_id, lat, lng, supabaseUrl, supabaseKey }) {
|
|
506
|
+
const sb = getClient(supabaseUrl, supabaseKey);
|
|
507
|
+
const fuzzy = (lat != null && lng != null) ? fuzzyCoord(lat, lng) : { lat: null, lng: null };
|
|
508
|
+
const { data, error } = await sb.rpc("event_checkin", {
|
|
509
|
+
p_code: code, p_device_id: device_id,
|
|
510
|
+
p_lat: fuzzy.lat, p_lng: fuzzy.lng,
|
|
481
511
|
});
|
|
482
512
|
if (error) throw new Error(error.message);
|
|
483
513
|
return data;
|
|
@@ -18,6 +18,8 @@ from .tools import (
|
|
|
18
18
|
handle_event_create,
|
|
19
19
|
handle_event_join,
|
|
20
20
|
handle_event_scan,
|
|
21
|
+
handle_event_end,
|
|
22
|
+
handle_event_checkin,
|
|
21
23
|
_sb,
|
|
22
24
|
_device_id,
|
|
23
25
|
_my_device_ids,
|
|
@@ -34,6 +36,8 @@ from .schemas import (
|
|
|
34
36
|
EVENT_CREATE_SCHEMA,
|
|
35
37
|
EVENT_JOIN_SCHEMA,
|
|
36
38
|
EVENT_SCAN_SCHEMA,
|
|
39
|
+
EVENT_END_SCHEMA,
|
|
40
|
+
EVENT_CHECKIN_SCHEMA,
|
|
37
41
|
)
|
|
38
42
|
import re
|
|
39
43
|
import time
|
|
@@ -61,6 +65,8 @@ def register(ctx):
|
|
|
61
65
|
ctx.register_tool("antenna_event_create", EVENT_CREATE_SCHEMA, handle_event_create)
|
|
62
66
|
ctx.register_tool("antenna_event_join", EVENT_JOIN_SCHEMA, handle_event_join)
|
|
63
67
|
ctx.register_tool("antenna_event_scan", EVENT_SCAN_SCHEMA, handle_event_scan)
|
|
68
|
+
ctx.register_tool("antenna_event_end", EVENT_END_SCHEMA, handle_event_end)
|
|
69
|
+
ctx.register_tool("antenna_event_checkin", EVENT_CHECKIN_SCHEMA, handle_event_checkin)
|
|
64
70
|
|
|
65
71
|
# āā Hook: auto-detect location + check web GPS events āāāāāāāāā
|
|
66
72
|
def on_pre_llm(messages, **kwargs):
|
|
@@ -176,7 +176,7 @@ EVENT_CREATE_SCHEMA = {
|
|
|
176
176
|
"name": "antenna_event_create",
|
|
177
177
|
"description": (
|
|
178
178
|
"Create an event. Returns a shareable link (antenna.fyi/e/CODE) "
|
|
179
|
-
"for participants to join."
|
|
179
|
+
"for participants to join. Optionally include a description and OG image URL."
|
|
180
180
|
),
|
|
181
181
|
"parameters": {
|
|
182
182
|
"type": "object",
|
|
@@ -188,6 +188,8 @@ EVENT_CREATE_SCHEMA = {
|
|
|
188
188
|
"lng": {"type": "number", "description": "Event longitude"},
|
|
189
189
|
"starts_at": {"type": "string", "description": "Start time ISO"},
|
|
190
190
|
"ends_at": {"type": "string", "description": "End time ISO"},
|
|
191
|
+
"description": {"type": "string", "description": "Event description"},
|
|
192
|
+
"og_image": {"type": "string", "description": "OG image URL for social sharing"},
|
|
191
193
|
},
|
|
192
194
|
"required": ["name", "sender_id", "channel"],
|
|
193
195
|
},
|
|
@@ -220,3 +222,33 @@ EVENT_SCAN_SCHEMA = {
|
|
|
220
222
|
"required": ["code", "sender_id", "channel"],
|
|
221
223
|
},
|
|
222
224
|
}
|
|
225
|
+
|
|
226
|
+
EVENT_END_SCHEMA = {
|
|
227
|
+
"name": "antenna_event_end",
|
|
228
|
+
"description": "End an event. Only the creator can end it.",
|
|
229
|
+
"parameters": {
|
|
230
|
+
"type": "object",
|
|
231
|
+
"properties": {
|
|
232
|
+
"code": {"type": "string", "description": "Event code"},
|
|
233
|
+
"sender_id": {"type": "string", "description": "The sender's user ID"},
|
|
234
|
+
"channel": {"type": "string", "description": "Platform name"},
|
|
235
|
+
},
|
|
236
|
+
"required": ["code", "sender_id", "channel"],
|
|
237
|
+
},
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
EVENT_CHECKIN_SCHEMA = {
|
|
241
|
+
"name": "antenna_event_checkin",
|
|
242
|
+
"description": "Check in at an event \u2014 marks you as present at the event location. Optionally updates GPS.",
|
|
243
|
+
"parameters": {
|
|
244
|
+
"type": "object",
|
|
245
|
+
"properties": {
|
|
246
|
+
"code": {"type": "string", "description": "Event code"},
|
|
247
|
+
"sender_id": {"type": "string", "description": "The sender's user ID"},
|
|
248
|
+
"channel": {"type": "string", "description": "Platform name"},
|
|
249
|
+
"lat": {"type": "number", "description": "Latitude (optional)"},
|
|
250
|
+
"lng": {"type": "number", "description": "Longitude (optional)"},
|
|
251
|
+
},
|
|
252
|
+
"required": ["code", "sender_id", "channel"],
|
|
253
|
+
},
|
|
254
|
+
}
|
|
@@ -379,6 +379,10 @@ def handle_event_create(params: dict) -> str:
|
|
|
379
379
|
rpc_params["p_starts_at"] = params["starts_at"]
|
|
380
380
|
if params.get("ends_at"):
|
|
381
381
|
rpc_params["p_ends_at"] = params["ends_at"]
|
|
382
|
+
if params.get("description"):
|
|
383
|
+
rpc_params["p_description"] = params["description"]
|
|
384
|
+
if params.get("og_image"):
|
|
385
|
+
rpc_params["p_og_image"] = params["og_image"]
|
|
382
386
|
|
|
383
387
|
resp = sb.rpc("create_event", rpc_params).execute()
|
|
384
388
|
data = resp.data or {}
|
|
@@ -459,3 +463,38 @@ def handle_bind(params: dict) -> str:
|
|
|
459
463
|
"url": f"{BASE_URL}/locate?token={token}",
|
|
460
464
|
"message": "åéčæäøŖé¾ę„ē»ēØę·ļ¼åØęęŗęµč§åØęå¼å³åÆå
±äŗ«ä½ē½®ć",
|
|
461
465
|
})
|
|
466
|
+
|
|
467
|
+
|
|
468
|
+
def handle_event_end(params: dict) -> str:
|
|
469
|
+
sb = _sb()
|
|
470
|
+
did = _device_id(params["sender_id"], params["channel"])
|
|
471
|
+
|
|
472
|
+
resp = sb.rpc("end_event", {
|
|
473
|
+
"p_code": params["code"],
|
|
474
|
+
"p_device_id": did,
|
|
475
|
+
}).execute()
|
|
476
|
+
data = resp.data or {}
|
|
477
|
+
|
|
478
|
+
if data.get("ended"):
|
|
479
|
+
return _ok({"ended": True, "message": f"ę“»åØå·²ē»ęć"})
|
|
480
|
+
return _ok({"ended": False, "error": data.get("error", "ē»ęę“»åØå¤±č“„")})
|
|
481
|
+
|
|
482
|
+
|
|
483
|
+
def handle_event_checkin(params: dict) -> str:
|
|
484
|
+
sb = _sb()
|
|
485
|
+
did = _device_id(params["sender_id"], params["channel"])
|
|
486
|
+
|
|
487
|
+
lat = params.get("lat")
|
|
488
|
+
lng = params.get("lng")
|
|
489
|
+
if lat is not None and lng is not None:
|
|
490
|
+
flat, flng = _fuzzy(lat, lng)
|
|
491
|
+
else:
|
|
492
|
+
flat, flng = None, None
|
|
493
|
+
|
|
494
|
+
resp = sb.rpc("event_checkin", {
|
|
495
|
+
"p_code": params["code"],
|
|
496
|
+
"p_device_id": did,
|
|
497
|
+
"p_lat": flat,
|
|
498
|
+
"p_lng": flng,
|
|
499
|
+
}).execute()
|
|
500
|
+
return _ok(resp.data or {})
|
package/lib/mcp.js
CHANGED
|
@@ -14,6 +14,8 @@ import {
|
|
|
14
14
|
createBindToken,
|
|
15
15
|
discover,
|
|
16
16
|
createEvent,
|
|
17
|
+
endEvent,
|
|
18
|
+
eventCheckin,
|
|
17
19
|
joinEvent,
|
|
18
20
|
eventScan,
|
|
19
21
|
deriveDeviceId,
|
|
@@ -233,10 +235,30 @@ export async function startMcpServer() {
|
|
|
233
235
|
lng: z.number().optional().describe("Event longitude"),
|
|
234
236
|
starts_at: z.string().optional().describe("Start time ISO string"),
|
|
235
237
|
ends_at: z.string().optional().describe("End time ISO string"),
|
|
238
|
+
description: z.string().optional().describe("Event description"),
|
|
239
|
+
og_image: z.string().optional().describe("OG image URL for social sharing"),
|
|
236
240
|
},
|
|
237
|
-
async ({ name, sender_id, channel, lat, lng, starts_at, ends_at }) => {
|
|
241
|
+
async ({ name, sender_id, channel, lat, lng, starts_at, ends_at, description, og_image }) => {
|
|
238
242
|
try {
|
|
239
|
-
const result = await createEvent({ name, lat, lng, device_id: deriveDeviceId(sender_id, channel), starts_at, ends_at });
|
|
243
|
+
const result = await createEvent({ name, lat, lng, device_id: deriveDeviceId(sender_id, channel), starts_at, ends_at, description, og_image });
|
|
244
|
+
return jsonResult(result);
|
|
245
|
+
} catch (e) { return jsonResult({ error: e.message }); }
|
|
246
|
+
}
|
|
247
|
+
);
|
|
248
|
+
|
|
249
|
+
// āāā antenna_event_end āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā
|
|
250
|
+
|
|
251
|
+
server.tool(
|
|
252
|
+
"antenna_event_end",
|
|
253
|
+
"End an event. Only the creator can end it.",
|
|
254
|
+
{
|
|
255
|
+
code: z.string().describe("Event code"),
|
|
256
|
+
sender_id: z.string().describe("The sender's user ID"),
|
|
257
|
+
channel: z.string().describe("Channel name"),
|
|
258
|
+
},
|
|
259
|
+
async ({ code, sender_id, channel }) => {
|
|
260
|
+
try {
|
|
261
|
+
const result = await endEvent({ code, device_id: deriveDeviceId(sender_id, channel) });
|
|
240
262
|
return jsonResult(result);
|
|
241
263
|
} catch (e) { return jsonResult({ error: e.message }); }
|
|
242
264
|
}
|
|
@@ -260,6 +282,26 @@ export async function startMcpServer() {
|
|
|
260
282
|
}
|
|
261
283
|
);
|
|
262
284
|
|
|
285
|
+
// āāā antenna_event_checkin āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā
|
|
286
|
+
|
|
287
|
+
server.tool(
|
|
288
|
+
"antenna_event_checkin",
|
|
289
|
+
"Check in at an event ā marks you as present at the event location. Optionally updates GPS.",
|
|
290
|
+
{
|
|
291
|
+
code: z.string().describe("Event code"),
|
|
292
|
+
sender_id: z.string().describe("The sender's user ID"),
|
|
293
|
+
channel: z.string().describe("Channel name"),
|
|
294
|
+
lat: z.number().optional().describe("Latitude (optional)"),
|
|
295
|
+
lng: z.number().optional().describe("Longitude (optional)"),
|
|
296
|
+
},
|
|
297
|
+
async ({ code, sender_id, channel, lat, lng }) => {
|
|
298
|
+
try {
|
|
299
|
+
const result = await eventCheckin({ code, device_id: deriveDeviceId(sender_id, channel), lat, lng });
|
|
300
|
+
return jsonResult(result);
|
|
301
|
+
} catch (e) { return jsonResult({ error: e.message }); }
|
|
302
|
+
}
|
|
303
|
+
);
|
|
304
|
+
|
|
263
305
|
// āāā antenna_event_scan āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā
|
|
264
306
|
|
|
265
307
|
server.tool(
|
package/package.json
CHANGED
package/skill/SKILL.md
CHANGED
|
@@ -66,11 +66,12 @@ cron 设å®åļ¼é®ēØę·äøå„ļ¼
|
|
|
66
66
|
## Tools
|
|
67
67
|
|
|
68
68
|
### `antenna_scan`
|
|
69
|
-
Scan for nearby people
|
|
69
|
+
Scan for nearby people **and events**. Returns raw profile cards + active events within 5km.
|
|
70
70
|
- `lat`, `lng`: coordinates (from `LocationLat`/`LocationLon` context, or geocoded from user input)
|
|
71
|
-
- `radius_m`: search radius in meters (default 500, max 1000)
|
|
71
|
+
- `radius_m`: search radius in meters (default 500, max 1000) for people; events search uses 5km
|
|
72
72
|
- `sender_id`: the user's id from message context
|
|
73
73
|
- `channel`: the channel name (telegram, whatsapp, discord, etc.)
|
|
74
|
+
- Returns `profiles` (nearby people) + `nearby_events` (active events with name, participants count, code)
|
|
74
75
|
|
|
75
76
|
After receiving the nearby profiles, **you decide** who to recommend:
|
|
76
77
|
- Use everything you know about the user: their SOUL.md, memory, recent conversations, interests, current mood
|
|
@@ -278,6 +279,13 @@ Create an event. Returns a shareable link (antenna.fyi/e/CODE).
|
|
|
278
279
|
- `sender_id`, `channel`: from context
|
|
279
280
|
- `lat`, `lng`: optional event location
|
|
280
281
|
- `starts_at`, `ends_at`: optional time range (default: now to +12h)
|
|
282
|
+
- `description`: optional event description
|
|
283
|
+
- `og_image`: optional OG image URL for social sharing preview
|
|
284
|
+
|
|
285
|
+
### `antenna_event_end`
|
|
286
|
+
End an event. Only the creator can end it.
|
|
287
|
+
- `code`: event code
|
|
288
|
+
- `sender_id`, `channel`: from context
|
|
281
289
|
|
|
282
290
|
### `antenna_event_join`
|
|
283
291
|
Join an event by code.
|
|
@@ -289,3 +297,9 @@ Scan people in an event. No distance limit ā returns all participants.
|
|
|
289
297
|
- `code`: event code
|
|
290
298
|
- `sender_id`, `channel`: from context
|
|
291
299
|
- Returns profiles with `source: "event"` tag
|
|
300
|
+
|
|
301
|
+
### `antenna_event_checkin`
|
|
302
|
+
Check in at an event ā marks you as present at the event location. Optionally updates GPS.
|
|
303
|
+
- `code`: event code
|
|
304
|
+
- `sender_id`, `channel`: from context
|
|
305
|
+
- `lat`, `lng`: optional GPS coordinates
|