indico-cli 0.2.1__tar.gz → 0.4.1__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: indico-cli
3
- Version: 0.2.1
3
+ Version: 0.4.1
4
4
  Summary: CLI tool for interacting with Indico event management systems
5
5
  Project-URL: Repository, https://gitlab.cern.ch/cern-agent-skills/indico-cli
6
6
  License: MIT
@@ -28,7 +28,7 @@ version_tuple: VERSION_TUPLE
28
28
  commit_id: COMMIT_ID
29
29
  __commit_id__: COMMIT_ID
30
30
 
31
- __version__ = version = '0.2.1'
32
- __version_tuple__ = version_tuple = (0, 2, 1)
31
+ __version__ = version = '0.4.1'
32
+ __version_tuple__ = version_tuple = (0, 4, 1)
33
33
 
34
34
  __commit_id__ = commit_id = None
@@ -71,10 +71,21 @@ def cli(ctx, base_url, token):
71
71
 
72
72
  @cli.command()
73
73
  @click.option("--base-url", required=True, help="Indico instance URL")
74
- @click.option("--token", default="", help="API bearer token")
74
+ @click.option("--token", envvar="INDICO_API_TOKEN", default="", help="API bearer token (or set INDICO_API_TOKEN)")
75
75
  def configure(base_url, token):
76
76
  """Configure connection to an Indico instance and test it."""
77
- api = IndicoAPI(base_url, bearer_token=token if token else None)
77
+ if not token:
78
+ try:
79
+ token = click.prompt("API token", hide_input=True)
80
+ except (EOFError, click.Abort):
81
+ pass
82
+ if not token:
83
+ click.echo("Error: no token provided.", err=True)
84
+ click.echo("Either:", err=True)
85
+ click.echo(" 1. Run in a real terminal: indico-cli configure --base-url URL", err=True)
86
+ click.echo(" 2. Set env var first: export INDICO_API_TOKEN=indp_... && indico-cli configure --base-url URL", err=True)
87
+ sys.exit(1)
88
+ api = IndicoAPI(base_url, bearer_token=token)
78
89
  client = IndicoClient(api)
79
90
  try:
80
91
  result = run_async(client.get_user_info())
@@ -84,6 +95,7 @@ def configure(base_url, token):
84
95
  click.echo(f"Configuration saved to {CONFIG_FILE}")
85
96
  except Exception as error:
86
97
  click.echo(f"Connection test failed: {error}", err=True)
98
+ click.echo("Check that your token starts with 'indp_' and has the correct scopes.", err=True)
87
99
  sys.exit(1)
88
100
 
89
101
 
@@ -113,11 +125,14 @@ def search_events(ctx, category_id, from_date, to_date, limit, only_public):
113
125
  @cli.command("search-by-term")
114
126
  @click.option("--term", required=True, help="Search term")
115
127
  @click.option("--limit", type=int, default=50, help="Maximum number of results")
128
+ @click.option("--type", "type_filter", default=None,
129
+ type=click.Choice(["category", "event", "contribution", "subcontribution", "attachment", "event_note"]),
130
+ help="Filter to a specific content type")
116
131
  @click.pass_context
117
- def search_by_term(ctx, term, limit):
132
+ def search_by_term(ctx, term, limit, type_filter):
118
133
  """Search for events by keyword/term."""
119
134
  client = get_client(ctx.obj["base_url"], ctx.obj["token"])
120
- result = run_async(client.search_events_by_term(term, limit))
135
+ result = run_async(client.search_events_by_term(term, limit, type_filter))
121
136
  click.echo(result)
122
137
 
123
138
 
@@ -365,13 +365,12 @@ class IndicoClient:
365
365
  return response
366
366
 
367
367
  async def search_events_by_term(
368
- self, search_term: str, limit: int = 50
368
+ self, search_term: str, limit: int = 50, type_filter: Optional[str] = None
369
369
  ) -> str:
370
370
  """Search for content by keyword/term using comprehensive Indico search API"""
371
371
  try:
372
- # URL-encode the search term to handle special characters
373
372
  # Define all search types to query
374
- search_types = [
373
+ all_search_types = [
375
374
  ("category", "Categories"),
376
375
  ("event", "Events"),
377
376
  ("contribution", "Contributions"),
@@ -380,6 +379,14 @@ class IndicoClient:
380
379
  ("event_note", "Event Notes")
381
380
  ]
382
381
 
382
+ # Filter to specific type if requested
383
+ if type_filter:
384
+ search_types = [(t, d) for t, d in all_search_types if t == type_filter]
385
+ if not search_types:
386
+ return f"Unknown search type '{type_filter}'. Valid types: category, event, contribution, subcontribution, attachment, event_note"
387
+ else:
388
+ search_types = all_search_types
389
+
383
390
  all_results = {}
384
391
  total_found = 0
385
392
 
@@ -1243,12 +1250,17 @@ class IndicoClient:
1243
1250
  else:
1244
1251
  path = download_url
1245
1252
 
1253
+ # Build legacy export path if the URL uses /event/... format
1254
+ legacy_path = path
1255
+ if path.startswith("/event/") and not path.startswith("/export/"):
1256
+ legacy_path = f"/export{path}"
1257
+
1246
1258
  # Use our download method
1247
1259
  fake_file_info = {
1248
1260
  "filename": filename or "downloaded_file",
1249
1261
  "download_url": download_url,
1250
1262
  "api_path": path,
1251
- "legacy_path": path,
1263
+ "legacy_path": legacy_path,
1252
1264
  }
1253
1265
 
1254
1266
  file_response = await self.download_file_with_auth(fake_file_info, "unknown")
@@ -23,11 +23,13 @@ Set up or update Indico CLI credentials.
23
23
 
24
24
  1. **Check if already configured**: run `uvx indico-cli user-info 2>&1`. If it returns user info, stop — already configured.
25
25
  2. **Ask the user** which Indico instance to connect to (e.g., `https://indico.cern.ch`, `https://indico.fnal.gov`, or a custom URL).
26
- 3. **Guide token creation**: tell the user to open `<base_url>/user/preferences/api`, click "Create new token", name it (e.g., "indico-cli"), select scopes `read:legacy_api`, `write:legacy_api`, `read:user`, click "Create", and copy the `indp_...` token immediately (shown only once).
26
+ 3. **Guide token creation**: tell the user to open `<base_url>/user/tokens/`, click "Create new token", name it (e.g., "indico-cli"), select all scopes (you can avoid write in case want to play on the safe side), click "Create", and copy the `indp_...` token immediately (shown only once).
27
27
  4. **Save credentials**:
28
+
28
29
  ```bash
29
30
  uvx indico-cli configure --base-url <BASE_URL> --token <TOKEN>
30
31
  ```
32
+
31
33
  Saves to `~/.config/indico-cli/config.json` (never inside a repo).
32
34
  5. **Verify**: the configure command tests the connection automatically. On failure: 403/401 = wrong scopes or expired token; connection error = wrong URL; SSL error = network issue.
33
35
 
@@ -44,6 +46,7 @@ If an event returns "not found" or "deleted", don't stop — use `search-by-term
44
46
  ### Chaining commands for deeper answers
45
47
 
46
48
  Many tasks require chaining multiple commands. For example, to find out what someone concluded in a talk:
49
+
47
50
  1. `search-by-term` or `contributions` to find the relevant contribution
48
51
  2. `files` or `download` to get the slides/PDF
49
52
  3. **Read the downloaded file** and extract the answer
@@ -53,6 +56,7 @@ The goal is to answer the user's question, not just list metadata. If slides wer
53
56
  ### Using event IDs from search results
54
57
 
55
58
  `search-by-term` returns `Event ID` for every contribution, attachment, and note result. Use this ID to drill into the event:
59
+
56
60
  1. `search-by-term --term "my topic"` — find the contribution and note its Event ID
57
61
  2. `event-details --event-id <ID>` — get full event info
58
62
  3. `contributions --event-id <ID>` — list all contributions
@@ -71,13 +75,14 @@ The goal is to answer the user's question, not just list metadata. If slides wer
71
75
  ### search-by-term — Full-text search across all Indico content
72
76
 
73
77
  ```bash
74
- uvx indico-cli search-by-term --term "<query>" [--limit N]
78
+ uvx indico-cli search-by-term --term "<query>" [--limit N] [--type TYPE]
75
79
  ```
76
80
 
77
81
  | Parameter | Required | Description |
78
82
  |-----------|----------|-------------|
79
83
  | `--term` | Yes | Search keyword or phrase |
80
84
  | `--limit` | No | Max results per content type (default: 50) |
85
+ | `--type` | No | Filter to one content type: `event`, `contribution`, `subcontribution`, `attachment`, `event_note`, `category` |
81
86
 
82
87
  Searches categories, events, contributions, subcontributions, attachments, and notes.
83
88
 
@@ -155,6 +160,7 @@ uvx indico-cli files --event-id <ID> [--download | --no-download] [--download-di
155
160
  | `--download-dir` | No | Directory for downloads |
156
161
 
157
162
  If the built-in download fails (403), list with `--no-download` to get URLs, then use curl:
163
+
158
164
  ```bash
159
165
  curl -L -H "Authorization: Bearer $INDICO_API_TOKEN" -o filename.pdf "DOWNLOAD_URL"
160
166
  ```
@@ -309,11 +315,13 @@ Used by `create-event-with-agenda`. A JSON array where items with a `contributio
309
315
  ## Examples
310
316
 
311
317
  Search for beam dynamics content:
318
+
312
319
  ```bash
313
320
  uvx indico-cli search-by-term --term "beam dynamics" --limit 5
314
321
  ```
315
322
 
316
323
  Create a meeting with agenda:
324
+
317
325
  ```bash
318
326
  uvx indico-cli create-event-with-agenda \
319
327
  --title "Workshop on ML" \
@@ -327,11 +335,13 @@ uvx indico-cli create-event-with-agenda \
327
335
  ```
328
336
 
329
337
  Download all files from an event:
338
+
330
339
  ```bash
331
340
  uvx indico-cli files --event-id 137346
332
341
  ```
333
342
 
334
343
  Schedule a contribution:
344
+
335
345
  ```bash
336
346
  uvx indico-cli add-timetable-entry --event-id 137346 --type contribution --object-id 12 --start 2025-06-15T14:00:00 --duration 30
337
347
  ```
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes