From 0d22af2470a2e63488ce7d7550cb3acdea6ca599 Mon Sep 17 00:00:00 2001 From: Piotr Dec Date: Wed, 30 Apr 2025 00:12:16 +0200 Subject: [PATCH 01/11] exporter-ng: argparse removed, reformatted --- exporter-ng.py | 80 ++++++++++++-------------------------------------- 1 file changed, 19 insertions(+), 61 deletions(-) diff --git a/exporter-ng.py b/exporter-ng.py index 16a7ecc..4d00ab5 100644 --- a/exporter-ng.py +++ b/exporter-ng.py @@ -1,16 +1,15 @@ +import json import os import sys -import requests -import json -from timeit import default_timer +from dataclasses import dataclass from datetime import datetime -import argparse +from time import sleep +from typing import List, Optional, Dict, Any + +import requests from dotenv import load_dotenv from pathvalidate import sanitize_filename -from time import sleep -from dataclasses import dataclass -from typing import List, Optional, Dict, Any, Iterator, Tuple -from abc import ABC, abstractmethod + @dataclass class SlackConfig: @@ -30,8 +29,10 @@ class SlackConfig: except KeyError: raise ValueError("Brak SLACK_USER_TOKEN w zmiennych środowiskowych") + class SlackAPI: """Klasa do komunikacji z API Slacka""" + def __init__(self, config: SlackConfig): self.config = config self.headers = {"Authorization": f"Bearer {config.user_token}"} @@ -130,6 +131,7 @@ class SlackAPI: params["channel"] = channel return self.paginated_get("files.list", params, "files") + @dataclass class SlackUser: """Reprezentacja użytkownika Slack""" @@ -189,8 +191,10 @@ class SlackUser: return ", ".join(parts) + class SlackChannel: """Reprezentacja kanału Slack""" + def __init__(self, data: Dict): self.id = data["id"] self.name = data.get("name", "") @@ -231,6 +235,7 @@ class SlackChannel: return " ".join(parts) + @dataclass class SlackFile: """Reprezentacja pliku Slack""" @@ -246,8 +251,10 @@ class SlackFile: url_private=data.get("url_private", "") ) + class SlackMessage: """Reprezentacja wiadomości Slack""" + def __init__(self, data: Dict, users: Dict[str, SlackUser]): self.timestamp = float(data["ts"]) self.text = data.get("text", "[no message content]") @@ -295,8 +302,10 @@ class SlackMessage: return message + "\n\n" + "*" * 24 + "\n\n" + class SlackExporter: """Główna klasa eksportera""" + def __init__(self, config: SlackConfig, output_dir: str): self.api = SlackAPI(config) self.timestamp = datetime.now().strftime("%Y-%m-%d_%H%M%S") @@ -397,14 +406,14 @@ class SlackExporter: data = header + "".join(msg.format(True) for msg in messages) self._save_data(data, f"channel-replies_{channel_id}", as_json) - + def export_channel_files(self, channel_id: Optional[str] = None): """Eksportuje pliki w kanale""" files = [SlackFile.from_dict(f) for f in self.api.get_files(channel_id)] for file in files: filename = f"{file.id}-{sanitize_filename(file.name)}" self.download_file(filename, file.url_private) - + def download_file(self, filename: str, url: str, attempts: int = 10) -> bool: if attempts == 0: return False @@ -422,58 +431,7 @@ class SlackExporter: print(f"Error downloading file {filename}: {e}. {attempts} attempts left.") return self.download_file(filename, url, attempts - 1) -def main(): - parser = argparse.ArgumentParser(description="Eksporter danych ze Slacka") - parser.add_argument("-o", help="Katalog wyjściowy (jeśli pusty, wyświetla na stdout)") - parser.add_argument("--lc", action="store_true", help="Lista wszystkich konwersacji") - parser.add_argument("--lu", action="store_true", help="Lista wszystkich użytkowników") - parser.add_argument("--json", action="store_true", help="Wynik w formacie JSON") - parser.add_argument("-c", action="store_true", help="Historia wszystkich dostępnych konwersacji") - parser.add_argument("--ch", help="Z -c, ogranicza eksport do podanego ID kanału") - parser.add_argument("--fr", help="Z -c, timestamp początku zakresu (Unix)") - parser.add_argument("--to", help="Z -c, timestamp końca zakresu (Unix)") - parser.add_argument("-r", action="store_true", help="Pobierz wątki ze wszystkich konwersacji") - parser.add_argument("--files", action="store_true", help="Pobierz wszystkie pliki") - - args = parser.parse_args() - - if args.files and not args.o: - print("Opcja --files wymaga określenia katalogu wyjściowego (-o)") - sys.exit(1) - - try: - config = SlackConfig.from_env() - exporter = SlackExporter(config) - - if args.o: - exporter.set_output_dir(args.o) - - exporter.load_users() - exporter.load_channels() - - if args.lc: - exporter.export_channel_list(args.json) - - if args.lu: - exporter.export_user_list(args.json) - - if args.c or args.r: - channel_ids = [args.ch] if args.ch else [ch.id for ch in exporter.channels] - for channel_id in channel_ids: - if args.c: - exporter.export_channel_history(channel_id, args.fr, args.to, args.json) - if args.r: - exporter.export_channel_replies(channel_id, args.fr, args.to, args.json) - - if args.files and args.o: - # TODO: Implementacja pobierania plików - print("Funkcja pobierania plików jeszcze nie zaimplementowana") - - except Exception as e: - print(f"Błąd: {e}") - sys.exit(1) if __name__ == "__main__": - # main() config = SlackConfig.from_env() exporter = SlackExporter(config, 'out') From bafe448aa278caa3adad21b0bfc130a47b6ab2f7 Mon Sep 17 00:00:00 2001 From: Piotr Dec Date: Wed, 30 Apr 2025 00:17:38 +0200 Subject: [PATCH 02/11] exporter-ng: output directory resolves to 'out' by default --- exporter-ng.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/exporter-ng.py b/exporter-ng.py index 4d00ab5..fc5f712 100644 --- a/exporter-ng.py +++ b/exporter-ng.py @@ -306,7 +306,7 @@ class SlackMessage: class SlackExporter: """Główna klasa eksportera""" - def __init__(self, config: SlackConfig, output_dir: str): + def __init__(self, config: SlackConfig, output_dir: str = 'out'): self.api = SlackAPI(config) self.timestamp = datetime.now().strftime("%Y-%m-%d_%H%M%S") self.output_dir = self._set_output_dir(output_dir) @@ -434,4 +434,4 @@ class SlackExporter: if __name__ == "__main__": config = SlackConfig.from_env() - exporter = SlackExporter(config, 'out') + exporter = SlackExporter(config) From c0bb7d5aa074ac03cea332fc3410f017d1ef0cc9 Mon Sep 17 00:00:00 2001 From: Piotr Dec Date: Wed, 30 Apr 2025 12:26:21 +0200 Subject: [PATCH 03/11] exporter-ng: dictionary fixes --- exporter-ng.py => exporter_ng.py | 55 ++++++++++++++++++++++++-------- 1 file changed, 41 insertions(+), 14 deletions(-) rename exporter-ng.py => exporter_ng.py (88%) diff --git a/exporter-ng.py b/exporter_ng.py similarity index 88% rename from exporter-ng.py rename to exporter_ng.py index fc5f712..955eb44 100644 --- a/exporter-ng.py +++ b/exporter_ng.py @@ -150,12 +150,11 @@ class SlackUser: @classmethod def from_dict(cls, data: Dict) -> 'SlackUser': - profile = data.get("profile", {}) return cls( id=data["id"], name=data.get("name", ""), - real_name=profile.get("real_name"), - display_name=profile.get("display_name"), + real_name=data.get("real_name"), + display_name=data.get("display_name"), is_admin=data.get("is_admin", False), is_owner=data.get("is_owner", False), is_primary_owner=data.get("is_primary_owner", False), @@ -195,15 +194,18 @@ class SlackUser: class SlackChannel: """Reprezentacja kanału Slack""" - def __init__(self, data: Dict): + def __init__(self, data: Dict, users: Dict[str, SlackUser]): self.id = data["id"] self.name = data.get("name", "") self.is_private = data.get("is_private", False) self.is_im = data.get("is_im", False) self.is_mpim = data.get("is_mpim", False) self.is_group = data.get("is_group", False) - self.creator_id = data.get("creator") - self.user_id = data.get("user") + self._creator_id = data.get("creator_id") + self._user_id = data.get("user_id") + self.user = users[self._user_id].get_display_name() if self._user_id and self._user_id in users else "(nieznany)" + self._mpim_users = self._list_mpim({u.name: u for u in users.values()}) if self.is_mpim else [] + self.label = self._create_label(users) @property def type(self) -> str: @@ -216,7 +218,24 @@ class SlackChannel: else: return "channel" - def format(self, users: Dict[str, SlackUser]) -> str: + @property + def short_label(self) -> str: + if self.is_im: + return f"(DM) {self.user}" + elif self.is_mpim: + return f"(MPDM) {', '.join(self._mpim_users)}" + return self.name + + def _list_mpim(self, users: Dict[str, SlackUser]) -> List[str]: + result = [] + for part in self.name.split("-"): + name = users.get(part) + if name: + result.append(name.get_display_name()) + return result + + + def _create_label(self, users: Dict[str, SlackUser]) -> str: """Formatuje informacje o kanale""" parts = [f"[{self.id}]"] @@ -228,10 +247,10 @@ class SlackChannel: parts.append(self.type) - if self.creator_id and self.creator_id in users: - parts.append(f"created by {users[self.creator_id].name}") - elif self.user_id and self.user_id in users: - parts.append(f"with {users[self.user_id].name}") + if self._creator_id and self._creator_id in users: + parts.append(f"created by {users[self._creator_id].get_display_name()}") + elif self._user_id and self._user_id in users: + parts.append(f"with {users[self._user_id].get_display_name()}") return " ".join(parts) @@ -322,13 +341,15 @@ class SlackExporter: def _load_users(self) -> Dict[str, SlackUser]: """Ładuje użytkowników""" - users_data = self.api.get_users() + # users_data = self.api.get_users() + users_data = json.load(open("out/user_list.json", "r", encoding="utf-8")) return {u["id"]: SlackUser.from_dict(u) for u in users_data} def _load_channels(self) -> List[SlackChannel]: """Ładuje kanały""" - channels_data = self.api.get_channels() - return [SlackChannel(ch) for ch in channels_data] + # channels_data = self.api.get_channels() + channels_data = json.load(open("out/channel_list.json", "r", encoding="utf-8")) + return [SlackChannel(ch, self.users) for ch in channels_data] def _save_data(self, data: Any, filename: str, as_json: bool = False): """Zapisuje dane do pliku""" @@ -346,6 +367,12 @@ class SlackExporter: else: f.write(data) + def export_channels(self, channels: List[str]): + with open(os.path.join(self.output_dir, "channels.txt"), "w", encoding="utf-8") as f: + for channel in channels: + f.write(str(channel) + "\n") + pass + def export_channel_list(self, as_json: bool = False): """Eksportuje listę kanałów""" if as_json: From 906566825f7b628ad4991f05562435abefa7ea21 Mon Sep 17 00:00:00 2001 From: Piotr Dec Date: Wed, 30 Apr 2025 12:26:35 +0200 Subject: [PATCH 04/11] TUI --- requirements.txt | 2 + tui.py | 119 +++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 121 insertions(+) create mode 100644 tui.py diff --git a/requirements.txt b/requirements.txt index 19d4264..03d29b3 100644 --- a/requirements.txt +++ b/requirements.txt @@ -2,3 +2,5 @@ Flask~=1.1.2 requests~=2.24.0 python-dotenv~=0.15.0 pathvalidate~=2.5.2 + +textual~=3.1.1 diff --git a/tui.py b/tui.py new file mode 100644 index 0000000..f91f343 --- /dev/null +++ b/tui.py @@ -0,0 +1,119 @@ +import sys + +from textual import work +from textual.app import App, ComposeResult +from textual.containers import Container +from textual.screen import Screen +from textual.widgets import Header, Button, ListView, ListItem, Footer, Label + +from exporter_ng import SlackExporter, SlackConfig + + +class SlackExporterScreen(Screen): + """Ekran główny eksportera Slack""" + + def __init__(self, exporter: SlackExporter, *args, **kwargs): + super().__init__(*args, **kwargs) + self.exporter = exporter + self.selected_channels = set() + + def compose(self) -> ComposeResult: + """Komponuje widgety na ekranie""" + yield Header(show_clock=True) + yield Container( + ListView(*[ + ListItem(Label(ch.short_label, id=ch.id)) + for ch in self.exporter.channels + ], id="channel-list"), + Button("Eksportuj zaznaczone", variant="primary", id="export-btn"), + id="main-container" + ) + yield Footer() + + def on_list_view_selected(self, event: ListView.Selected) -> None: + """Obsługuje zaznaczenie elementu listy""" + item = event.item + item_id = item.children[0].id + if item_id in self.selected_channels: + self.selected_channels.remove(item_id) + item.remove_class("selected") + else: + self.selected_channels.add(item_id) + item.add_class("selected") + + @work(exclusive=True) + async def export_channels(self): + """Eksportuje zaznaczone kanały""" + if not self.selected_channels: + self.notify("Nie wybrano żadnych kanałów") + return + + # self.notify("Rozpoczynam eksport...") + # self.exporter.export_channels(list(self.selected_channels)) + # # for channel_id in self.selected_channels: + # # self.notify(f"Eksportuję kanał {channel_id}...") + # # self.exporter.export_channel_history(channel_id) + # self.notify("Eksport zakończony") + self.app.exit(return_code=8080) + + + async def on_button_pressed(self, event: Button.Pressed) -> None: + """Obsługuje kliknięcie przycisku""" + if event.button.id == "export-btn": + self.export_channels() + +class SlackTUI(App): + """Główna klasa interfejsu użytkownika""" + CSS = """ + #main-container { + layout: vertical; + height: 100%; + padding: 1; + } + + ListView { + height: 1fr; + border: solid green; + } + + .selected { + background: $accent; + color: $text; + } + + Button { + margin: 1; + width: 100%; + } + """ + + def __init__(self, exporter: SlackExporter): + super().__init__() + self.exporter = exporter + self._screen = SlackExporterScreen(self.exporter) + + def on_mount(self) -> None: + """Wywoływane przy montowaniu aplikacji""" + self.push_screen(self._screen) + + def get_selection(self): + return self._screen.selected_channels + + def get_return_code(self): + return self._return_code + +def run_tui(exporter: SlackExporter): + """Uruchamia interfejs użytkownika""" + app = SlackTUI(exporter) + app.run() + if app.get_return_code() == 8080: + exporter.export_channels(app.get_selection()) + +if __name__ == "__main__": + try: + config = SlackConfig.from_env() + exporter = SlackExporter(config) + run_tui(exporter) + except Exception as e: + print(f"Błąd: {e}") + sys.exit(1) From c36276aee5fe4b2b827b7b915e6c57903991c6d5 Mon Sep 17 00:00:00 2001 From: Piotr Dec Date: Wed, 30 Apr 2025 12:40:00 +0200 Subject: [PATCH 05/11] Channel export --- exporter_ng.py | 16 +++++++++++----- tui.py | 2 +- 2 files changed, 12 insertions(+), 6 deletions(-) diff --git a/exporter_ng.py b/exporter_ng.py index 955eb44..4d96221 100644 --- a/exporter_ng.py +++ b/exporter_ng.py @@ -368,17 +368,23 @@ class SlackExporter: f.write(data) def export_channels(self, channels: List[str]): - with open(os.path.join(self.output_dir, "channels.txt"), "w", encoding="utf-8") as f: - for channel in channels: - f.write(str(channel) + "\n") - pass + channels_map = {ch.id: ch for ch in self.channels} + self.export_channel_list(True) + self.export_user_list(True) + for channel_id in channels: + print(f"Eksport {channels_map.get(channel_id).label}...") + self.export_channel_history(channel_id) + self.export_channel_history(channel_id, as_json=True) + self.export_channel_replies(channel_id) + self.export_channel_replies(channel_id, as_json=True) + self.export_channel_files(channel_id) def export_channel_list(self, as_json: bool = False): """Eksportuje listę kanałów""" if as_json: data = [vars(ch) for ch in self.channels] else: - data = "\n".join(ch.format(self.users) for ch in self.channels) + data = "\n".join(ch.label for ch in self.channels) self._save_data(data, "channel_list", as_json) def export_user_list(self, as_json: bool = False): diff --git a/tui.py b/tui.py index f91f343..d146443 100644 --- a/tui.py +++ b/tui.py @@ -107,7 +107,7 @@ def run_tui(exporter: SlackExporter): app = SlackTUI(exporter) app.run() if app.get_return_code() == 8080: - exporter.export_channels(app.get_selection()) + exporter.export_channels(list(app.get_selection())) if __name__ == "__main__": try: From 066232222fd99195ca23300e278ad03abb30c9b5 Mon Sep 17 00:00:00 2001 From: Piotr Dec Date: Wed, 30 Apr 2025 13:39:31 +0200 Subject: [PATCH 06/11] Dual format persistence fixes --- exporter_ng.py | 21 ++++++++++++++------- 1 file changed, 14 insertions(+), 7 deletions(-) diff --git a/exporter_ng.py b/exporter_ng.py index 4d96221..32a351c 100644 --- a/exporter_ng.py +++ b/exporter_ng.py @@ -373,10 +373,11 @@ class SlackExporter: self.export_user_list(True) for channel_id in channels: print(f"Eksport {channels_map.get(channel_id).label}...") + print(f"[{channel_id}] Historia") self.export_channel_history(channel_id) - self.export_channel_history(channel_id, as_json=True) + print(f"[{channel_id}] Odpowiedzi") self.export_channel_replies(channel_id) - self.export_channel_replies(channel_id, as_json=True) + print(f"[{channel_id}] Pliki") self.export_channel_files(channel_id) def export_channel_list(self, as_json: bool = False): @@ -396,10 +397,13 @@ class SlackExporter: self._save_data(data, "user_list", as_json) def export_channel_history(self, channel_id: str, oldest: Optional[str] = None, - latest: Optional[str] = None, as_json: bool = False): - """Eksportuje historię kanału""" + latest: Optional[str] = None): history = self.api.get_channel_history(channel_id, oldest, latest) + self._export_channel_history(channel_id, history, True) + self._export_channel_history(channel_id, history, False) + def _export_channel_history(self, channel_id: str, history: List[Dict], as_json: bool): + """Eksportuje historię kanału""" if as_json: data = history else: @@ -416,16 +420,18 @@ class SlackExporter: self._save_data(data, f"channel_{channel_id}", as_json) def export_channel_replies(self, channel_id: str, oldest: Optional[str] = None, - latest: Optional[str] = None, as_json: bool = False): - """Eksportuje wątki w kanale""" + latest: Optional[str] = None): history = self.api.get_channel_history(channel_id, oldest, latest) thread_messages = [msg for msg in history if "reply_count" in msg] - all_replies = [] for msg in thread_messages: replies = self.api.get_replies(channel_id, msg["ts"]) all_replies.extend(replies) + self._export_channel_replies(channel_id, all_replies, True) + self._export_channel_replies(channel_id, all_replies, False) + def _export_channel_replies(self, channel_id: str, all_replies: List[Dict], as_json: bool): + """Eksportuje wątki w kanale""" if as_json: data = all_replies else: @@ -459,6 +465,7 @@ class SlackExporter: with open(target, 'wb') as f: for chunk in response.iter_content(chunk_size=8192): f.write(chunk) + print(f"Zapisano plik {target}") return True except requests.exceptions.RequestException as e: print(f"Error downloading file {filename}: {e}. {attempts} attempts left.") From bce46422fcb62bd831dbe642aabf8f98a36da9fa Mon Sep 17 00:00:00 2001 From: Piotr Dec Date: Wed, 30 Apr 2025 13:40:26 +0200 Subject: [PATCH 07/11] Unmock channels & users --- exporter_ng.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/exporter_ng.py b/exporter_ng.py index 32a351c..57329ac 100644 --- a/exporter_ng.py +++ b/exporter_ng.py @@ -341,14 +341,14 @@ class SlackExporter: def _load_users(self) -> Dict[str, SlackUser]: """Ładuje użytkowników""" - # users_data = self.api.get_users() - users_data = json.load(open("out/user_list.json", "r", encoding="utf-8")) + users_data = self.api.get_users() + # users_data = json.load(open("out/user_list.json", "r", encoding="utf-8")) return {u["id"]: SlackUser.from_dict(u) for u in users_data} def _load_channels(self) -> List[SlackChannel]: """Ładuje kanały""" - # channels_data = self.api.get_channels() - channels_data = json.load(open("out/channel_list.json", "r", encoding="utf-8")) + channels_data = self.api.get_channels() + # channels_data = json.load(open("out/channel_list.json", "r", encoding="utf-8")) return [SlackChannel(ch, self.users) for ch in channels_data] def _save_data(self, data: Any, filename: str, as_json: bool = False): From f2b2c05a29964526eb8893eb01c7bc4fad48783e Mon Sep 17 00:00:00 2001 From: Piotr Dec Date: Wed, 30 Apr 2025 13:50:07 +0200 Subject: [PATCH 08/11] Docker & CI --- .woodpecker/latest.yaml | 13 +++++++++++++ Dockerfile | 7 ++++--- 2 files changed, 17 insertions(+), 3 deletions(-) create mode 100644 .woodpecker/latest.yaml diff --git a/.woodpecker/latest.yaml b/.woodpecker/latest.yaml new file mode 100644 index 0000000..c5ae2a3 --- /dev/null +++ b/.woodpecker/latest.yaml @@ -0,0 +1,13 @@ +steps: + - name: build + image: woodpeckerci/plugin-docker-buildx + settings: + platforms: linux/amd64 + repo: git.ztsh.eu/slack-exporter + registry: git.ztsh.eu + tags: latest + username: stawros + password: + from_secret: git_pat + when: + - event: [tag, push, manual] diff --git a/Dockerfile b/Dockerfile index b265373..944b773 100644 --- a/Dockerfile +++ b/Dockerfile @@ -3,10 +3,11 @@ LABEL authors="stawros" RUN mkdir /app -COPY slack-exporter/requirements.txt /app/ -COPY slack-exporter/exporter.py /app/ +COPY requirements.txt /app/ +COPY exporter_ng.py /app/ +COPY tui.py /app/ RUN pip3 uninstall urllib3 RUN pip3 install -r /app/requirements.txt -CMD ["python3", "/app/exporter.py"] +CMD ["python3", "/app/tui.py"] From 51688a48a567eead9ef3745800bf550716c1b442 Mon Sep 17 00:00:00 2001 From: Piotr Dec Date: Wed, 30 Apr 2025 13:53:00 +0200 Subject: [PATCH 09/11] plugin version --- .woodpecker/latest.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.woodpecker/latest.yaml b/.woodpecker/latest.yaml index c5ae2a3..e13668f 100644 --- a/.woodpecker/latest.yaml +++ b/.woodpecker/latest.yaml @@ -1,6 +1,6 @@ steps: - name: build - image: woodpeckerci/plugin-docker-buildx + image: woodpeckerci/plugin-docker-buildx:5.2.2 settings: platforms: linux/amd64 repo: git.ztsh.eu/slack-exporter From 2f24e73d45dcf3ee099d3ebe91dca3cb58b6b279 Mon Sep 17 00:00:00 2001 From: Piotr Dec Date: Wed, 30 Apr 2025 13:57:13 +0200 Subject: [PATCH 10/11] docker repo coords fix --- .woodpecker/latest.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.woodpecker/latest.yaml b/.woodpecker/latest.yaml index e13668f..92d447d 100644 --- a/.woodpecker/latest.yaml +++ b/.woodpecker/latest.yaml @@ -3,7 +3,7 @@ steps: image: woodpeckerci/plugin-docker-buildx:5.2.2 settings: platforms: linux/amd64 - repo: git.ztsh.eu/slack-exporter + repo: git.ztsh.eu/stawros/slack-exporter registry: git.ztsh.eu tags: latest username: stawros From 13473709490f63999bf651c6a1a75fdfd0455ae4 Mon Sep 17 00:00:00 2001 From: Piotr Dec Date: Wed, 30 Apr 2025 14:27:25 +0200 Subject: [PATCH 11/11] slack channel users fix --- exporter_ng.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/exporter_ng.py b/exporter_ng.py index 57329ac..dad9d00 100644 --- a/exporter_ng.py +++ b/exporter_ng.py @@ -201,8 +201,8 @@ class SlackChannel: self.is_im = data.get("is_im", False) self.is_mpim = data.get("is_mpim", False) self.is_group = data.get("is_group", False) - self._creator_id = data.get("creator_id") - self._user_id = data.get("user_id") + self._creator_id = data.get("creator") + self._user_id = data.get("user") self.user = users[self._user_id].get_display_name() if self._user_id and self._user_id in users else "(nieznany)" self._mpim_users = self._list_mpim({u.name: u for u in users.values()}) if self.is_mpim else [] self.label = self._create_label(users)