getRepeaterBook() output is misaligned - RepeaterBook added a new leading column, breaking the hardcoded 11-cell stride #141

Closed
opened 2026-10-05 01:25:38 +02:00 by adam · 1 comment
Owner

Describe the bug

getRepeaterBook() in modules/locationdata.py assumes each repeater entry in RepeaterBook's results table is exactly 11 <td> cells wide, and reads fields at fixed offsets (i+0 through i+9) from that assumption. RepeaterBook's table now has 12 cells per row (an extra leading, unlabeled column - likely a checkbox for a "compare" feature added after this scraper was written). This shifts every field read by one position, and the misalignment compounds by one additional cell per repeater since the loop advances by a fixed 11 instead of the real 12 - so entry 1 is off by 1 cell, entry 2 by 2 cells, entry 3 by 3 cells, etc.

To Reproduce

  1. Enable repeaterLookup = rbook with a Canadian location whose Maidenhead grid starts with a letter pair that's also used by the US-endpoint routing logic (e.g. EN, FN - these bands span both southern Ontario and the northern US)
  2. Send rlist
  3. Output looks like garbled/nonsensical text mixing frequencies, tones, and place names together

Evidence

Fetching the bot's actual live URL directly and inspecting the real table structure:

Header columns (11 labeled): ['', 'Freq', 'Offset', 'Access', 'Call', 'Location', 'ST/PR', 'Use', 'Mode', 'Mi', 'Status']
First data row (12 raw cells):
  [0] ''
  [1] '444.9500'
  [2] '+5.0 MHz'
  [3] 'CC 1 NAC 293 156.7'
  [4] 'VE3UHF'
  [5] 'Hanover'
  [6] 'ON'
  [7] 'OPEN'
  [8] 'FM DMR DSTAR P-25'
  [9] '8.06'
  [10] 'NE'
  [11] (status icon)

Reconstructing the bot's current output formula against this real row confirms the exact bug:

f"{cells[3]}📶{cells[0]}{cells[1]},{cells[2]}.{cells[7]}"
= "CC 1 NAC 293 156.7" + "📶" + "" + "444.9500" + "," + "+5.0 MHz" + "." + "OPEN"

This is an exact match to real bot output: CC 1 NAC 293 156.7📶444.9500,+5.0 MHz.OPEN - so the DMR/NXDN access-tone field is being displayed as if it were the call sign, while the real call sign (VE3UHF) silently lands in the unused location field slot instead.

Expected behavior

Output should correctly show call sign, frequency, offset, tone, and mode for each repeater, matching what's actually on RepeaterBook's page.

Suggested fix

In getRepeaterBook(), update the stride from 11 to 12 and shift every field index by +1 to match the real current column order:

for i in range(0, len(cells), 12):
    if i + 11 < len(cells):
        repeater = {
            'frequency': cells[i + 1].text.strip() if i + 1 < len(cells) else 'N/A',
            'offset': cells[i + 2].text.strip() if i + 2 < len(cells) else 'N/A',
            'tone': cells[i + 3].text.strip() if i + 3 < len(cells) else 'N/A',
            'call_sign': cells[i + 4].text.strip() if i + 4 < len(cells) else 'N/A',
            'location': cells[i + 5].text.strip() if i + 5 < len(cells) else 'N/A',
            'state': cells[i + 6].text.strip() if i + 6 < len(cells) else 'N/A',
            'use': cells[i + 7].text.strip() if i + 7 < len(cells) else 'N/A',
            'mode': cells[i + 8].text.strip() if i + 8 < len(cells) else 'N/A',
            'distance': cells[i + 9].text.strip() if i + 9 < len(cells) else 'N/A',
            'direction': cells[i + 10].text.strip() if i + 10 < len(cells) else 'N/A'
        }
        data.append(repeater)

Since RepeaterBook could change their table layout again in the future, it may also be worth matching columns by the <thead> header text instead of a hardcoded numeric offset, so this doesn't silently break again on the next site update.

Additional context

Also worth noting separately (not necessarily a bug, just an observation): the US vs international endpoint routing (grid[:2] in [...]) uses Maidenhead grid letter pairs to guess US vs elsewhere, but grid letters are purely geographic and don't respect national borders - e.g. EN and FN cover parts of both southern Ontario and the northern US. This happens to still return valid Canadian repeaters via the US endpoint in this case, but may be worth a closer look for correctness in border regions.

**Describe the bug** `getRepeaterBook()` in `modules/locationdata.py` assumes each repeater entry in RepeaterBook's results table is exactly 11 `<td>` cells wide, and reads fields at fixed offsets (i+0 through i+9) from that assumption. RepeaterBook's table now has **12 cells per row** (an extra leading, unlabeled column - likely a checkbox for a "compare" feature added after this scraper was written). This shifts every field read by one position, and the misalignment **compounds by one additional cell per repeater** since the loop advances by a fixed 11 instead of the real 12 - so entry 1 is off by 1 cell, entry 2 by 2 cells, entry 3 by 3 cells, etc. **To Reproduce** 1. Enable `repeaterLookup = rbook` with a Canadian location whose Maidenhead grid starts with a letter pair that's also used by the US-endpoint routing logic (e.g. `EN`, `FN` - these bands span both southern Ontario and the northern US) 2. Send `rlist` 3. Output looks like garbled/nonsensical text mixing frequencies, tones, and place names together **Evidence** Fetching the bot's actual live URL directly and inspecting the real table structure: ``` Header columns (11 labeled): ['', 'Freq', 'Offset', 'Access', 'Call', 'Location', 'ST/PR', 'Use', 'Mode', 'Mi', 'Status'] First data row (12 raw cells): [0] '' [1] '444.9500' [2] '+5.0 MHz' [3] 'CC 1 NAC 293 156.7' [4] 'VE3UHF' [5] 'Hanover' [6] 'ON' [7] 'OPEN' [8] 'FM DMR DSTAR P-25' [9] '8.06' [10] 'NE' [11] (status icon) ``` Reconstructing the bot's current output formula against this real row confirms the exact bug: ```python f"{cells[3]}📶{cells[0]}{cells[1]},{cells[2]}.{cells[7]}" = "CC 1 NAC 293 156.7" + "📶" + "" + "444.9500" + "," + "+5.0 MHz" + "." + "OPEN" ``` This is an exact match to real bot output: `CC 1 NAC 293 156.7📶444.9500,+5.0 MHz.OPEN` - so the DMR/NXDN access-tone field is being displayed as if it were the call sign, while the real call sign (VE3UHF) silently lands in the unused `location` field slot instead. **Expected behavior** Output should correctly show call sign, frequency, offset, tone, and mode for each repeater, matching what's actually on RepeaterBook's page. **Suggested fix** In `getRepeaterBook()`, update the stride from 11 to 12 and shift every field index by +1 to match the real current column order: ```python for i in range(0, len(cells), 12): if i + 11 < len(cells): repeater = { 'frequency': cells[i + 1].text.strip() if i + 1 < len(cells) else 'N/A', 'offset': cells[i + 2].text.strip() if i + 2 < len(cells) else 'N/A', 'tone': cells[i + 3].text.strip() if i + 3 < len(cells) else 'N/A', 'call_sign': cells[i + 4].text.strip() if i + 4 < len(cells) else 'N/A', 'location': cells[i + 5].text.strip() if i + 5 < len(cells) else 'N/A', 'state': cells[i + 6].text.strip() if i + 6 < len(cells) else 'N/A', 'use': cells[i + 7].text.strip() if i + 7 < len(cells) else 'N/A', 'mode': cells[i + 8].text.strip() if i + 8 < len(cells) else 'N/A', 'distance': cells[i + 9].text.strip() if i + 9 < len(cells) else 'N/A', 'direction': cells[i + 10].text.strip() if i + 10 < len(cells) else 'N/A' } data.append(repeater) ``` Since RepeaterBook could change their table layout again in the future, it may also be worth matching columns by the `<thead>` header text instead of a hardcoded numeric offset, so this doesn't silently break again on the next site update. **Additional context** Also worth noting separately (not necessarily a bug, just an observation): the US vs international endpoint routing (`grid[:2] in [...]`) uses Maidenhead grid letter pairs to guess US vs elsewhere, but grid letters are purely geographic and don't respect national borders - e.g. `EN` and `FN` cover parts of both southern Ontario and the northern US. This happens to still return valid Canadian repeaters via the US endpoint in this case, but may be worth a closer look for correctness in border regions. <!-- github-sync-id:5166098617 -->
adam closed this issue 2026-10-05 01:25:38 +02:00
Author
Owner

nice, thanks! the grid issue is tricky in these dense areas
patch in

nice, thanks! the grid issue is tricky in these dense areas patch in <!-- github-comment-id:5309559882 -->
Sign in to join this conversation.
No labels
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: adam/meshing-around#141