I hate how good AI is at doing menial straightforward tasks.
This commit is contained in:
commit
7c49de7e55
5 changed files with 168 additions and 0 deletions
7
.gitignore
vendored
Normal file
7
.gitignore
vendored
Normal file
|
|
@ -0,0 +1,7 @@
|
|||
.zuliprc
|
||||
.mypy_cache/**
|
||||
.venv/**
|
||||
__pycache__/**
|
||||
build/**
|
||||
dist/**
|
||||
*.md
|
||||
4
.zuliprc.template
Normal file
4
.zuliprc.template
Normal file
|
|
@ -0,0 +1,4 @@
|
|||
[api]
|
||||
email=me@example.com
|
||||
key=some_api_key
|
||||
site=https://zulip.example.com
|
||||
10
requirements.txt
Normal file
10
requirements.txt
Normal file
|
|
@ -0,0 +1,10 @@
|
|||
certifi==2026.5.20
|
||||
charset-normalizer==3.4.7
|
||||
click==8.4.1
|
||||
colorama==0.4.6
|
||||
distro==1.9.0
|
||||
idna==3.18
|
||||
requests==2.34.2
|
||||
typing_extensions==4.15.0
|
||||
urllib3==2.7.0
|
||||
zulip==0.9.1
|
||||
102
topic-export.py
Normal file
102
topic-export.py
Normal file
|
|
@ -0,0 +1,102 @@
|
|||
import datetime
|
||||
import zulip
|
||||
import sys
|
||||
import os
|
||||
|
||||
# Check if running as a PyInstaller bundle or raw python script
|
||||
if getattr(sys, "frozen", False) and hasattr(sys, "_MEIPASS"):
|
||||
# Path inside the temporary binary folder
|
||||
base_path = sys._MEIPASS # type: ignore
|
||||
else:
|
||||
# Path in your standard local workspace folder
|
||||
base_path = os.path.abspath(".")
|
||||
|
||||
CONFIG_PATH = os.path.join(base_path, ".zuliprc")
|
||||
CHANNEL_NAME = "wifey-time"
|
||||
TOPIC_NAME = "Mutual Enjoyment"
|
||||
OUTPUT_FILE = (
|
||||
f"{datetime.date.today().isoformat()}_Mutual_Enjoyment.md" # Saved directly as .md
|
||||
)
|
||||
|
||||
# Initialize client using the embedded configuration
|
||||
client = zulip.Client(config_file=CONFIG_PATH)
|
||||
|
||||
narrow_filter = [
|
||||
{"operator": "channel", "operand": CHANNEL_NAME},
|
||||
{"operator": "topic", "operand": TOPIC_NAME},
|
||||
]
|
||||
|
||||
anchor = "oldest"
|
||||
all_messages = []
|
||||
batch_count = 0
|
||||
|
||||
print(f"Starting export for '{CHANNEL_NAME}' > '{TOPIC_NAME}'...")
|
||||
|
||||
# Step 1: Automatic Pagination Loop
|
||||
while True:
|
||||
batch_count += 1
|
||||
|
||||
request_params = {
|
||||
"anchor": anchor,
|
||||
"num_before": 0,
|
||||
"num_after": 1000,
|
||||
"narrow": narrow_filter,
|
||||
"apply_markdown": False, # This ensures Zulip gives us raw markdown strings
|
||||
}
|
||||
|
||||
response = client.call_endpoint(
|
||||
url="messages",
|
||||
method="GET",
|
||||
request=request_params,
|
||||
)
|
||||
|
||||
if response.get("result") != "success":
|
||||
print(f"Error fetching data: {response.get('msg')}")
|
||||
break
|
||||
|
||||
messages = response.get("messages", [])
|
||||
if not messages:
|
||||
break
|
||||
|
||||
if anchor == "oldest":
|
||||
all_messages.extend(messages)
|
||||
else:
|
||||
all_messages.extend(messages[1:])
|
||||
if len(messages) <= 1:
|
||||
break
|
||||
|
||||
anchor = messages[-1]["id"]
|
||||
print(f" Batch {batch_count}: Downloaded {len(messages)} messages...")
|
||||
|
||||
# Step 2: Format Data into a Valid Markdown File
|
||||
if all_messages:
|
||||
with open(OUTPUT_FILE, "w", encoding="utf-8") as f:
|
||||
# Markdown File Header
|
||||
f.write(f"# Chat Export: {CHANNEL_NAME} > {TOPIC_NAME}\n")
|
||||
f.write(f"**Total Messages:** {len(all_messages)} \n")
|
||||
f.write(f"**Export Date:** {datetime.date.today().isoformat()} \n")
|
||||
f.write("\n---\n\n")
|
||||
|
||||
# Process each individual message payload
|
||||
for msg in all_messages:
|
||||
sender = msg.get("sender_full_name", "Unknown User")
|
||||
content = msg.get("content", "")
|
||||
|
||||
# Convert Unix timestamp to a friendly readable format
|
||||
timestamp = msg.get("timestamp", 0)
|
||||
formatted_time = datetime.datetime.fromtimestamp(timestamp).strftime(
|
||||
"%Y-%m-%d %H:%M:%S"
|
||||
)
|
||||
|
||||
# Write metadata as a markdown bold header line
|
||||
f.write(f"**[{formatted_time}] {sender}:**\n\n")
|
||||
|
||||
# Print the raw markdown content exactly as typed in Zulip
|
||||
f.write(f"{content}\n\n")
|
||||
|
||||
# Add a clean markdown line break rule between chat entries
|
||||
f.write(" \n")
|
||||
|
||||
print(f"\nSuccess! Exported {len(all_messages)} messages to: '{OUTPUT_FILE}'.")
|
||||
else:
|
||||
print("\nNo messages discovered matching this specific channel and topic criteria.")
|
||||
45
topic-export.spec
Normal file
45
topic-export.spec
Normal file
|
|
@ -0,0 +1,45 @@
|
|||
# -*- mode: python ; coding: utf-8 -*-
|
||||
|
||||
block_cipher = None
|
||||
|
||||
a = Analysis(
|
||||
['topic-export.py'],
|
||||
pathex=[],
|
||||
binaries=[],
|
||||
datas=[('.zuliprc', '.')],
|
||||
hiddenimports=[],
|
||||
hookspath=[],
|
||||
hooksconfig={},
|
||||
runtime_hooks=[],
|
||||
excludes=[],
|
||||
noarchive=False,
|
||||
optimize=0,
|
||||
)
|
||||
|
||||
pyz = PYZ(
|
||||
a.pure,
|
||||
a.zipped_data,
|
||||
cipher=block_cipher
|
||||
)
|
||||
|
||||
exe = EXE(
|
||||
pyz,
|
||||
a.scripts,
|
||||
a.binaries,
|
||||
a.zipfiles,
|
||||
a.datas,
|
||||
[],
|
||||
name="export_mutual_enjoyment",
|
||||
debug=False,
|
||||
bootloader_ignore_signals=False,
|
||||
strip=False,
|
||||
upx=True,
|
||||
upx_exclude=[],
|
||||
runtime_tmpdir=None,
|
||||
console=True,
|
||||
disable_windowed_traceback=False,
|
||||
argv_emulation=False,
|
||||
target_arch=None,
|
||||
codesign_identity=None,
|
||||
entitlements_file=None,
|
||||
)
|
||||
Loading…
Reference in a new issue