|
16 | 16 | from .transaction import PartialTxOutput |
17 | 17 | from .lnurl import (decode_lnurl, request_lnurl, callback_lnurl, LNURLError, |
18 | 18 | lightning_address_to_url, try_resolve_lnurlpay, LNURL6Data, |
19 | | - LNURL3Data, LNURLData) |
| 19 | + LNURL3Data, LNURLData, SUPPORTED_LNURL_SCHEMES) |
20 | 20 | from .bitcoin import opcodes, construct_script |
21 | 21 | from .lnaddr import LnInvoiceException |
22 | 22 | from .lnutil import IncompatibleOrInsaneFeatures |
@@ -45,9 +45,25 @@ def remove_uri_prefix(data: str, *, prefix: str) -> str: |
45 | 45 | return data |
46 | 46 |
|
47 | 47 |
|
| 48 | +def maybe_extract_url_from_lud_17_uri(data: str) -> Optional[str]: |
| 49 | + """https://github.com/lnurl/luds/blob/luds/17.md""" |
| 50 | + data = data.strip() |
| 51 | + try: |
| 52 | + parsed = urllib.parse.urlsplit(data) |
| 53 | + except ValueError: |
| 54 | + return None |
| 55 | + if parsed.scheme not in SUPPORTED_LNURL_SCHEMES: |
| 56 | + return None |
| 57 | + if not (host := parsed.hostname) or not parsed.path: |
| 58 | + return None |
| 59 | + is_onion = host.endswith('.onion') |
| 60 | + url_scheme = 'http' if is_onion else 'https' |
| 61 | + return urllib.parse.urlunsplit(parsed._replace(scheme=url_scheme)) |
| 62 | + |
| 63 | + |
48 | 64 | RE_ALIAS = r'(.*?)\s*\<([0-9A-Za-z]{1,})\>' |
49 | | -RE_EMAIL = r'\b[A-Za-z0-9._%+-]+@([A-Za-z0-9-]+\.)+[A-Z|a-z]{2,7}\b' |
50 | | -RE_DOMAIN = r'\b([A-Za-z0-9-]+\.)+[A-Z|a-z]{2,7}\b' |
| 65 | +RE_EMAIL = r'\b[A-Za-z0-9._%+-]+@([A-Za-z0-9-]+\.)+[A-Za-z]{2,7}\b' |
| 66 | +RE_DOMAIN = r'\b([A-Za-z0-9-]+\.)+[A-Za-z]{2,7}\b' |
51 | 67 | RE_SCRIPT_FN = r'script\((.*)\)' |
52 | 68 |
|
53 | 69 |
|
@@ -98,6 +114,7 @@ class PaymentIdentifier(Logger): |
98 | 114 | * openalias |
99 | 115 | * bip21 URI |
100 | 116 | * lightning-URI (containing bolt11 or lnurl) |
| 117 | + * lnurl-URI (lud17 lnurlw/lnurlp URI) |
101 | 118 | * bolt11 invoice |
102 | 119 | * lnurl |
103 | 120 | * lightning address |
@@ -228,6 +245,10 @@ def parse(self, text: str): |
228 | 245 | self.logger.debug(f'Exception cause {e.args!r}') |
229 | 246 | return |
230 | 247 | self.set_state(PaymentIdentifierState.AVAILABLE) |
| 248 | + elif lnurl_url := maybe_extract_url_from_lud_17_uri(text): |
| 249 | + self._type = PaymentIdentifierType.LNURL |
| 250 | + self.lnurl = lnurl_url |
| 251 | + self.set_state(PaymentIdentifierState.NEED_RESOLVE) |
231 | 252 | elif text.lower().startswith(BITCOIN_BIP21_URI_SCHEME + ':'): |
232 | 253 | try: |
233 | 254 | out = parse_bip21_URI(text) |
|
0 commit comments