feat: enhance Mattermost mirror with direct-message and group DM labeling for improved clarity
This commit is contained in:
@@ -69,6 +69,12 @@ and `threads/...` when a single discussion thread is the relevant evidence.
|
||||
This mirrors Slack's export pattern of one folder per conversation with one file
|
||||
per date, while adding Mattermost-specific thread views.
|
||||
|
||||
Direct-message channels are labeled as `dm-<user-a>--<user-b>` when the mirror
|
||||
has seen enough user metadata to resolve the Mattermost channel ID. Group DMs
|
||||
use `group-...`. If a DM was first captured before the relevant user metadata
|
||||
arrived, the folder can temporarily use raw IDs; later captures use the readable
|
||||
label and `refs/channels.json` remains the source for resolving channel IDs.
|
||||
|
||||
The mirror writes any post payload it sees, including older messages returned
|
||||
when the desktop app loads channel history or a thread. It dedupes by `post_id`,
|
||||
so scrolling back through useful history is a safe way to backfill missing local
|
||||
|
||||
@@ -61,6 +61,7 @@ class MattermostMirror:
|
||||
self.seen_by_file: dict[Path, set[str]] = {}
|
||||
self.users: dict[str, str] = {}
|
||||
self.channels: dict[str, str] = {}
|
||||
self.channel_meta: dict[str, dict[str, Any]] = {}
|
||||
self.state: dict[str, Any] = {"channels": {}, "users": {}, "updated_at": None}
|
||||
|
||||
self._ensure_dirs()
|
||||
@@ -80,6 +81,7 @@ class MattermostMirror:
|
||||
try:
|
||||
self.state = json.loads(self.state_path.read_text(encoding="utf-8"))
|
||||
self.users = dict(self.state.get("users") or {})
|
||||
self.channel_meta = dict(self.state.get("channel_meta") or {})
|
||||
for channel_id, value in (self.state.get("channels") or {}).items():
|
||||
if isinstance(value, dict):
|
||||
name = value.get("channel_name") or value.get("name")
|
||||
@@ -205,10 +207,48 @@ class MattermostMirror:
|
||||
channel_id = channel.get("id")
|
||||
if not channel_id:
|
||||
return
|
||||
name = channel.get("name") or channel.get("display_name") or channel_id
|
||||
self.channel_meta[channel_id] = channel
|
||||
name = self._channel_label(channel)
|
||||
self.channels[channel_id] = name
|
||||
self._write_refs()
|
||||
|
||||
def _user_label(self, user_id: str | None) -> str | None:
|
||||
if not user_id:
|
||||
return None
|
||||
return self.users.get(user_id) or user_id
|
||||
|
||||
def _channel_label(self, channel: dict[str, Any]) -> str:
|
||||
channel_id = channel.get("id") or "unknown-channel"
|
||||
channel_type = channel.get("type")
|
||||
display_name = (channel.get("display_name") or "").strip()
|
||||
name = (channel.get("name") or "").strip()
|
||||
|
||||
if channel_type == "D":
|
||||
user_ids = [item for item in name.split("__") if item]
|
||||
labels = [self._user_label(user_id) or user_id for user_id in user_ids]
|
||||
if labels:
|
||||
return "dm-" + "--".join(labels)
|
||||
|
||||
if channel_type == "G":
|
||||
if display_name:
|
||||
return "group-" + display_name
|
||||
user_ids = [item for item in name.split("__") if item]
|
||||
labels = [self._user_label(user_id) or user_id for user_id in user_ids]
|
||||
if labels:
|
||||
return "group-" + "--".join(labels)
|
||||
|
||||
return display_name or name or channel_id
|
||||
|
||||
def _refresh_channel_labels(self) -> None:
|
||||
changed = False
|
||||
for channel_id, meta in self.channel_meta.items():
|
||||
label = self._channel_label(meta)
|
||||
if label and self.channels.get(channel_id) != label:
|
||||
self.channels[channel_id] = label
|
||||
changed = True
|
||||
if changed:
|
||||
self._write_refs()
|
||||
|
||||
def _write_refs(self) -> None:
|
||||
users_path = self.refs_dir / "users.json"
|
||||
channels_path = self.refs_dir / "channels.json"
|
||||
@@ -244,6 +284,8 @@ class MattermostMirror:
|
||||
if isinstance(channel, dict):
|
||||
self._remember_channel(channel)
|
||||
|
||||
self._refresh_channel_labels()
|
||||
|
||||
def _normalize_post(self, post: dict[str, Any], source: str, raw_event: str | None = None) -> dict[str, Any] | None:
|
||||
post_id = post.get("id")
|
||||
channel_id = post.get("channel_id")
|
||||
@@ -311,6 +353,7 @@ class MattermostMirror:
|
||||
entry["last_seen_create_at"] = max(int(entry.get("last_seen_create_at") or 0), int(msg.get("created_at_ms") or 0))
|
||||
entry["last_seen_post_id"] = msg.get("post_id")
|
||||
self.state["users"] = self.users
|
||||
self.state["channel_meta"] = self.channel_meta
|
||||
self.state["updated_at"] = datetime.now(timezone.utc).isoformat()
|
||||
self._atomic_write_text(self.state_path, json.dumps(self.state, ensure_ascii=False, indent=2, sort_keys=True) + "\n")
|
||||
self._write_refs()
|
||||
|
||||
Reference in New Issue
Block a user