Skip to content

Commit 9d96049

Browse files
authored
Merge pull request #12 from ChartinoLabs/feat/add-users-to-room
feat: add bulk user addition functionality to Webex rooms
2 parents 27c23d8 + 39d5a26 commit 9d96049

File tree

11 files changed

+875
-44
lines changed

11 files changed

+875
-44
lines changed

.github/pull_request_template.md

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
## 📝 Description
2+
3+
## 🔗 Related Issue(s)
4+
5+
- Fixes # (issue)
6+
- Related to # (issue)
7+
8+
## ✔️ Type of Change
9+
10+
- [ ] 🐛 Bug fix (non-breaking change which fixes an issue)
11+
- [ ] 🚀 New feature (non-breaking change which adds functionality)
12+
- [ ] ⚠️ Breaking change (fix or feature that would cause existing functionality to not work as expected)
13+
- [ ] 🛠️ Refactoring/Technical debt (internal code improvements with no direct user-facing changes)
14+
- [ ] 📄 Documentation update
15+
- [ ] ⚙️ Chore (build process, CI, tooling, etc.)
16+
- [ ] ✨ Other (please describe):
17+
18+
## 🎯 Key Changes & Implementation Details
19+
20+
-
21+
-
22+
-
23+
24+
## 🧪 Testing Done
25+
26+
- [ ] New unit tests added/updated
27+
- [ ] Integration tests performed
28+
- [ ] Manual E2E testing performed (describe steps/scenarios):
29+
- Scenario 1: ...
30+
- Scenario 2: ...
31+
- [ ] All existing tests pass
32+
33+
## ✅ Checklist
34+
35+
- [ ] My code follows the style guidelines of this project (e.g., ran `pre-commit run -a`).
36+
- [ ] I have commented my code, particularly in hard-to-understand areas.
37+
- [ ] I have made corresponding changes to the documentation (if applicable).
38+
- [ ] My changes generate no new warnings.
39+
- [ ] I have added/updated relevant diagrams (if applicable).
40+
- [ ] I have updated `release-notes.md` with a summary of my changes under the appropriate version (if applicable, for significant user-facing changes or bug fixes).
41+
42+
## 🖼️ Screenshots (if applicable)
43+
44+
## ➡️ Next Steps (if applicable)
45+
46+
## ❓ Questions & Open Items (if applicable)

.gitignore

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -164,3 +164,10 @@ cython_debug/
164164

165165
# Application logs
166166
logs/
167+
168+
# Claude and editor configuration files
169+
CLAUDE.md
170+
.cursorrules
171+
172+
# Ruff cache
173+
.ruff_cache

summarizer/cli.py

Lines changed: 137 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,14 +3,18 @@
33
import logging
44
from datetime import datetime, timedelta
55
from enum import Enum
6+
from pathlib import Path
67
from typing import Annotated
78

89
import typer
910
from dotenv import load_dotenv
1011

1112
from summarizer.config import AppConfig
13+
from summarizer.console_ui import console
1214
from summarizer.logging import setup_logging
1315
from summarizer.runner import run_app
16+
from summarizer.webex import WebexClient
17+
from summarizer.yaml_utils import load_users_from_yaml
1418

1519
# Load environment variables from .env before initializing the Typer app
1620
load_dotenv()
@@ -188,6 +192,7 @@ def _run_date_range(
188192
max_messages: int,
189193
room_search_mode: str | None,
190194
room_search_value: str | None,
195+
all_messages: bool,
191196
) -> None:
192197
"""Execute date range workflow."""
193198
current = parsed_start_date
@@ -201,6 +206,7 @@ def _run_date_range(
201206
time_display_format=time_display_format,
202207
room_chunk_size=room_chunk_size,
203208
max_messages=max_messages,
209+
all_messages=all_messages,
204210
)
205211
_run_for_date(
206212
config,
@@ -321,6 +327,12 @@ def main(
321327
max_messages: Annotated[
322328
int, typer.Option(help="Maximum number of messages to retrieve from room")
323329
] = 1000,
330+
all_messages: Annotated[
331+
bool,
332+
typer.Option(
333+
help="Retrieve ALL messages from room regardless of user participation"
334+
),
335+
] = False,
324336
) -> None:
325337
"""Webex Summarizer CLI (Typer config parsing demo)."""
326338
if debug is True:
@@ -354,6 +366,7 @@ def main(
354366
max_messages,
355367
room_search_mode,
356368
room_search_value,
369+
all_messages,
357370
)
358371
return
359372

@@ -371,6 +384,7 @@ def main(
371384
time_display_format=time_display_format.value,
372385
room_chunk_size=room_chunk_size,
373386
max_messages=max_messages,
387+
all_messages=all_messages,
374388
)
375389

376390
# Determine if we should apply date filtering
@@ -385,6 +399,129 @@ def main(
385399
)
386400

387401

402+
@app.command()
403+
def add_users(
404+
webex_token: Annotated[
405+
str,
406+
typer.Option(
407+
...,
408+
envvar="WEBEX_TOKEN",
409+
prompt=(
410+
"Enter your Webex access token "
411+
"(https://developer.webex.com/docs/getting-started)"
412+
),
413+
hide_input=True,
414+
),
415+
],
416+
room_id: Annotated[
417+
str,
418+
typer.Option(..., help="Room ID to add users to"),
419+
],
420+
users_file: Annotated[
421+
Path,
422+
typer.Option(..., help="Path to YAML file containing user list"),
423+
],
424+
debug: Annotated[bool, typer.Option(help="Enable debug logging")] = False,
425+
) -> None:
426+
"""Add users from a YAML file to a Webex room.
427+
428+
This command reads a YAML file containing team member information (with cec_id
429+
fields) and adds each user to the specified Webex room. Users are added with
430+
email addresses in the format {cec_id}@cisco.com.
431+
432+
The YAML file should follow the team structure with a 'members' list where each
433+
member has a 'cec_id' field.
434+
435+
Example YAML structure:
436+
name: team-name
437+
members:
438+
- username: jsmith
439+
cec_id: jsmith
440+
full_name: John Smith
441+
442+
Users who are already members of the room are counted as successful additions.
443+
A report of failed additions (if any) will be written to failed_additions.yaml.
444+
"""
445+
if debug is True:
446+
logger.setLevel(logging.DEBUG)
447+
logger.debug("Debug logging enabled")
448+
449+
# Load user emails from YAML file
450+
try:
451+
user_emails = load_users_from_yaml(users_file)
452+
except (FileNotFoundError, ValueError, Exception) as e:
453+
console.print(f"[red]Error loading users from YAML file: {e}[/red]")
454+
raise typer.Exit(1) from e
455+
456+
if not user_emails:
457+
console.print("[yellow]No users found in YAML file. Exiting.[/yellow]")
458+
raise typer.Exit(0)
459+
460+
console.print(f"[blue]Loaded {len(user_emails)} users from {users_file}[/blue]")
461+
462+
# Initialize Webex client
463+
config = AppConfig(
464+
webex_token=webex_token,
465+
user_email="", # Not needed for this operation
466+
target_date=None,
467+
context_window_minutes=0,
468+
passive_participation=False,
469+
time_display_format="12h",
470+
room_chunk_size=50,
471+
max_messages=1000,
472+
all_messages=False,
473+
)
474+
client = WebexClient(config)
475+
476+
# Add users to room
477+
try:
478+
successful, failed = client.add_users_to_room(room_id, user_emails)
479+
except Exception as e:
480+
console.print(f"[red]Error adding users to room: {e}[/red]")
481+
raise typer.Exit(1) from e
482+
483+
# Display results
484+
console.print(
485+
f"\n[bold green]Successfully added {len(successful)} users "
486+
f"to the room[/bold green]"
487+
)
488+
489+
if failed:
490+
console.print(f"[bold yellow]Failed to add {len(failed)} users[/bold yellow]")
491+
492+
# Write failed additions to a report file
493+
failed_report_path = Path("failed_additions.yaml")
494+
try:
495+
import yaml
496+
497+
failed_data = {
498+
"room_id": room_id,
499+
"timestamp": datetime.now().isoformat(),
500+
"failed_users": [
501+
{"email": email, "error": error} for email, error in failed
502+
],
503+
}
504+
505+
with failed_report_path.open("w") as f:
506+
yaml.dump(failed_data, f, default_flow_style=False)
507+
508+
console.print(
509+
f"[yellow]Failed additions written to {failed_report_path}[/yellow]"
510+
)
511+
except Exception as e:
512+
logger.error("Failed to write error report: %s", e)
513+
console.print(
514+
f"[red]Warning: Could not write failed additions report: {e}[/red]"
515+
)
516+
517+
# Also print failed users to console for immediate visibility
518+
console.print("\n[yellow]Failed additions:[/yellow]")
519+
for email, error in failed:
520+
console.print(f" - {email}: {error}")
521+
else:
522+
console.print("[bold green]All users added successfully![/bold green]")
523+
524+
388525
if __name__ == "__main__":
389526
setup_logging()
390527
app()

summarizer/config.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ class AppConfig:
1919
time_display_format: Literal["12h", "24h"] = "12h"
2020
room_chunk_size: int = 50
2121
max_messages: int = 1000
22+
all_messages: bool = False
2223

2324

2425
def load_config_from_env() -> None:

0 commit comments

Comments
 (0)