feat: support channel meetings with channel-pane-message selectors

This commit is contained in:
Oliver Hofmann
2026-05-17 13:04:20 +02:00
parent 3ff8381e5a
commit ccfe47aa35
4 changed files with 158 additions and 67 deletions
+69 -29
View File
@@ -1,14 +1,11 @@
"""Run this script once with a Teams meeting chat open.
It prints DOM info to identify selectors for messages and profile cards.
"""DOM discovery for Teams Web — meeting chat and channel posts.
Usage:
.venv/bin/python scripts/discover_dom.py [teams-chat-url]
.venv/bin/python scripts/discover_dom.py
"""
import sys
from pathlib import Path
from playwright.sync_api import sync_playwright
URL = sys.argv[1] if len(sys.argv) > 1 else "https://teams.microsoft.com"
SESSION_DIR = str(Path.home() / ".teampulse" / "session")
@@ -20,34 +17,77 @@ def main():
args=["--no-sandbox"],
)
page = browser.pages[0] if browser.pages else browser.new_page()
page.goto(URL)
print("Navigiere im Browser zu einem Meeting-Chat, dann hier Enter drücken...")
page.goto("https://teams.microsoft.com")
print("Navigiere im Browser zum Channel/Chat mit sichtbaren Nachrichten, dann Enter...")
input()
candidates = page.query_selector_all(
"[data-tid*='message'], [class*='message'], [role='listitem']"
)
print(f"\n{len(candidates)} potenzielle Nachrichten-Elemente gefunden")
for i, el in enumerate(candidates[:5]):
print(f"\n--- Element {i} ---")
print(f" tag: {el.evaluate('e => e.tagName')}")
print(f" data-tid: {el.get_attribute('data-tid')}")
print(f" class (100 Zch): {(el.get_attribute('class') or '')[:100]}")
print(f" text (100 Zch): {el.inner_text()[:100].replace(chr(10), ' ')}")
results = page.evaluate("""() => {
const out = {};
print("\nKlicke im Browser auf einen Sender-Namen, dann hier Enter drücken...")
input()
// 1. All unique data-tid values on the page
const tids = new Set();
document.querySelectorAll('[data-tid]').forEach(el => tids.add(el.getAttribute('data-tid')));
out.allDataTids = [...tids].sort();
cards = page.query_selector_all(
"[class*='persona'], [class*='Persona'], [class*='profile'], [data-tid*='persona']"
)
print(f"\n{len(cards)} potenzielle Profilkarten-Elemente gefunden")
for i, el in enumerate(cards[:5]):
print(f"\n--- Karte {i} ---")
print(f" tag: {el.evaluate('e => e.tagName')}")
print(f" data-tid: {el.get_attribute('data-tid')}")
print(f" class (100 Zch): {(el.get_attribute('class') or '')[:100]}")
print(f" text (100 Zch): {el.inner_text()[:100].replace(chr(10), ' ')}")
// 2. Try common message selectors
const msgSelectors = [
"[data-tid='chat-pane-message']",
"[data-tid='channel-message-content']",
"[data-tid='message-body']",
"[data-tid='messageBody']",
"[class*='fui-ChatMessage']:not([class*='Control'])",
"[class*='message-body']",
"[class*='messageBody']",
"[class*='chatMessage']",
"[class*='ChatMessage']",
];
out.msgSelectorHits = {};
msgSelectors.forEach(sel => {
try {
out.msgSelectorHits[sel] = document.querySelectorAll(sel).length;
} catch(e) {}
});
// 3. Find elements whose text contains known message content
const knownTexts = ['Oliver Hofmann', '!stop', 'test', '!start'];
out.knownTextMatches = [];
document.querySelectorAll('*').forEach(el => {
if (el.children.length > 0) return;
const t = el.textContent.trim();
if (knownTexts.some(kt => t === kt || t.startsWith(kt))) {
let p = el;
const ancestors = [];
for (let i = 0; i < 5 && p; i++) {
ancestors.push({
tag: p.tagName,
dataTid: p.getAttribute('data-tid'),
cls: (p.className || '').substring(0, 80)
});
p = p.parentElement;
}
out.knownTextMatches.push({ text: t.substring(0, 40), ancestors });
}
});
out.knownTextMatches = out.knownTextMatches.slice(0, 10);
return out;
}""")
print("\n--- Alle data-tid Werte auf der Seite ---")
print(", ".join(results["allDataTids"]))
print("\n--- Nachrichten-Selektoren ---")
for sel, count in results["msgSelectorHits"].items():
if count > 0:
print(f" ✓ {sel}: {count} Treffer")
else:
print(f" {sel}: 0")
print("\n--- Elemente mit bekanntem Text ---")
for match in results["knownTextMatches"]:
print(f"\n Text: \"{match['text']}\"")
for anc in match["ancestors"]:
print(f" {anc['tag']} data-tid='{anc['dataTid']}' class='{anc['cls'][:60]}'")
print("\nEnter zum Schließen...")
input()