Nostr的Python库。
项目描述
pynostr
CI/CD | |
包 |
为Nostr编写的Python库。
此库使用coincurve而不是secp256k1,因此pynostr可以在Windows上使用。pynostr最初是python-nostr的一个分支,现在已独立开发。
此库与python >= 3.7兼容
功能
NIPs 列出了特定中继实现的实例。
- NIP-01:基本协议流程描述
- NIP-02:联系人列表和昵称
- NIP-03:事件的开源时间戳证明
- NIP-04:加密直接消息
- NIP-05:将Nostr密钥映射到基于DNS的互联网标识符
- NIP-06:从助记词种子短语派生基本密钥
- NIP-08:处理提及
- NIP-09:事件删除
- NIP-10:客户端在文本事件中使用e和p标签的约定
- NIP-11:中继信息文档
- NIP-12:通用标签查询
- NIP-13:工作量证明
- NIP-14:文本事件中的主题标签
- NIP-15:存储事件结束通知
- NIP-16:事件处理
- NIP-19:bech32编码实体
- NIP-20:命令结果
- NIP-21:nostr:URL方案
- NIP-22:事件created_at限制
- NIP-23:长格式内容
- NIP-25: 反应
- NIP-26: 委托事件签名
- NIP-28: 公共聊天
- NIP-33: 参数化可替换事件
- NIP-36: 敏感内容
- NIP-40: 过期时间戳
- NIP-42: 客户端到中继的认证
- NIP-46: Nostr Connect
- NIP-50: 关键词过滤器
- NIP-56: 报告
- NIP-57: Lightning Zaps
- NIP-58: 徽章
- NIP-65: 中继列表元数据
与python-nostr的差异
- tornado网络WebSocket
- coincurve secp256k1实现
- 无代理
- 无ssl_options
- 中继可用于打开到中继的连接
python-nostr | pynostr |
---|---|
过滤器 | 过滤器 |
过滤器 | 过滤器列表 |
relay_manager.open_connections | relay_manager.run_sync() |
relay_manager.close_connections() | - |
private_key.sign_event(event) | event.sign(private_key.hex()) |
安装
pip install pynostr
支持websocket-client
pip install pynostr[websocket-client]
在android的termux内部可以安装必要的coincurve
pkg update
pkg install build-essential
pkg install binutils
pkg install python-cryptography
pip install coincurve --no-binary all
使用方法
生成密钥
from pynostr.key import PrivateKey
private_key = PrivateKey()
public_key = private_key.public_key
print(f"Private key: {private_key.bech32()}")
print(f"Public key: {public_key.bech32()}")
连接到中继
from pynostr.relay_manager import RelayManager
from pynostr.filters import FiltersList, Filters
from pynostr.event import EventKind
import time
import uuid
relay_manager = RelayManager(timeout=2)
relay_manager.add_relay("wss://nostr-pub.wellorder.net")
relay_manager.add_relay("wss://relay.damus.io")
filters = FiltersList([Filters(kinds=[EventKind.TEXT_NOTE], limit=100)])
subscription_id = uuid.uuid1().hex
relay_manager.add_subscription_on_all_relays(subscription_id, filters)
relay_manager.run_sync()
while relay_manager.message_pool.has_notices():
notice_msg = relay_manager.message_pool.get_notice()
print(notice_msg.content)
while relay_manager.message_pool.has_events():
event_msg = relay_manager.message_pool.get_event()
print(event_msg.event.content)
relay_manager.close_all_relay_connections()
连接到单个中继
from pynostr.relay import Relay
from pynostr.filters import FiltersList, Filters
from pynostr.event import EventKind
from pynostr.base_relay import RelayPolicy
from pynostr.message_pool import MessagePool
import tornado.ioloop
from tornado import gen
import time
import uuid
message_pool = MessagePool(first_response_only=False)
policy = RelayPolicy()
io_loop = tornado.ioloop.IOLoop.current()
r = Relay(
"wss://relay.damus.io",
message_pool,
io_loop,
policy,
timeout=2
)
filters = FiltersList([Filters(kinds=[EventKind.TEXT_NOTE], limit=100)])
subscription_id = uuid.uuid1().hex
r.add_subscription(subscription_id, filters)
try:
io_loop.run_sync(r.connect)
except gen.Return:
pass
io_loop.stop()
while message_pool.has_notices():
notice_msg = message_pool.get_notice()
print(notice_msg.content)
while message_pool.has_events():
event_msg = message_pool.get_event()
print(event_msg.event.content)
发布到中继
import json
import ssl
import time
import uuid
from pynostr.event import Event
from pynostr.relay_manager import RelayManager
from pynostr.filters import FiltersList, Filters
from pynostr.message_type import ClientMessageType
from pynostr.key import PrivateKey
relay_manager = RelayManager(timeout=6)
relay_manager.add_relay("wss://nostr-pub.wellorder.net")
relay_manager.add_relay("wss://relay.damus.io")
private_key = PrivateKey()
filters = FiltersList([Filters(authors=[private_key.public_key.hex()], limit=100)])
subscription_id = uuid.uuid1().hex
relay_manager.add_subscription_on_all_relays(subscription_id, filters)
event = Event("Hello Nostr")
event.sign(private_key.hex())
relay_manager.publish_event(event)
relay_manager.run_sync()
time.sleep(5) # allow the messages to send
while relay_manager.message_pool.has_ok_notices():
ok_msg = relay_manager.message_pool.get_ok_notice()
print(ok_msg)
while relay_manager.message_pool.has_events():
event_msg = relay_manager.message_pool.get_event()
print(event_msg.event.to_dict())
回复笔记
from pynostr.event import Event
reply = Event(
content="Sounds good!",
)
# create 'e' tag reference to the note you're replying to
reply.add_event_ref(original_note_id)
# create 'p' tag reference to the pubkey you're replying to
reply.add_pubkey_ref(original_note_author_pubkey)
reply.sign(private_key.hex())
发送私聊
from pynostr.encrypted_dm import EncryptedDirectMessage
from pynostr.key import PrivateKey
private_key = PrivateKey()
recipient_pubkey = PrivateKey().public_key.hex()
dm = EncryptedDirectMessage()
dm.encrypt(private_key.hex(),
recipient_pubkey=recipient_pubkey,
cleartext_content="Secret message!"
)
dm_event = dm.to_event()
dm_event.sign(private_key.hex())
NIP-26委托
from pynostr.delegation import Delegation
from pynostr.event import EventKind, Event
from pynostr.key import PrivateKey
# Load your "identity" PK that you'd like to keep safely offline
identity_pk = PrivateKey.from_nsec("nsec1...")
# Create a new, disposable PK as the "delegatee" that can be "hot" in a Nostr client
delegatee_pk = PrivateKey()
# the "identity" PK will authorize "delegatee" to sign TEXT_NOTEs on its behalf for the next month
delegation = Delegation(
delegator_pubkey=identity_pk.public_key.hex(),
delegatee_pubkey=delegatee_pk.public_key.hex(),
event_kind=EventKind.TEXT_NOTE,
duration_secs=30*24*60*60
)
identity_pk.sign_delegation(delegation)
event = Event(
"Hello, NIP-26!",
tags=[delegation.get_tag()],
)
event.sign(self.delegatee_pk.hex())
# ...normal broadcast steps...
NIP-13:工作量证明
from pynostr.event import Event
from pynostr.pow import PowEvent
pe = PowEvent(difficulty=25)
e=Event()
e=pe.mine(e)
assert pe.check_difficulty(e)
测试套件
设置测试环境
安装测试运行器依赖项
pip3 install -r test-requirements.txt
然后通过安装本地开发目录作为可编辑模块,使pynostr python模块对测试可见/可导入
# from the repo root
pip3 install -e .
运行测试套件
运行整个测试套件
# from the repo root
pytest
运行特定的测试文件
pytest test/test_this_file.py
运行特定的测试
pytest test/test_this_file.py::test_this_specific_test
使用tox运行测试
安装tox
pip install tox
运行测试
tox
pre-commit配置
安装
$ pip install pre-commit
使用homebrew
$ brew install pre-commit
$ pre-commit --version
pre-commit 2.10.0
安装git钩子脚本
$ pre-commit install
针对所有文件运行
pre-commit run --all-files
pre-commit run --show-diff-on-failure --color=always --all-files
更新pre-commit yaml中的包版本
pre-commit autoupdate
pre-commit run --show-diff-on-failure --color=always --all-files
项目详情
下载文件
下载适用于您平台的文件。如果您不确定选择哪个,请了解更多关于安装包的信息。
源分发
pynostr-0.6.2.tar.gz (52.3 kB 查看哈希值)
构建分发
pynostr-0.6.2-py3-none-any.whl (36.3 kB 查看哈希值)
关闭
pynostr-0.6.2.tar.gz的哈希值
算法 | 哈希摘要 | |
---|---|---|
SHA256 | 2974ea05b3ff41a1a4060e3b1813eb0ce0e60c0b81fbe668afaa65164c7f82f4 |
|
MD5 | aa7b075fc00e60186f6a9369259a8b81 |
|
BLAKE2b-256 | 08b6818c072bd98c6472c305fa0ce9822592a3c8601ebe550b02465404fa629b |
关闭
pynostr-0.6.2-py3-none-any.whl的哈希值
算法 | 哈希摘要 | |
---|---|---|
SHA256 | d43fb236c73174093275ee0080b2f8ed17e974b2b516f0d73da4c9a3e908ddc5 |
|
MD5 | bdcf3732218a4cf35a23093cce0afc6a |
|
BLAKE2b-256 | 674cd76378abc44c15375708cb3eb8ee9f199879b905b4c2ceda9ea108dfae79 |