magic-campus-sdk 0.1.0__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.
Files changed (65) hide show
  1. magic_campus_sdk-0.1.0/PKG-INFO +165 -0
  2. magic_campus_sdk-0.1.0/README.md +151 -0
  3. magic_campus_sdk-0.1.0/magic_campus_sdk.egg-info/PKG-INFO +165 -0
  4. magic_campus_sdk-0.1.0/magic_campus_sdk.egg-info/SOURCES.txt +63 -0
  5. magic_campus_sdk-0.1.0/magic_campus_sdk.egg-info/dependency_links.txt +1 -0
  6. magic_campus_sdk-0.1.0/magic_campus_sdk.egg-info/entry_points.txt +2 -0
  7. magic_campus_sdk-0.1.0/magic_campus_sdk.egg-info/requires.txt +6 -0
  8. magic_campus_sdk-0.1.0/magic_campus_sdk.egg-info/top_level.txt +2 -0
  9. magic_campus_sdk-0.1.0/magiccampus_cli/__init__.py +1 -0
  10. magic_campus_sdk-0.1.0/magiccampus_cli/__main__.py +9 -0
  11. magic_campus_sdk-0.1.0/magiccampus_cli/accounts.py +126 -0
  12. magic_campus_sdk-0.1.0/magiccampus_cli/cli.py +118 -0
  13. magic_campus_sdk-0.1.0/magiccampus_cli/client.py +99 -0
  14. magic_campus_sdk-0.1.0/magiccampus_cli/commands/auth.py +26 -0
  15. magic_campus_sdk-0.1.0/magiccampus_cli/commands/config.py +95 -0
  16. magic_campus_sdk-0.1.0/magiccampus_cli/commands/feed.py +23 -0
  17. magic_campus_sdk-0.1.0/magiccampus_cli/commands/im.py +20 -0
  18. magic_campus_sdk-0.1.0/magiccampus_cli/commands/notify.py +92 -0
  19. magic_campus_sdk-0.1.0/magiccampus_cli/commands/user.py +66 -0
  20. magic_campus_sdk-0.1.0/magiccampus_cli/config_store.py +57 -0
  21. magic_campus_sdk-0.1.0/magiccampus_cli/http_send.py +565 -0
  22. magic_campus_sdk-0.1.0/magiccampus_cli/notify.py +357 -0
  23. magic_campus_sdk-0.1.0/magiccampus_cli/output.py +101 -0
  24. magic_campus_sdk-0.1.0/magiccampus_cli/prompts.py +58 -0
  25. magic_campus_sdk-0.1.0/magiccampus_cli/targets.py +26 -0
  26. magic_campus_sdk-0.1.0/magiccampus_cli/utils.py +67 -0
  27. magic_campus_sdk-0.1.0/magiccampus_sdk/__init__.py +118 -0
  28. magic_campus_sdk-0.1.0/magiccampus_sdk/auth.py +111 -0
  29. magic_campus_sdk-0.1.0/magiccampus_sdk/client.py +89 -0
  30. magic_campus_sdk-0.1.0/magiccampus_sdk/example.py +46 -0
  31. magic_campus_sdk-0.1.0/magiccampus_sdk/example_ws.py +59 -0
  32. magic_campus_sdk-0.1.0/magiccampus_sdk/feed_client.py +21 -0
  33. magic_campus_sdk-0.1.0/magiccampus_sdk/im/__init__.py +85 -0
  34. magic_campus_sdk-0.1.0/magiccampus_sdk/im/client.py +913 -0
  35. magic_campus_sdk-0.1.0/magiccampus_sdk/im/gob_codec.py +289 -0
  36. magic_campus_sdk-0.1.0/magiccampus_sdk/im/http_api.py +58 -0
  37. magic_campus_sdk-0.1.0/magiccampus_sdk/im/media.py +761 -0
  38. magic_campus_sdk-0.1.0/magiccampus_sdk/im/models.py +583 -0
  39. magic_campus_sdk-0.1.0/magiccampus_sdk/im/proto/__init__.py +21 -0
  40. magic_campus_sdk-0.1.0/magiccampus_sdk/im/proto/sdkws/__init__.py +1 -0
  41. magic_campus_sdk-0.1.0/magiccampus_sdk/im/proto/sdkws/sdkws_pb2.py +215 -0
  42. magic_campus_sdk-0.1.0/magiccampus_sdk/im/proto/wrapperspb/__init__.py +1 -0
  43. magic_campus_sdk-0.1.0/magiccampus_sdk/im/proto/wrapperspb/wrapperspb_pb2.py +45 -0
  44. magic_campus_sdk-0.1.0/magiccampus_sdk/im/self_user_info_api.py +48 -0
  45. magic_campus_sdk-0.1.0/magiccampus_sdk/im/storage.py +213 -0
  46. magic_campus_sdk-0.1.0/magiccampus_sdk/im/text.py +49 -0
  47. magic_campus_sdk-0.1.0/magiccampus_sdk/im/ws_client.py +1235 -0
  48. magic_campus_sdk-0.1.0/magiccampus_sdk/models.py +164 -0
  49. magic_campus_sdk-0.1.0/magiccampus_sdk/platform_client.py +119 -0
  50. magic_campus_sdk-0.1.0/magiccampus_sdk/platform_http.py +71 -0
  51. magic_campus_sdk-0.1.0/magiccampus_sdk/platform_ws.py +122 -0
  52. magic_campus_sdk-0.1.0/magiccampus_sdk/user_client.py +36 -0
  53. magic_campus_sdk-0.1.0/magiccampus_sdk/user_info_api.py +55 -0
  54. magic_campus_sdk-0.1.0/pyproject.toml +37 -0
  55. magic_campus_sdk-0.1.0/setup.cfg +4 -0
  56. magic_campus_sdk-0.1.0/tests/test_auth.py +64 -0
  57. magic_campus_sdk-0.1.0/tests/test_auth_status.py +57 -0
  58. magic_campus_sdk-0.1.0/tests/test_cli_config.py +39 -0
  59. magic_campus_sdk-0.1.0/tests/test_cli_domains.py +204 -0
  60. magic_campus_sdk-0.1.0/tests/test_cli_interactive.py +34 -0
  61. magic_campus_sdk-0.1.0/tests/test_cli_main.py +23 -0
  62. magic_campus_sdk-0.1.0/tests/test_cli_notify.py +294 -0
  63. magic_campus_sdk-0.1.0/tests/test_im_namespace.py +18 -0
  64. magic_campus_sdk-0.1.0/tests/test_smoke_cli.py +53 -0
  65. magic_campus_sdk-0.1.0/tests/test_ws_client.py +73 -0
@@ -0,0 +1,165 @@
1
+ Metadata-Version: 2.4
2
+ Name: magic-campus-sdk
3
+ Version: 0.1.0
4
+ Summary: MagicCampus platform SDK and CLI with bundled IM transport support.
5
+ Author: MagicCampus Contributors
6
+ License-Expression: AGPL-3.0-or-later
7
+ Requires-Python: >=3.9
8
+ Description-Content-Type: text/markdown
9
+ Requires-Dist: httpx<1,>=0.27
10
+ Requires-Dist: protobuf<7,>=6.32.0
11
+ Requires-Dist: websocket-client<2,>=1.8.0
12
+ Provides-Extra: dev
13
+ Requires-Dist: pytest>=8.0; extra == "dev"
14
+
15
+ # magic-campus-sdk
16
+
17
+ Python SDK and CLI for MagicCampus platform integrations. IM remains a supported domain, and this repository keeps the bundled OpenIM transport inside `magiccampus_sdk`.
18
+
19
+ This project removes direct user-facing dependency on OpenIM token and endpoint configuration. You only configure:
20
+
21
+ - `apiurl`
22
+ - `apikey`
23
+ - `platform`
24
+
25
+ At runtime, IM-backed flows call:
26
+
27
+ `GET /api/v1/accounts/imToken?platform=<PLATFORM>`
28
+
29
+ and uses the response fields:
30
+
31
+ - `userId`
32
+ - `imToken`
33
+ - `wsApi`
34
+ - `httpApi`
35
+
36
+ ## Install locally
37
+
38
+ ```bash
39
+ uv sync
40
+ ```
41
+
42
+ This repository vendors only the OpenIM transport pieces that `magiccampus_sdk` actually uses, and layers platform-facing SDK / CLI commands on top.
43
+
44
+ IM-specific low-level internals, models, and protobufs now live under `magiccampus_sdk.im`.
45
+
46
+ ## CLI quick start
47
+
48
+ ```bash
49
+ magic-campus --help
50
+ magic-campus config init --apiurl https://api-test.pearlapi.com --apikey "$MAGICCAMPUS_APIKEY" --platform IOS --default true
51
+ magic-campus auth status --format pretty
52
+ magic-campus im notify send --to user:10134002 --text "hello"
53
+ magic-campus user get --id 10134002 --format pretty
54
+ ```
55
+
56
+ `magic-campus config init` also supports an interactive TTY flow when you omit auth flags.
57
+
58
+ `im notify send` sends over MagicCampus HTTP `POST /agent/v1/im/sendMessage`. `im notify history` still relies on the websocket transport and local sync database.
59
+
60
+ Legacy compatibility commands remain available:
61
+
62
+ ```bash
63
+ magic-campus notify +send --to user:10134002 --text "hello"
64
+ magic-campus notify +history --to user:10134002
65
+ ```
66
+
67
+ CLI config is stored at:
68
+
69
+ `~/.mushroom_agent/auth/magiccampus-im-sdk.json`
70
+
71
+ Supported commands:
72
+
73
+ - `config init|list|use|remove`
74
+ - `auth status`
75
+ - `im notify send`
76
+ - `im notify history`
77
+ - `user get`
78
+ - `feed list`
79
+ - `notify +send` (compat)
80
+ - `notify +history` (compat)
81
+
82
+ ## Python SDK quick start
83
+
84
+ ```python
85
+ from magiccampus_sdk import MagicCampusClient, MagicCampusClientConfig
86
+
87
+ client = MagicCampusClient(
88
+ MagicCampusClientConfig(
89
+ apiurl="https://api-test.pearlapi.com",
90
+ apikey="YOUR_API_KEY",
91
+ platform="IOS",
92
+ data_dir="./magiccampus_data",
93
+ )
94
+ )
95
+
96
+ user = client.user.get("10134002")
97
+ print(user.nickname)
98
+ print(user.avatar_url)
99
+ ```
100
+
101
+ ## Python websocket quick start
102
+
103
+ ```python
104
+ from magiccampus_sdk import MagicCampusWSSDK, MagicCampusWSConfig
105
+
106
+ sdk = MagicCampusWSSDK(
107
+ MagicCampusWSConfig(
108
+ apiurl="https://api-test.pearlapi.com",
109
+ apikey="YOUR_API_KEY",
110
+ platform="IOS",
111
+ data_dir="./magiccampus_data",
112
+ )
113
+ )
114
+
115
+ sdk.login()
116
+ sdk.start()
117
+ sdk.send_text("hello", recv_id="10134002")
118
+ ```
119
+
120
+ Runnable examples live in [magiccampus_sdk/example.py](magiccampus_sdk/example.py) and [magiccampus_sdk/example_ws.py](magiccampus_sdk/example_ws.py).
121
+
122
+ ## CLI smoke script
123
+
124
+ An executable smoke helper lives at [scripts/smoke_cli.py](scripts/smoke_cli.py).
125
+
126
+ Offline-safe mode only exercises config persistence and notify dry-run:
127
+
128
+ ```bash
129
+ uv run python scripts/smoke_cli.py
130
+ ```
131
+
132
+ This mode does not require a real API key. It uses a placeholder key by default and avoids any live auth call.
133
+
134
+ ## Real network mode
135
+
136
+ To run the live auth probe, provide a real API key and enable `--live`:
137
+
138
+ ```bash
139
+ export MAGICCAMPUS_APIURL=https://api-test.pearlapi.com
140
+ export MAGICCAMPUS_APIKEY='your real api key'
141
+ export MAGICCAMPUS_PLATFORM=IOS
142
+ uv run python scripts/smoke_cli.py --live
143
+ ```
144
+
145
+ Optional variables:
146
+
147
+ - `MAGICCAMPUS_SMOKE_TARGET`: target used by dry-run and optional live send, default `user:smoke-target`
148
+ - `MAGICCAMPUS_PLATFORM`: defaults to `IOS`
149
+
150
+ If you also want to send a real text message, set a real target and pass `--live-send`:
151
+
152
+ ```bash
153
+ export MAGICCAMPUS_SMOKE_TARGET='user:10134002'
154
+ uv run python scripts/smoke_cli.py --live --live-send --text 'hello from smoke script'
155
+ ```
156
+
157
+ `--live-send` performs a real outbound send, so use it only with a valid target and credentials.
158
+
159
+ ## Notes
160
+
161
+ - `apiurl` can point to any MagicCampus API base URL; IM-backed flows append `/api/v1/accounts/imToken`
162
+ - `client.user.get(...)` calls `GET /api/v1/accounts/getUserInfo` with `apiurl` and `apikey` directly
163
+ - `platform` defaults to `IOS`
164
+ - low-level IM send / receive behavior comes from the bundled transport modules inside `magiccampus_sdk`
165
+ - the wrapper does not persist raw OpenIM credentials in CLI config
@@ -0,0 +1,151 @@
1
+ # magic-campus-sdk
2
+
3
+ Python SDK and CLI for MagicCampus platform integrations. IM remains a supported domain, and this repository keeps the bundled OpenIM transport inside `magiccampus_sdk`.
4
+
5
+ This project removes direct user-facing dependency on OpenIM token and endpoint configuration. You only configure:
6
+
7
+ - `apiurl`
8
+ - `apikey`
9
+ - `platform`
10
+
11
+ At runtime, IM-backed flows call:
12
+
13
+ `GET /api/v1/accounts/imToken?platform=<PLATFORM>`
14
+
15
+ and uses the response fields:
16
+
17
+ - `userId`
18
+ - `imToken`
19
+ - `wsApi`
20
+ - `httpApi`
21
+
22
+ ## Install locally
23
+
24
+ ```bash
25
+ uv sync
26
+ ```
27
+
28
+ This repository vendors only the OpenIM transport pieces that `magiccampus_sdk` actually uses, and layers platform-facing SDK / CLI commands on top.
29
+
30
+ IM-specific low-level internals, models, and protobufs now live under `magiccampus_sdk.im`.
31
+
32
+ ## CLI quick start
33
+
34
+ ```bash
35
+ magic-campus --help
36
+ magic-campus config init --apiurl https://api-test.pearlapi.com --apikey "$MAGICCAMPUS_APIKEY" --platform IOS --default true
37
+ magic-campus auth status --format pretty
38
+ magic-campus im notify send --to user:10134002 --text "hello"
39
+ magic-campus user get --id 10134002 --format pretty
40
+ ```
41
+
42
+ `magic-campus config init` also supports an interactive TTY flow when you omit auth flags.
43
+
44
+ `im notify send` sends over MagicCampus HTTP `POST /agent/v1/im/sendMessage`. `im notify history` still relies on the websocket transport and local sync database.
45
+
46
+ Legacy compatibility commands remain available:
47
+
48
+ ```bash
49
+ magic-campus notify +send --to user:10134002 --text "hello"
50
+ magic-campus notify +history --to user:10134002
51
+ ```
52
+
53
+ CLI config is stored at:
54
+
55
+ `~/.mushroom_agent/auth/magiccampus-im-sdk.json`
56
+
57
+ Supported commands:
58
+
59
+ - `config init|list|use|remove`
60
+ - `auth status`
61
+ - `im notify send`
62
+ - `im notify history`
63
+ - `user get`
64
+ - `feed list`
65
+ - `notify +send` (compat)
66
+ - `notify +history` (compat)
67
+
68
+ ## Python SDK quick start
69
+
70
+ ```python
71
+ from magiccampus_sdk import MagicCampusClient, MagicCampusClientConfig
72
+
73
+ client = MagicCampusClient(
74
+ MagicCampusClientConfig(
75
+ apiurl="https://api-test.pearlapi.com",
76
+ apikey="YOUR_API_KEY",
77
+ platform="IOS",
78
+ data_dir="./magiccampus_data",
79
+ )
80
+ )
81
+
82
+ user = client.user.get("10134002")
83
+ print(user.nickname)
84
+ print(user.avatar_url)
85
+ ```
86
+
87
+ ## Python websocket quick start
88
+
89
+ ```python
90
+ from magiccampus_sdk import MagicCampusWSSDK, MagicCampusWSConfig
91
+
92
+ sdk = MagicCampusWSSDK(
93
+ MagicCampusWSConfig(
94
+ apiurl="https://api-test.pearlapi.com",
95
+ apikey="YOUR_API_KEY",
96
+ platform="IOS",
97
+ data_dir="./magiccampus_data",
98
+ )
99
+ )
100
+
101
+ sdk.login()
102
+ sdk.start()
103
+ sdk.send_text("hello", recv_id="10134002")
104
+ ```
105
+
106
+ Runnable examples live in [magiccampus_sdk/example.py](magiccampus_sdk/example.py) and [magiccampus_sdk/example_ws.py](magiccampus_sdk/example_ws.py).
107
+
108
+ ## CLI smoke script
109
+
110
+ An executable smoke helper lives at [scripts/smoke_cli.py](scripts/smoke_cli.py).
111
+
112
+ Offline-safe mode only exercises config persistence and notify dry-run:
113
+
114
+ ```bash
115
+ uv run python scripts/smoke_cli.py
116
+ ```
117
+
118
+ This mode does not require a real API key. It uses a placeholder key by default and avoids any live auth call.
119
+
120
+ ## Real network mode
121
+
122
+ To run the live auth probe, provide a real API key and enable `--live`:
123
+
124
+ ```bash
125
+ export MAGICCAMPUS_APIURL=https://api-test.pearlapi.com
126
+ export MAGICCAMPUS_APIKEY='your real api key'
127
+ export MAGICCAMPUS_PLATFORM=IOS
128
+ uv run python scripts/smoke_cli.py --live
129
+ ```
130
+
131
+ Optional variables:
132
+
133
+ - `MAGICCAMPUS_SMOKE_TARGET`: target used by dry-run and optional live send, default `user:smoke-target`
134
+ - `MAGICCAMPUS_PLATFORM`: defaults to `IOS`
135
+
136
+ If you also want to send a real text message, set a real target and pass `--live-send`:
137
+
138
+ ```bash
139
+ export MAGICCAMPUS_SMOKE_TARGET='user:10134002'
140
+ uv run python scripts/smoke_cli.py --live --live-send --text 'hello from smoke script'
141
+ ```
142
+
143
+ `--live-send` performs a real outbound send, so use it only with a valid target and credentials.
144
+
145
+ ## Notes
146
+
147
+ - `apiurl` can point to any MagicCampus API base URL; IM-backed flows append `/api/v1/accounts/imToken`
148
+ - `client.user.get(...)` calls `GET /api/v1/accounts/getUserInfo` with `apiurl` and `apikey` directly
149
+ - `platform` defaults to `IOS`
150
+ - low-level IM send / receive behavior comes from the bundled transport modules inside `magiccampus_sdk`
151
+ - the wrapper does not persist raw OpenIM credentials in CLI config
@@ -0,0 +1,165 @@
1
+ Metadata-Version: 2.4
2
+ Name: magic-campus-sdk
3
+ Version: 0.1.0
4
+ Summary: MagicCampus platform SDK and CLI with bundled IM transport support.
5
+ Author: MagicCampus Contributors
6
+ License-Expression: AGPL-3.0-or-later
7
+ Requires-Python: >=3.9
8
+ Description-Content-Type: text/markdown
9
+ Requires-Dist: httpx<1,>=0.27
10
+ Requires-Dist: protobuf<7,>=6.32.0
11
+ Requires-Dist: websocket-client<2,>=1.8.0
12
+ Provides-Extra: dev
13
+ Requires-Dist: pytest>=8.0; extra == "dev"
14
+
15
+ # magic-campus-sdk
16
+
17
+ Python SDK and CLI for MagicCampus platform integrations. IM remains a supported domain, and this repository keeps the bundled OpenIM transport inside `magiccampus_sdk`.
18
+
19
+ This project removes direct user-facing dependency on OpenIM token and endpoint configuration. You only configure:
20
+
21
+ - `apiurl`
22
+ - `apikey`
23
+ - `platform`
24
+
25
+ At runtime, IM-backed flows call:
26
+
27
+ `GET /api/v1/accounts/imToken?platform=<PLATFORM>`
28
+
29
+ and uses the response fields:
30
+
31
+ - `userId`
32
+ - `imToken`
33
+ - `wsApi`
34
+ - `httpApi`
35
+
36
+ ## Install locally
37
+
38
+ ```bash
39
+ uv sync
40
+ ```
41
+
42
+ This repository vendors only the OpenIM transport pieces that `magiccampus_sdk` actually uses, and layers platform-facing SDK / CLI commands on top.
43
+
44
+ IM-specific low-level internals, models, and protobufs now live under `magiccampus_sdk.im`.
45
+
46
+ ## CLI quick start
47
+
48
+ ```bash
49
+ magic-campus --help
50
+ magic-campus config init --apiurl https://api-test.pearlapi.com --apikey "$MAGICCAMPUS_APIKEY" --platform IOS --default true
51
+ magic-campus auth status --format pretty
52
+ magic-campus im notify send --to user:10134002 --text "hello"
53
+ magic-campus user get --id 10134002 --format pretty
54
+ ```
55
+
56
+ `magic-campus config init` also supports an interactive TTY flow when you omit auth flags.
57
+
58
+ `im notify send` sends over MagicCampus HTTP `POST /agent/v1/im/sendMessage`. `im notify history` still relies on the websocket transport and local sync database.
59
+
60
+ Legacy compatibility commands remain available:
61
+
62
+ ```bash
63
+ magic-campus notify +send --to user:10134002 --text "hello"
64
+ magic-campus notify +history --to user:10134002
65
+ ```
66
+
67
+ CLI config is stored at:
68
+
69
+ `~/.mushroom_agent/auth/magiccampus-im-sdk.json`
70
+
71
+ Supported commands:
72
+
73
+ - `config init|list|use|remove`
74
+ - `auth status`
75
+ - `im notify send`
76
+ - `im notify history`
77
+ - `user get`
78
+ - `feed list`
79
+ - `notify +send` (compat)
80
+ - `notify +history` (compat)
81
+
82
+ ## Python SDK quick start
83
+
84
+ ```python
85
+ from magiccampus_sdk import MagicCampusClient, MagicCampusClientConfig
86
+
87
+ client = MagicCampusClient(
88
+ MagicCampusClientConfig(
89
+ apiurl="https://api-test.pearlapi.com",
90
+ apikey="YOUR_API_KEY",
91
+ platform="IOS",
92
+ data_dir="./magiccampus_data",
93
+ )
94
+ )
95
+
96
+ user = client.user.get("10134002")
97
+ print(user.nickname)
98
+ print(user.avatar_url)
99
+ ```
100
+
101
+ ## Python websocket quick start
102
+
103
+ ```python
104
+ from magiccampus_sdk import MagicCampusWSSDK, MagicCampusWSConfig
105
+
106
+ sdk = MagicCampusWSSDK(
107
+ MagicCampusWSConfig(
108
+ apiurl="https://api-test.pearlapi.com",
109
+ apikey="YOUR_API_KEY",
110
+ platform="IOS",
111
+ data_dir="./magiccampus_data",
112
+ )
113
+ )
114
+
115
+ sdk.login()
116
+ sdk.start()
117
+ sdk.send_text("hello", recv_id="10134002")
118
+ ```
119
+
120
+ Runnable examples live in [magiccampus_sdk/example.py](magiccampus_sdk/example.py) and [magiccampus_sdk/example_ws.py](magiccampus_sdk/example_ws.py).
121
+
122
+ ## CLI smoke script
123
+
124
+ An executable smoke helper lives at [scripts/smoke_cli.py](scripts/smoke_cli.py).
125
+
126
+ Offline-safe mode only exercises config persistence and notify dry-run:
127
+
128
+ ```bash
129
+ uv run python scripts/smoke_cli.py
130
+ ```
131
+
132
+ This mode does not require a real API key. It uses a placeholder key by default and avoids any live auth call.
133
+
134
+ ## Real network mode
135
+
136
+ To run the live auth probe, provide a real API key and enable `--live`:
137
+
138
+ ```bash
139
+ export MAGICCAMPUS_APIURL=https://api-test.pearlapi.com
140
+ export MAGICCAMPUS_APIKEY='your real api key'
141
+ export MAGICCAMPUS_PLATFORM=IOS
142
+ uv run python scripts/smoke_cli.py --live
143
+ ```
144
+
145
+ Optional variables:
146
+
147
+ - `MAGICCAMPUS_SMOKE_TARGET`: target used by dry-run and optional live send, default `user:smoke-target`
148
+ - `MAGICCAMPUS_PLATFORM`: defaults to `IOS`
149
+
150
+ If you also want to send a real text message, set a real target and pass `--live-send`:
151
+
152
+ ```bash
153
+ export MAGICCAMPUS_SMOKE_TARGET='user:10134002'
154
+ uv run python scripts/smoke_cli.py --live --live-send --text 'hello from smoke script'
155
+ ```
156
+
157
+ `--live-send` performs a real outbound send, so use it only with a valid target and credentials.
158
+
159
+ ## Notes
160
+
161
+ - `apiurl` can point to any MagicCampus API base URL; IM-backed flows append `/api/v1/accounts/imToken`
162
+ - `client.user.get(...)` calls `GET /api/v1/accounts/getUserInfo` with `apiurl` and `apikey` directly
163
+ - `platform` defaults to `IOS`
164
+ - low-level IM send / receive behavior comes from the bundled transport modules inside `magiccampus_sdk`
165
+ - the wrapper does not persist raw OpenIM credentials in CLI config
@@ -0,0 +1,63 @@
1
+ README.md
2
+ pyproject.toml
3
+ magic_campus_sdk.egg-info/PKG-INFO
4
+ magic_campus_sdk.egg-info/SOURCES.txt
5
+ magic_campus_sdk.egg-info/dependency_links.txt
6
+ magic_campus_sdk.egg-info/entry_points.txt
7
+ magic_campus_sdk.egg-info/requires.txt
8
+ magic_campus_sdk.egg-info/top_level.txt
9
+ magiccampus_cli/__init__.py
10
+ magiccampus_cli/__main__.py
11
+ magiccampus_cli/accounts.py
12
+ magiccampus_cli/cli.py
13
+ magiccampus_cli/client.py
14
+ magiccampus_cli/config_store.py
15
+ magiccampus_cli/http_send.py
16
+ magiccampus_cli/notify.py
17
+ magiccampus_cli/output.py
18
+ magiccampus_cli/prompts.py
19
+ magiccampus_cli/targets.py
20
+ magiccampus_cli/utils.py
21
+ magiccampus_cli/commands/auth.py
22
+ magiccampus_cli/commands/config.py
23
+ magiccampus_cli/commands/feed.py
24
+ magiccampus_cli/commands/im.py
25
+ magiccampus_cli/commands/notify.py
26
+ magiccampus_cli/commands/user.py
27
+ magiccampus_sdk/__init__.py
28
+ magiccampus_sdk/auth.py
29
+ magiccampus_sdk/client.py
30
+ magiccampus_sdk/example.py
31
+ magiccampus_sdk/example_ws.py
32
+ magiccampus_sdk/feed_client.py
33
+ magiccampus_sdk/models.py
34
+ magiccampus_sdk/platform_client.py
35
+ magiccampus_sdk/platform_http.py
36
+ magiccampus_sdk/platform_ws.py
37
+ magiccampus_sdk/user_client.py
38
+ magiccampus_sdk/user_info_api.py
39
+ magiccampus_sdk/im/__init__.py
40
+ magiccampus_sdk/im/client.py
41
+ magiccampus_sdk/im/gob_codec.py
42
+ magiccampus_sdk/im/http_api.py
43
+ magiccampus_sdk/im/media.py
44
+ magiccampus_sdk/im/models.py
45
+ magiccampus_sdk/im/self_user_info_api.py
46
+ magiccampus_sdk/im/storage.py
47
+ magiccampus_sdk/im/text.py
48
+ magiccampus_sdk/im/ws_client.py
49
+ magiccampus_sdk/im/proto/__init__.py
50
+ magiccampus_sdk/im/proto/sdkws/__init__.py
51
+ magiccampus_sdk/im/proto/sdkws/sdkws_pb2.py
52
+ magiccampus_sdk/im/proto/wrapperspb/__init__.py
53
+ magiccampus_sdk/im/proto/wrapperspb/wrapperspb_pb2.py
54
+ tests/test_auth.py
55
+ tests/test_auth_status.py
56
+ tests/test_cli_config.py
57
+ tests/test_cli_domains.py
58
+ tests/test_cli_interactive.py
59
+ tests/test_cli_main.py
60
+ tests/test_cli_notify.py
61
+ tests/test_im_namespace.py
62
+ tests/test_smoke_cli.py
63
+ tests/test_ws_client.py
@@ -0,0 +1,2 @@
1
+ [console_scripts]
2
+ magic-campus = magiccampus_cli.__main__:main
@@ -0,0 +1,6 @@
1
+ httpx<1,>=0.27
2
+ protobuf<7,>=6.32.0
3
+ websocket-client<2,>=1.8.0
4
+
5
+ [dev]
6
+ pytest>=8.0
@@ -0,0 +1,2 @@
1
+ magiccampus_cli
2
+ magiccampus_sdk
@@ -0,0 +1 @@
1
+ __version__ = "0.1.0"
@@ -0,0 +1,9 @@
1
+ from .cli import main as cli_main
2
+
3
+
4
+ def main() -> int:
5
+ return cli_main()
6
+
7
+
8
+ if __name__ == "__main__":
9
+ raise SystemExit(main())
@@ -0,0 +1,126 @@
1
+ from __future__ import annotations
2
+
3
+ from dataclasses import dataclass
4
+
5
+ from magiccampus_sdk.auth import normalize_apiurl, normalize_platform
6
+
7
+ from .utils import env_string, mask_secret, trim_string
8
+
9
+
10
+ @dataclass(frozen=True)
11
+ class AccountConfig:
12
+ account_id: str
13
+ enabled: bool
14
+ apiurl: str
15
+ apikey: str
16
+ platform: str
17
+
18
+
19
+ def account_config_to_raw(account: AccountConfig) -> dict[str, object]:
20
+ return {
21
+ "enabled": account.enabled,
22
+ "apiUrl": account.apiurl,
23
+ "apiKey": account.apikey,
24
+ "platform": account.platform,
25
+ }
26
+
27
+
28
+ def normalize_stored_account(raw: object) -> dict[str, object]:
29
+ source = raw if isinstance(raw, dict) else {}
30
+ apiurl = trim_string(source.get("apiUrl") or source.get("apiurl"))
31
+ platform = trim_string(source.get("platform")) or "IOS"
32
+ normalized: dict[str, object] = {
33
+ "enabled": source.get("enabled") is not False,
34
+ "apiUrl": normalize_apiurl(apiurl) if apiurl else "",
35
+ "apiKey": trim_string(source.get("apiKey") or source.get("apikey")),
36
+ "platform": normalize_platform(platform),
37
+ }
38
+ return normalized
39
+
40
+
41
+ def env_default_account() -> dict[str, object] | None:
42
+ apiurl = env_string("MAGICCAMPUS_APIURL")
43
+ apikey = env_string("MAGICCAMPUS_APIKEY")
44
+ if not apiurl or not apikey:
45
+ return None
46
+
47
+ return {
48
+ "enabled": True,
49
+ "apiUrl": apiurl,
50
+ "apiKey": apikey,
51
+ "platform": env_string("MAGICCAMPUS_PLATFORM") or "IOS",
52
+ }
53
+
54
+
55
+ def normalize_account(account_id: str, raw: object) -> AccountConfig | None:
56
+ stored = normalize_stored_account(raw)
57
+ if not stored["apiUrl"] or not stored["apiKey"]:
58
+ return None
59
+
60
+ return AccountConfig(
61
+ account_id=account_id,
62
+ enabled=stored.get("enabled") is not False,
63
+ apiurl=str(stored["apiUrl"]),
64
+ apikey=str(stored["apiKey"]),
65
+ platform=str(stored["platform"]),
66
+ )
67
+
68
+
69
+ def list_account_ids(root: dict[str, object]) -> list[str]:
70
+ accounts = root.get("accounts")
71
+ ids = list(accounts.keys()) if isinstance(accounts, dict) else []
72
+ if env_default_account() and "default" not in ids:
73
+ ids.insert(0, "default")
74
+ return ids
75
+
76
+
77
+ def get_account_config(root: dict[str, object], account_id: str | None) -> AccountConfig | None:
78
+ resolved_id = account_id or str(root.get("defaultAccountId") or "default")
79
+ if resolved_id == "default":
80
+ env_account = env_default_account()
81
+ if env_account is not None:
82
+ return normalize_account("default", env_account)
83
+
84
+ accounts = root.get("accounts")
85
+ configured = accounts.get(resolved_id) if isinstance(accounts, dict) else None
86
+ if configured is not None:
87
+ return normalize_account(resolved_id, configured)
88
+ return None
89
+
90
+
91
+ def list_account_summaries(root: dict[str, object]) -> list[dict[str, object]]:
92
+ summaries: list[dict[str, object]] = []
93
+ default_account_id = str(root.get("defaultAccountId") or "default")
94
+ for account_id in list_account_ids(root):
95
+ account = get_account_config(root, account_id)
96
+ if account is None:
97
+ continue
98
+ summaries.append(
99
+ {
100
+ "accountId": account.account_id,
101
+ "default": account.account_id == default_account_id,
102
+ "enabled": account.enabled,
103
+ "apiUrl": account.apiurl,
104
+ "platform": account.platform,
105
+ }
106
+ )
107
+ return summaries
108
+
109
+
110
+ def upsert_stored_account(root: dict[str, object], account_id: str, raw_account: dict[str, object], make_default: bool = False) -> dict[str, object]:
111
+ accounts = root.get("accounts")
112
+ next_accounts = dict(accounts) if isinstance(accounts, dict) else {}
113
+ next_accounts[account_id] = normalize_stored_account(raw_account)
114
+ default_account_id = account_id if make_default else str(root.get("defaultAccountId") or account_id)
115
+ return {"defaultAccountId": default_account_id, "accounts": next_accounts}
116
+
117
+
118
+ def remove_stored_account(root: dict[str, object], account_id: str) -> dict[str, object]:
119
+ accounts = root.get("accounts")
120
+ next_accounts = dict(accounts) if isinstance(accounts, dict) else {}
121
+ next_accounts.pop(account_id, None)
122
+ remaining_ids = list(next_accounts.keys())
123
+ default_account_id = str(root.get("defaultAccountId") or "default")
124
+ if default_account_id == account_id:
125
+ default_account_id = remaining_ids[0] if remaining_ids else "default"
126
+ return {"defaultAccountId": default_account_id, "accounts": next_accounts}