diff options
Diffstat (limited to 'scripts')
| -rw-r--r-- | scripts/build-pool-index.py | 18 |
1 files changed, 17 insertions, 1 deletions
diff --git a/scripts/build-pool-index.py b/scripts/build-pool-index.py index 382b6c3..d3eb386 100644 --- a/scripts/build-pool-index.py +++ b/scripts/build-pool-index.py | |||
| @@ -8,6 +8,7 @@ import html | |||
| 8 | import json | 8 | import json |
| 9 | import os | 9 | import os |
| 10 | import time | 10 | import time |
| 11 | import urllib.parse | ||
| 11 | import urllib.request | 12 | import urllib.request |
| 12 | 13 | ||
| 13 | 14 | ||
| @@ -23,6 +24,10 @@ def normalize_pool(source, obj, now): | |||
| 23 | operator = obj.get("operator", {}) | 24 | operator = obj.get("operator", {}) |
| 24 | pool = obj.get("pool", {}) | 25 | pool = obj.get("pool", {}) |
| 25 | node = obj.get("node", {}) | 26 | node = obj.get("node", {}) |
| 27 | rounds_file = operator.get("roundsFile") or "pool_rounds.json" | ||
| 28 | rounds_url = "" | ||
| 29 | if source.startswith("http://") or source.startswith("https://"): | ||
| 30 | rounds_url = urllib.parse.urljoin(source, rounds_file) | ||
| 26 | updated = int(obj.get("updatedAt") or 0) | 31 | updated = int(obj.get("updatedAt") or 0) |
| 27 | age = max(0, now - updated) if updated else None | 32 | age = max(0, now - updated) if updated else None |
| 28 | online = bool(node.get("poolRunning")) and age is not None and age <= 120 | 33 | online = bool(node.get("poolRunning")) and age is not None and age <= 120 |
| @@ -39,6 +44,8 @@ def normalize_pool(source, obj, now): | |||
| 39 | "blocksFoundSession": int(pool.get("blocksFoundSession") or 0), | 44 | "blocksFoundSession": int(pool.get("blocksFoundSession") or 0), |
| 40 | "roundShares": int(pool.get("roundShares") or 0), | 45 | "roundShares": int(pool.get("roundShares") or 0), |
| 41 | "hashRate": float(pool.get("hashRate") or 0.0), | 46 | "hashRate": float(pool.get("hashRate") or 0.0), |
| 47 | "roundsUrl": rounds_url, | ||
| 48 | "recentRounds": obj.get("recentRounds", []), | ||
| 42 | } | 49 | } |
| 43 | 50 | ||
| 44 | 51 | ||
| @@ -56,6 +63,7 @@ def render_html(pools, generated_at): | |||
| 56 | rows = [] | 63 | rows = [] |
| 57 | for p in pools: | 64 | for p in pools: |
| 58 | dash = p["dashboardUrl"] | 65 | dash = p["dashboardUrl"] |
| 66 | rounds = p.get("roundsUrl", "") | ||
| 59 | # Only linkify http(s). The dashboard URL comes from an operator's | 67 | # Only linkify http(s). The dashboard URL comes from an operator's |
| 60 | # self-published status file, so a "javascript:" or "data:" scheme | 68 | # self-published status file, so a "javascript:" or "data:" scheme |
| 61 | # would become a clickable script-injection on this public page. | 69 | # would become a clickable script-injection on this public page. |
| @@ -65,6 +73,12 @@ def render_html(pools, generated_at): | |||
| 65 | html.escape(dash, quote=True)) | 73 | html.escape(dash, quote=True)) |
| 66 | else: | 74 | else: |
| 67 | dash_html = "-" | 75 | dash_html = "-" |
| 76 | rounds_lower = rounds.lower() | ||
| 77 | if rounds_lower.startswith("http://") or rounds_lower.startswith("https://"): | ||
| 78 | rounds_html = '<a href="{0}" rel="noopener noreferrer">proof</a>'.format( | ||
| 79 | html.escape(rounds, quote=True)) | ||
| 80 | else: | ||
| 81 | rounds_html = "-" | ||
| 68 | rows.append( | 82 | rows.append( |
| 69 | "<tr>" | 83 | "<tr>" |
| 70 | "<td>{status}</td>" | 84 | "<td>{status}</td>" |
| @@ -76,6 +90,7 @@ def render_html(pools, generated_at): | |||
| 76 | "<td>{height}</td>" | 90 | "<td>{height}</td>" |
| 77 | "<td>{age}</td>" | 91 | "<td>{age}</td>" |
| 78 | "<td>{dash}</td>" | 92 | "<td>{dash}</td>" |
| 93 | "<td>{rounds}</td>" | ||
| 79 | "</tr>".format( | 94 | "</tr>".format( |
| 80 | status="online" if p["online"] else "stale", | 95 | status="online" if p["online"] else "stale", |
| 81 | name=html.escape(p["name"]), | 96 | name=html.escape(p["name"]), |
| @@ -87,6 +102,7 @@ def render_html(pools, generated_at): | |||
| 87 | height=p["height"], | 102 | height=p["height"], |
| 88 | age="{}s".format(p["ageSeconds"]) if p["ageSeconds"] is not None else "-", | 103 | age="{}s".format(p["ageSeconds"]) if p["ageSeconds"] is not None else "-", |
| 89 | dash=dash_html, | 104 | dash=dash_html, |
| 105 | rounds=rounds_html, | ||
| 90 | ) | 106 | ) |
| 91 | ) | 107 | ) |
| 92 | 108 | ||
| @@ -110,7 +126,7 @@ def render_html(pools, generated_at): | |||
| 110 | <p class="note">This directory is informational. Bitflash nodes discover pools through Nostr and .btf; this page only helps humans compare public operators.</p> | 126 | <p class="note">This directory is informational. Bitflash nodes discover pools through Nostr and .btf; this page only helps humans compare public operators.</p> |
| 111 | <table> | 127 | <table> |
| 112 | <thead> | 128 | <thead> |
| 113 | <tr><th>Status</th><th>Pool</th><th>Fee</th><th>Miners</th><th>H/s</th><th>Blocks</th><th>Height</th><th>Age</th><th>Link</th></tr> | 129 | <tr><th>Status</th><th>Pool</th><th>Fee</th><th>Miners</th><th>H/s</th><th>Blocks</th><th>Height</th><th>Age</th><th>Link</th><th>Proof</th></tr> |
| 114 | </thead> | 130 | </thead> |
| 115 | <tbody> | 131 | <tbody> |
| 116 | {rows} | 132 | {rows} |