Subscribe notifications

This commit is contained in:
koalasat
2025-07-22 19:06:03 +02:00
parent d9385ae0ea
commit ba6353a57e
4 changed files with 59 additions and 13 deletions

View File

@ -53,10 +53,10 @@ class Nostr:
Tag.parse(
[
"order_id",
f"{config("COORDINATOR_ALIAS", cast=str)}#{order.id}",
f"{config("COORDINATOR_ALIAS", cast=str).lower()}#{order.id}",
]
),
Tag.parse(["status", Order.Status(order.status).label]),
Tag.parse(["status", order.status]),
]
await client.send_private_msg(PublicKey.parse(robot.nostr_pubkey), text, tags)

View File

@ -37,7 +37,7 @@ class Notifications:
self.save_message(order, robot, title, description)
if robot.nostr_pubkey:
nostr_send_notification_event.delay(
robot_id=robot.id, order_id=order.id, text=description
robot_id=robot.id, order_id=order.id, text=title
)
if robot.telegram_enabled:
self.send_telegram_message(robot.telegram_chat_id, title, description)

View File

@ -3,6 +3,8 @@ import { Box, Drawer, List, ListItem, Typography, useTheme } from '@mui/material
import { AppContext, type UseAppStoreType } from '../../../contexts/AppContext';
import { RoboSatsTextIcon } from '../../../components/Icons';
import { useTranslation } from 'react-i18next';
import { UseFederationStoreType, FederationContext } from '../../../contexts/FederationContext';
import { GarageContext, UseGarageStoreType } from '../../../contexts/GarageContext';
interface NotificationsDrawerProps {
show: boolean;
@ -12,11 +14,25 @@ interface NotificationsDrawerProps {
const NotificationsDrawer = ({ show, setShow }: NotificationsDrawerProps): React.JSX.Element => {
const { t } = useTranslation();
const theme = useTheme();
const { page } = useContext<UseAppStoreType>(AppContext);
const { page, settings } = useContext<UseAppStoreType>(AppContext);
const { federation } = useContext<UseFederationStoreType>(FederationContext);
const { garage } = useContext<UseGarageStoreType>(GarageContext);
useEffect(() => {
setShow(false);
}, [page]);
useEffect(() => {
if (settings.connection === 'nostr' && !federation.loading) loadNotifciationsNostr();
}, [settings.connection, federation.loading]);
const loadNotifciationsNostr = (): void => {
federation.roboPool.subscribeNotifications(garage, {
onevent: (_event) => {},
oneose: () => {},
});
};
return (
<Drawer anchor='right' open={show} onClose={() => setShow(false)}>
<Box sx={{ width: 270, height: '100%' }} role='presentation'>

View File

@ -1,5 +1,5 @@
import { type Event } from 'nostr-tools';
import { type Coordinator, type Settings } from '../../models';
import { nip17, type Event } from 'nostr-tools';
import { Garage, type Coordinator, type Settings } from '../../models';
import defaultFederation from '../../../static/federation.json';
import { websocketClient, type WebsocketConnection, WebsocketState } from '../Websocket';
import thirdParties from '../../../static/thirdparties.json';
@ -100,14 +100,17 @@ class RoboPool {
}
const authors = scope.map((f) => f.nostrHexPubkey).filter((item) => item !== undefined);
const subscribeBookPending = 'subscribeBookPending';
const subscribeBookSuccess = 'subscribeBookPending';
const requestPending = [
'REQ',
'subscribeBookPending',
subscribeBookPending,
{ authors, kinds: [38383], '#s': ['pending'] },
];
const requestSuccess = [
'REQ',
'subscribeBookSuccess',
subscribeBookSuccess,
{
authors,
kinds: [38383],
@ -118,6 +121,9 @@ class RoboPool {
this.messageHandlers.push((_url: string, messageEvent: MessageEvent) => {
const jsonMessage = JSON.parse(messageEvent.data);
if (![subscribeBookPending, subscribeBookSuccess].includes(jsonMessage[1])) return;
if (jsonMessage[0] === 'EVENT') {
const event: Event = jsonMessage[2];
const network = event.tags.find((e) => e[0] === 'network');
@ -135,14 +141,18 @@ class RoboPool {
.map((f) => f.nostrHexPubkey)
.filter((item) => item !== undefined);
const subscribeRatings = `subscribeRatings${id ?? ''}`;
const requestRatings = [
'REQ',
`subscribeRatings${id ?? ''}`,
subscribeRatings,
{ kinds: [31986], '#p': pubkeys ?? defaultPubkeys, since: 1746316800 },
];
this.messageHandlers.push((_url: string, messageEvent: MessageEvent) => {
const jsonMessage = JSON.parse(messageEvent.data);
if (subscribeRatings !== jsonMessage[1]) return;
if (jsonMessage[0] === 'EVENT') {
events.onevent(jsonMessage[2]);
} else if (jsonMessage[0] === 'EOSE') {
@ -152,18 +162,38 @@ class RoboPool {
this.sendMessage(JSON.stringify(requestRatings));
};
subscribeChat = (hexPubKeys: string[], since: number, events: RoboPoolEvents): void => {
const requestRatings = ['REQ', 'subscribeChat', { kinds: [1059], '#p': hexPubKeys, since }];
subscribeNotifications = (garage: Garage, events: RoboPoolEvents): void => {
const hexPubKeys = Object.values(garage.slots).map((s) => s.nostrPubKey);
if (hexPubKeys.length === 0) return;
const subscribeChat = 'subscribeChat';
const requestNotifications = ['REQ', subscribeChat, { kinds: [1059], '#p': hexPubKeys }];
this.messageHandlers.push((_url: string, messageEvent: MessageEvent) => {
const jsonMessage = JSON.parse(messageEvent.data);
if (subscribeChat !== jsonMessage[1]) return;
if (jsonMessage[0] === 'EVENT') {
events.onevent(jsonMessage[2]);
const wrappedEvent: Event = jsonMessage[2];
console.log('wrappedEvent', wrappedEvent);
const hexPubKey = wrappedEvent.tags.find((t) => t[0] == 'p')?.[1];
const slot = Object.values(garage.slots).find((s) => s.nostrPubKey == hexPubKey);
if (slot?.nostrSecKey) {
const unwrappedEvent = nip17.unwrapEvent(wrappedEvent, slot.nostrSecKey);
events.onevent(unwrappedEvent as Event);
}
} else if (jsonMessage[0] === 'EOSE') {
events.oneose();
}
});
this.sendMessage(JSON.stringify(requestRatings));
this.sendMessage(JSON.stringify(requestNotifications));
};
sendEvent = (event: Event): void => {