holgern / pynostr

Python library for nostr
MIT License
69 stars 16 forks source link

Best way to monitor mentions? #3

Open steveboi123 opened 1 year ago

steveboi123 commented 1 year ago

I want to monitor pubkey_refs for a single pubkey, and print the event as soon as it happens. What's the best way to implement this, it seems like there's no obvious best way. The only way I can think of is to keep updating the since param in filters, and closing and adding subscriptions while doing run_sync() in a loop. Or else, I keep getting the same events.

Should I do something like this, or is there a better way?:

start_time = int(time.time())
subscription_id = "abc"
While True:
    filters = FiltersList([  # enter filter condition
        Filters(
            since=start_time,
            kinds=[EventKind.TEXT_NOTE],
            pubkey_refs=[nostr_pubkey,]
        )
    ])

    relay_manager.add_subscription_on_all_relays(subscription_id, filters)
    relay_manager.run_sync()
    time.sleep(5)
    while relay_manager.message_pool.has_events():
        event_msg = relay_manager.message_pool.get_event()
        print(event_msg.event.content)

    start_time = int(time.time())
    relay_manager.close_subscription_on_all_relays(subscription_id)

Doesn't seem like a great way to me to be honest.

Also, related: how do I prevent duplicate events being sent from all the relays I'm connected to? I'd like to just receive an event once.

EDIT: I tested the above method and it doesn't even work. So I'm not sure how to do this.

Bashy commented 1 year ago

How about some async coroutines?

steveboi123 commented 1 year ago

How about some async coroutines?

@Bashy Can you please provide an example. I've never wrote something like that before.

Bashy commented 1 year ago

@steveboi123 I've just discovered this repo yesterday, I might try to make an async coroutine to read some notes, I'll keep you updated here if I manage to do it properly.

holgern commented 1 year ago

This library is work in progress and i'm still figuring things out.

I improved the handling of subscriptions in the new 0.6.0 release.

steveboi123 commented 1 year ago

@holgern do you mind providing a snippet to do this task? I appreciate your work on this library because I think the implementation with tornado will make the connections more stable.

holgern commented 1 year ago

@steveboi123 I have added a working example in commit 62aed543cd45cd4527b0ef662b313589c4a27a4c

timeout=0,close_on_eose=False, message_callback=print_message

needs to be set in either add_relay or in add_relay_list function of relay manager.

When timeout=0 and close_on_eose=False is set, the connection will not stop when an eose is received. The connection remains open forever and whenever a new event is received that matches the filter it goes through the message_callback function.

As the websocket is not closed, the run_sync() function will run forever.

holgern commented 1 year ago

I will think on how this can be improved, right now the URL of the relay is missing which has received the event.

steveboi123 commented 1 year ago

@holgern thank you. How do you recommend I don't call print_message multiple times for a single event?

This library uses a MessagePool class that keeps track of unique events.

steveboi123 commented 1 year ago

It seems that setting first_response_only=True in this library doesn't work. I think this is a bug. message_callback should be implemented in message_pool.py, not base_relay.py, because that way it knows if it's a unique event or not.

P.S. Why did you use the @gen.coroutine decorator on the print_message function? Seems like it's not an async one.

steveboi123 commented 1 year ago

@holgern just wondering if you plan to work on this library (deciding which library to go with).

My use case is I want to monitor mentions and then reply to the mention.

However from the monitor_mentions.py example, it's not clear how to:

  1. call message_callback only once per event
  2. reply to the event