Populate chat metadata for unknown nodes (#182)

* Populate chat metadata for unknown nodes

* run rufo

* fix comments

* run rufo
This commit is contained in:
l5y
2025-09-26 16:45:42 +02:00
committed by GitHub
parent 9e62621819
commit 3863e2d63d
2 changed files with 70 additions and 7 deletions
+11 -6
View File
@@ -585,7 +585,7 @@ end
# @param node_ref [Object] raw identifier extracted from the payload.
# @param fallback_num [Object] optional numeric reference used when the
# identifier is missing.
def ensure_unknown_node(db, node_ref, fallback_num = nil)
def ensure_unknown_node(db, node_ref, fallback_num = nil, heard_time: nil)
parts = canonical_node_parts(node_ref, fallback_num)
return unless parts
@@ -598,16 +598,21 @@ def ensure_unknown_node(db, node_ref, fallback_num = nil)
return if existing
long_name = "Meshtastic #{short_id}"
heard_time = coerce_integer(heard_time)
inserted = false
with_busy_retry do
db.execute(
<<~SQL,
INSERT OR IGNORE INTO nodes(node_id,num,short_name,long_name,role)
VALUES (?,?,?,?,?)
INSERT OR IGNORE INTO nodes(node_id,num,short_name,long_name,role,last_heard,first_heard)
VALUES (?,?,?,?,?,?,?)
SQL
[node_id, node_num, short_id, long_name, "CLIENT_HIDDEN"],
[node_id, node_num, short_id, long_name, "CLIENT_HIDDEN", heard_time, heard_time],
)
inserted = db.changes.positive?
end
inserted
end
# Insert or update a node row with the most recent metrics.
@@ -849,7 +854,7 @@ def insert_position(db, payload)
canonical = normalize_node_id(db, node_id || node_num)
node_id = canonical if canonical
ensure_unknown_node(db, node_id || node_num, node_num)
ensure_unknown_node(db, node_id || node_num, node_num, heard_time: rx_time)
to_id = string_or_nil(payload["to_id"] || payload["to"])
@@ -1044,7 +1049,7 @@ def insert_message(db, m)
encrypted = string_or_nil(m["encrypted"])
ensure_unknown_node(db, from_id || raw_from_id, m["from_num"])
ensure_unknown_node(db, from_id || raw_from_id, m["from_num"], heard_time: rx_time)
row = [
msg_id,
+59 -1
View File
@@ -414,6 +414,62 @@ RSpec.describe "Potato Mesh Sinatra app" do
end
end
describe "#ensure_unknown_node" do
it "creates a hidden placeholder with timestamps for chat notifications" do
with_db do |db|
created = ensure_unknown_node(db, "!1234abcd", nil, heard_time: reference_time.to_i)
expect(created).to be_truthy
end
with_db(readonly: true) do |db|
db.results_as_hash = true
row = db.get_first_row(
<<~SQL,
SELECT short_name, long_name, role, last_heard, first_heard
FROM nodes
WHERE node_id = ?
SQL
["!1234abcd"],
)
expect(row["short_name"]).to eq("ABCD")
expect(row["long_name"]).to eq("Meshtastic ABCD")
expect(row["role"]).to eq("CLIENT_HIDDEN")
expect(row["last_heard"]).to eq(reference_time.to_i)
expect(row["first_heard"]).to eq(reference_time.to_i)
end
end
it "leaves timestamps nil when no receive time is provided" do
with_db do |db|
created = ensure_unknown_node(db, "!1111beef", nil)
expect(created).to be_truthy
end
with_db(readonly: true) do |db|
db.results_as_hash = true
row = db.get_first_row(
<<~SQL,
SELECT last_heard, first_heard
FROM nodes
WHERE node_id = ?
SQL
["!1111beef"],
)
expect(row["last_heard"]).to be_nil
expect(row["first_heard"]).to be_nil
end
end
it "returns false when the node already exists" do
with_db do |db|
expect(ensure_unknown_node(db, "!0000c0de", nil)).to be_truthy
expect(ensure_unknown_node(db, "!0000c0de", nil)).to be_falsey
end
end
end
describe "POST /api/messages" do
it "persists messages from fixture data" do
import_nodes_fixture
@@ -470,7 +526,7 @@ RSpec.describe "Potato Mesh Sinatra app" do
with_db(readonly: true) do |db|
db.results_as_hash = true
row = db.get_first_row(
"SELECT node_id, num, short_name, long_name, role FROM nodes WHERE node_id = ?",
"SELECT node_id, num, short_name, long_name, role, last_heard, first_heard FROM nodes WHERE node_id = ?",
["!feedf00d"],
)
@@ -480,6 +536,8 @@ RSpec.describe "Potato Mesh Sinatra app" do
expect(row["short_name"]).to eq("F00D")
expect(row["long_name"]).to eq("Meshtastic F00D")
expect(row["role"]).to eq("CLIENT_HIDDEN")
expect(row["last_heard"]).to eq(payload["rx_time"])
expect(row["first_heard"]).to eq(payload["rx_time"])
end
end