pingthings 0.1.0

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 (177) hide show
  1. package/LICENSE +11 -0
  2. package/README.md +262 -0
  3. package/bin/pingthings.js +78 -0
  4. package/package.json +34 -0
  5. package/packs/0ad-civilizations/manifest.json +77 -0
  6. package/packs/0ad-civilizations/sounds/alarm-alert.wav +0 -0
  7. package/packs/0ad-civilizations/sounds/alarm-attack.wav +0 -0
  8. package/packs/0ad-civilizations/sounds/alarm-defeat.wav +0 -0
  9. package/packs/0ad-civilizations/sounds/alarm-no-resource.wav +0 -0
  10. package/packs/0ad-civilizations/sounds/alarm-objective.wav +0 -0
  11. package/packs/0ad-civilizations/sounds/alarm-research-complete.wav +0 -0
  12. package/packs/0ad-civilizations/sounds/alarm-victory.wav +0 -0
  13. package/packs/0ad-civilizations/sounds/greek-as-you-wish.wav +0 -0
  14. package/packs/0ad-civilizations/sounds/greek-attack-1.wav +0 -0
  15. package/packs/0ad-civilizations/sounds/greek-build-1.wav +0 -0
  16. package/packs/0ad-civilizations/sounds/greek-heal-1.wav +0 -0
  17. package/packs/0ad-civilizations/sounds/greek-march-1.wav +0 -0
  18. package/packs/0ad-civilizations/sounds/greek-my-lord-1.wav +0 -0
  19. package/packs/0ad-civilizations/sounds/greek-my-lord-2.wav +0 -0
  20. package/packs/0ad-civilizations/sounds/greek-retreat-1.wav +0 -0
  21. package/packs/0ad-civilizations/sounds/greek-what-is-it-1.wav +0 -0
  22. package/packs/0ad-civilizations/sounds/greek-yes.wav +0 -0
  23. package/packs/0ad-civilizations/sounds/latin-attack-1.wav +0 -0
  24. package/packs/0ad-civilizations/sounds/latin-build-1.wav +0 -0
  25. package/packs/0ad-civilizations/sounds/latin-fight-1.wav +0 -0
  26. package/packs/0ad-civilizations/sounds/latin-heal-1.wav +0 -0
  27. package/packs/0ad-civilizations/sounds/latin-hello-1.wav +0 -0
  28. package/packs/0ad-civilizations/sounds/latin-my-lord-1.wav +0 -0
  29. package/packs/0ad-civilizations/sounds/latin-what-is-it.wav +0 -0
  30. package/packs/0ad-civilizations/sounds/persian-attack-1.wav +0 -0
  31. package/packs/0ad-civilizations/sounds/persian-by-your-order.wav +0 -0
  32. package/packs/0ad-civilizations/sounds/persian-forward-1.wav +0 -0
  33. package/packs/0ad-civilizations/sounds/persian-i-will-go.wav +0 -0
  34. package/packs/7kaa-soldiers/manifest.json +111 -0
  35. package/packs/7kaa-soldiers/sounds/00001-CH_A2.wav +0 -0
  36. package/packs/7kaa-soldiers/sounds/00006-NO_V2.wav +0 -0
  37. package/packs/7kaa-soldiers/sounds/00007-NO_V3.wav +0 -0
  38. package/packs/7kaa-soldiers/sounds/00008-MA_V1.wav +0 -0
  39. package/packs/7kaa-soldiers/sounds/00009-GR_V2.wav +0 -0
  40. package/packs/7kaa-soldiers/sounds/00010-GR_V3.wav +0 -0
  41. package/packs/7kaa-soldiers/sounds/00011-VI_V1.wav +0 -0
  42. package/packs/7kaa-soldiers/sounds/00012-NO_A1.wav +0 -0
  43. package/packs/7kaa-soldiers/sounds/00012-VI_V2.wav +0 -0
  44. package/packs/7kaa-soldiers/sounds/00013-GR_V1.wav +0 -0
  45. package/packs/7kaa-soldiers/sounds/00013-NO_A2.wav +0 -0
  46. package/packs/7kaa-soldiers/sounds/00014-MA_A1.wav +0 -0
  47. package/packs/7kaa-soldiers/sounds/00014-PE_V1.wav +0 -0
  48. package/packs/7kaa-soldiers/sounds/00015-GR_A1.wav +0 -0
  49. package/packs/7kaa-soldiers/sounds/00015-MA_V2.wav +0 -0
  50. package/packs/7kaa-soldiers/sounds/00016-MA_V3.wav +0 -0
  51. package/packs/7kaa-soldiers/sounds/00016-VI_A1.wav +0 -0
  52. package/packs/7kaa-soldiers/sounds/00017-MA_V4.wav +0 -0
  53. package/packs/7kaa-soldiers/sounds/00017-VI_A2.wav +0 -0
  54. package/packs/7kaa-soldiers/sounds/00018-PE_A2.wav +0 -0
  55. package/packs/7kaa-soldiers/sounds/00018-PE_V2.wav +0 -0
  56. package/packs/7kaa-soldiers/sounds/00019-PE_V3.wav +0 -0
  57. package/packs/7kaa-soldiers/sounds/00020-PE_A1.wav +0 -0
  58. package/packs/7kaa-soldiers/sounds/00020-PE_V4.wav +0 -0
  59. package/packs/7kaa-soldiers/sounds/00021-CH_A1.wav +0 -0
  60. package/packs/7kaa-soldiers/sounds/00021-CH_V1.wav +0 -0
  61. package/packs/7kaa-soldiers/sounds/00022-CH_V2.wav +0 -0
  62. package/packs/7kaa-soldiers/sounds/00022-JA_A1.wav +0 -0
  63. package/packs/7kaa-soldiers/sounds/00023-CH_V3.wav +0 -0
  64. package/packs/7kaa-soldiers/sounds/00023-JA_A2.wav +0 -0
  65. package/packs/7kaa-soldiers/sounds/00024-CH_V4.wav +0 -0
  66. package/packs/7kaa-soldiers/sounds/00025-CH_V5.wav +0 -0
  67. package/packs/7kaa-soldiers/sounds/00026-JA_V1.wav +0 -0
  68. package/packs/7kaa-soldiers/sounds/00027-JA_V2.wav +0 -0
  69. package/packs/7kaa-soldiers/sounds/00028-JA_V3.wav +0 -0
  70. package/packs/7kaa-soldiers/sounds/00029-JA_V4.wav +0 -0
  71. package/packs/7kaa-soldiers/sounds/00030-JA_V5.wav +0 -0
  72. package/packs/7kaa-soldiers/sounds/00035-MA_V5.wav +0 -0
  73. package/packs/7kaa-soldiers/sounds/00083-READY.wav +0 -0
  74. package/packs/7kaa-soldiers/sounds/00084-NO_V1.wav +0 -0
  75. package/packs/7kaa-soldiers/sounds/00085-EG_V1.wav +0 -0
  76. package/packs/7kaa-soldiers/sounds/00086-EG_V2.wav +0 -0
  77. package/packs/7kaa-soldiers/sounds/00087-EG_V3.wav +0 -0
  78. package/packs/7kaa-soldiers/sounds/00088-EG_V4.wav +0 -0
  79. package/packs/7kaa-soldiers/sounds/00089-IN_V1.wav +0 -0
  80. package/packs/7kaa-soldiers/sounds/00090-IN_V2.wav +0 -0
  81. package/packs/7kaa-soldiers/sounds/00091-IN_V3.wav +0 -0
  82. package/packs/7kaa-soldiers/sounds/00092-IN_V4.wav +0 -0
  83. package/packs/7kaa-soldiers/sounds/00093-ZU_V2.wav +0 -0
  84. package/packs/7kaa-soldiers/sounds/00094-ZU_V3.wav +0 -0
  85. package/packs/7kaa-soldiers/sounds/00095-ZU_V5.wav +0 -0
  86. package/packs/7kaa-soldiers/sounds/00096-ZU_V7.wav +0 -0
  87. package/packs/7kaa-soldiers/sounds/00097-ZU_V8.wav +0 -0
  88. package/packs/freedoom-arsenal/manifest.json +57 -0
  89. package/packs/freedoom-arsenal/sounds/dsbarexp.wav +0 -0
  90. package/packs/freedoom-arsenal/sounds/dsbfg.wav +0 -0
  91. package/packs/freedoom-arsenal/sounds/dsdoropn.wav +0 -0
  92. package/packs/freedoom-arsenal/sounds/dsdshtgn.wav +0 -0
  93. package/packs/freedoom-arsenal/sounds/dsgetpow.wav +0 -0
  94. package/packs/freedoom-arsenal/sounds/dsitemup.wav +0 -0
  95. package/packs/freedoom-arsenal/sounds/dsoof.wav +0 -0
  96. package/packs/freedoom-arsenal/sounds/dspistol.wav +0 -0
  97. package/packs/freedoom-arsenal/sounds/dsplasma.wav +0 -0
  98. package/packs/freedoom-arsenal/sounds/dspldeth.wav +0 -0
  99. package/packs/freedoom-arsenal/sounds/dspunch.wav +0 -0
  100. package/packs/freedoom-arsenal/sounds/dsrlaunc.wav +0 -0
  101. package/packs/freedoom-arsenal/sounds/dsrxplod.wav +0 -0
  102. package/packs/freedoom-arsenal/sounds/dssawup.wav +0 -0
  103. package/packs/freedoom-arsenal/sounds/dssgcock.wav +0 -0
  104. package/packs/freedoom-arsenal/sounds/dsshotgn.wav +0 -0
  105. package/packs/freedoom-arsenal/sounds/dsswtchn.wav +0 -0
  106. package/packs/freedoom-arsenal/sounds/dstelept.wav +0 -0
  107. package/packs/freedoom-arsenal/sounds/dswpnup.wav +0 -0
  108. package/packs/openarena-announcer/manifest.json +54 -0
  109. package/packs/openarena-announcer/sounds/accuracy.wav +0 -0
  110. package/packs/openarena-announcer/sounds/assist.wav +0 -0
  111. package/packs/openarena-announcer/sounds/defense.wav +0 -0
  112. package/packs/openarena-announcer/sounds/denied.wav +0 -0
  113. package/packs/openarena-announcer/sounds/excellent.wav +0 -0
  114. package/packs/openarena-announcer/sounds/fight.wav +0 -0
  115. package/packs/openarena-announcer/sounds/gauntlet.wav +0 -0
  116. package/packs/openarena-announcer/sounds/humiliation.wav +0 -0
  117. package/packs/openarena-announcer/sounds/impressive.wav +0 -0
  118. package/packs/openarena-announcer/sounds/one.wav +0 -0
  119. package/packs/openarena-announcer/sounds/perfect.wav +0 -0
  120. package/packs/openarena-announcer/sounds/prepare.wav +0 -0
  121. package/packs/openarena-announcer/sounds/sudden_death.wav +0 -0
  122. package/packs/openarena-announcer/sounds/takenlead.wav +0 -0
  123. package/packs/openarena-announcer/sounds/three.wav +0 -0
  124. package/packs/openarena-announcer/sounds/two.wav +0 -0
  125. package/packs/openarena-announcer/sounds/voc_holyshit.wav +0 -0
  126. package/packs/openarena-announcer/sounds/youwin.wav +0 -0
  127. package/packs/warzone2100-command/manifest.json +63 -0
  128. package/packs/warzone2100-command/sounds/construction-completed.wav +0 -0
  129. package/packs/warzone2100-command/sounds/design-completed.wav +0 -0
  130. package/packs/warzone2100-command/sounds/enemy-detected.wav +0 -0
  131. package/packs/warzone2100-command/sounds/incoming-enemy-transport.wav +0 -0
  132. package/packs/warzone2100-command/sounds/incoming-transmission.wav +0 -0
  133. package/packs/warzone2100-command/sounds/major-research-completed.wav +0 -0
  134. package/packs/warzone2100-command/sounds/mission-failed.wav +0 -0
  135. package/packs/warzone2100-command/sounds/mission-objective.wav +0 -0
  136. package/packs/warzone2100-command/sounds/mission-successful.wav +0 -0
  137. package/packs/warzone2100-command/sounds/mission-update.wav +0 -0
  138. package/packs/warzone2100-command/sounds/new-research-available.wav +0 -0
  139. package/packs/warzone2100-command/sounds/nexus-laugh1.wav +0 -0
  140. package/packs/warzone2100-command/sounds/nexus-laugh2.wav +0 -0
  141. package/packs/warzone2100-command/sounds/power-low.wav +0 -0
  142. package/packs/warzone2100-command/sounds/production-cancelled.wav +0 -0
  143. package/packs/warzone2100-command/sounds/production-completed.wav +0 -0
  144. package/packs/warzone2100-command/sounds/reinforcements-available.wav +0 -0
  145. package/packs/warzone2100-command/sounds/research-completed.wav +0 -0
  146. package/packs/warzone2100-command/sounds/retreat-heavy-damage.wav +0 -0
  147. package/packs/warzone2100-command/sounds/structure-under-attack.wav +0 -0
  148. package/packs/warzone2100-command/sounds/unit-repaired.wav +0 -0
  149. package/packs/wesnoth-combat/manifest.json +58 -0
  150. package/packs/wesnoth-combat/sounds/axe.wav +0 -0
  151. package/packs/wesnoth-combat/sounds/bow.wav +0 -0
  152. package/packs/wesnoth-combat/sounds/crossbow.wav +0 -0
  153. package/packs/wesnoth-combat/sounds/dwarf-laugh.wav +0 -0
  154. package/packs/wesnoth-combat/sounds/explosion.wav +0 -0
  155. package/packs/wesnoth-combat/sounds/fanfare-short.wav +0 -0
  156. package/packs/wesnoth-combat/sounds/flame-big.wav +0 -0
  157. package/packs/wesnoth-combat/sounds/gold.wav +0 -0
  158. package/packs/wesnoth-combat/sounds/gryphon-shriek-1.wav +0 -0
  159. package/packs/wesnoth-combat/sounds/hatchet.wav +0 -0
  160. package/packs/wesnoth-combat/sounds/heal.wav +0 -0
  161. package/packs/wesnoth-combat/sounds/lightning.wav +0 -0
  162. package/packs/wesnoth-combat/sounds/magic-dark.wav +0 -0
  163. package/packs/wesnoth-combat/sounds/magic-holy-1.wav +0 -0
  164. package/packs/wesnoth-combat/sounds/magic-missile-1.wav +0 -0
  165. package/packs/wesnoth-combat/sounds/open-chest.wav +0 -0
  166. package/packs/wesnoth-combat/sounds/potion.wav +0 -0
  167. package/packs/wesnoth-combat/sounds/sword-1.wav +0 -0
  168. package/packs/wesnoth-combat/sounds/wolf-growl-1.wav +0 -0
  169. package/src/cli/config.js +42 -0
  170. package/src/cli/install.js +8 -0
  171. package/src/cli/list.js +25 -0
  172. package/src/cli/play.js +127 -0
  173. package/src/cli/preview.js +30 -0
  174. package/src/cli/use.js +25 -0
  175. package/src/config.js +48 -0
  176. package/src/packs.js +130 -0
  177. package/src/player.js +39 -0
@@ -0,0 +1,57 @@
1
+ {
2
+ "name": "freedoom-arsenal",
3
+ "description": "Retro FPS weapon and pickup sounds from Freedoom",
4
+ "version": "1.0.0",
5
+ "license": "BSD-3-Clause",
6
+ "credits": "Freedoom contributors (https://github.com/freedoom/freedoom)",
7
+ "sounds": [
8
+ "sounds/dsbarexp.wav",
9
+ "sounds/dsbfg.wav",
10
+ "sounds/dsdoropn.wav",
11
+ "sounds/dsdshtgn.wav",
12
+ "sounds/dsgetpow.wav",
13
+ "sounds/dsitemup.wav",
14
+ "sounds/dsoof.wav",
15
+ "sounds/dspistol.wav",
16
+ "sounds/dsplasma.wav",
17
+ "sounds/dspldeth.wav",
18
+ "sounds/dspunch.wav",
19
+ "sounds/dsrlaunc.wav",
20
+ "sounds/dsrxplod.wav",
21
+ "sounds/dssawup.wav",
22
+ "sounds/dssgcock.wav",
23
+ "sounds/dsshotgn.wav",
24
+ "sounds/dsswtchn.wav",
25
+ "sounds/dstelept.wav",
26
+ "sounds/dswpnup.wav"
27
+ ],
28
+ "events": {
29
+ "done": [
30
+ "sounds/dsitemup.wav",
31
+ "sounds/dsswtchn.wav",
32
+ "sounds/dspistol.wav",
33
+ "sounds/dspunch.wav"
34
+ ],
35
+ "permission": [
36
+ "sounds/dssgcock.wav",
37
+ "sounds/dssawup.wav",
38
+ "sounds/dsdoropn.wav"
39
+ ],
40
+ "complete": [
41
+ "sounds/dsgetpow.wav",
42
+ "sounds/dswpnup.wav",
43
+ "sounds/dstelept.wav"
44
+ ],
45
+ "error": [
46
+ "sounds/dsoof.wav",
47
+ "sounds/dsbarexp.wav",
48
+ "sounds/dsrxplod.wav",
49
+ "sounds/dspldeth.wav"
50
+ ],
51
+ "blocked": [
52
+ "sounds/dsbfg.wav",
53
+ "sounds/dsrlaunc.wav",
54
+ "sounds/dsdshtgn.wav"
55
+ ]
56
+ }
57
+ }
@@ -0,0 +1,54 @@
1
+ {
2
+ "name": "openarena-announcer",
3
+ "description": "Arena FPS announcer voice lines from OpenArena",
4
+ "version": "1.0.0",
5
+ "license": "GPL-2.0",
6
+ "credits": "OpenArena contributors (http://openarena.ws)",
7
+ "sounds": [
8
+ "sounds/accuracy.wav",
9
+ "sounds/assist.wav",
10
+ "sounds/defense.wav",
11
+ "sounds/denied.wav",
12
+ "sounds/excellent.wav",
13
+ "sounds/fight.wav",
14
+ "sounds/gauntlet.wav",
15
+ "sounds/humiliation.wav",
16
+ "sounds/impressive.wav",
17
+ "sounds/one.wav",
18
+ "sounds/perfect.wav",
19
+ "sounds/prepare.wav",
20
+ "sounds/sudden_death.wav",
21
+ "sounds/takenlead.wav",
22
+ "sounds/three.wav",
23
+ "sounds/two.wav",
24
+ "sounds/voc_holyshit.wav",
25
+ "sounds/youwin.wav"
26
+ ],
27
+ "events": {
28
+ "done": [
29
+ "sounds/excellent.wav",
30
+ "sounds/impressive.wav",
31
+ "sounds/accuracy.wav",
32
+ "sounds/assist.wav"
33
+ ],
34
+ "permission": [
35
+ "sounds/prepare.wav",
36
+ "sounds/fight.wav",
37
+ "sounds/defense.wav"
38
+ ],
39
+ "complete": [
40
+ "sounds/youwin.wav",
41
+ "sounds/perfect.wav",
42
+ "sounds/takenlead.wav"
43
+ ],
44
+ "error": [
45
+ "sounds/denied.wav",
46
+ "sounds/humiliation.wav",
47
+ "sounds/sudden_death.wav"
48
+ ],
49
+ "blocked": [
50
+ "sounds/voc_holyshit.wav",
51
+ "sounds/gauntlet.wav"
52
+ ]
53
+ }
54
+ }
@@ -0,0 +1,63 @@
1
+ {
2
+ "name": "warzone2100-command",
3
+ "description": "Sci-fi military commander voice lines from Warzone 2100",
4
+ "version": "1.0.0",
5
+ "license": "GPL-2.0",
6
+ "credits": "Warzone 2100 Project (https://github.com/Warzone2100/warzone2100)",
7
+ "sounds": [
8
+ "sounds/construction-completed.wav",
9
+ "sounds/design-completed.wav",
10
+ "sounds/enemy-detected.wav",
11
+ "sounds/incoming-enemy-transport.wav",
12
+ "sounds/incoming-transmission.wav",
13
+ "sounds/major-research-completed.wav",
14
+ "sounds/mission-failed.wav",
15
+ "sounds/mission-objective.wav",
16
+ "sounds/mission-successful.wav",
17
+ "sounds/mission-update.wav",
18
+ "sounds/new-research-available.wav",
19
+ "sounds/nexus-laugh1.wav",
20
+ "sounds/nexus-laugh2.wav",
21
+ "sounds/power-low.wav",
22
+ "sounds/production-cancelled.wav",
23
+ "sounds/production-completed.wav",
24
+ "sounds/reinforcements-available.wav",
25
+ "sounds/research-completed.wav",
26
+ "sounds/retreat-heavy-damage.wav",
27
+ "sounds/structure-under-attack.wav",
28
+ "sounds/unit-repaired.wav"
29
+ ],
30
+ "events": {
31
+ "done": [
32
+ "sounds/research-completed.wav",
33
+ "sounds/construction-completed.wav",
34
+ "sounds/production-completed.wav",
35
+ "sounds/design-completed.wav",
36
+ "sounds/unit-repaired.wav"
37
+ ],
38
+ "permission": [
39
+ "sounds/incoming-transmission.wav",
40
+ "sounds/mission-objective.wav",
41
+ "sounds/mission-update.wav",
42
+ "sounds/new-research-available.wav"
43
+ ],
44
+ "complete": [
45
+ "sounds/mission-successful.wav",
46
+ "sounds/major-research-completed.wav",
47
+ "sounds/reinforcements-available.wav"
48
+ ],
49
+ "error": [
50
+ "sounds/structure-under-attack.wav",
51
+ "sounds/power-low.wav",
52
+ "sounds/mission-failed.wav",
53
+ "sounds/production-cancelled.wav"
54
+ ],
55
+ "blocked": [
56
+ "sounds/enemy-detected.wav",
57
+ "sounds/incoming-enemy-transport.wav",
58
+ "sounds/retreat-heavy-damage.wav",
59
+ "sounds/nexus-laugh1.wav",
60
+ "sounds/nexus-laugh2.wav"
61
+ ]
62
+ }
63
+ }
@@ -0,0 +1,58 @@
1
+ {
2
+ "name": "wesnoth-combat",
3
+ "description": "Fantasy combat and magic sounds from Battle for Wesnoth",
4
+ "version": "1.0.0",
5
+ "license": "GPL-2.0",
6
+ "credits": "Battle for Wesnoth contributors (https://github.com/wesnoth/wesnoth) — licensed under GPL v2+",
7
+ "sounds": [
8
+ "sounds/axe.wav",
9
+ "sounds/bow.wav",
10
+ "sounds/crossbow.wav",
11
+ "sounds/dwarf-laugh.wav",
12
+ "sounds/explosion.wav",
13
+ "sounds/fanfare-short.wav",
14
+ "sounds/flame-big.wav",
15
+ "sounds/gold.wav",
16
+ "sounds/gryphon-shriek-1.wav",
17
+ "sounds/hatchet.wav",
18
+ "sounds/heal.wav",
19
+ "sounds/lightning.wav",
20
+ "sounds/magic-dark.wav",
21
+ "sounds/magic-holy-1.wav",
22
+ "sounds/magic-missile-1.wav",
23
+ "sounds/open-chest.wav",
24
+ "sounds/potion.wav",
25
+ "sounds/sword-1.wav",
26
+ "sounds/wolf-growl-1.wav"
27
+ ],
28
+ "events": {
29
+ "done": [
30
+ "sounds/gold.wav",
31
+ "sounds/sword-1.wav",
32
+ "sounds/bow.wav",
33
+ "sounds/crossbow.wav",
34
+ "sounds/hatchet.wav"
35
+ ],
36
+ "permission": [
37
+ "sounds/open-chest.wav",
38
+ "sounds/potion.wav",
39
+ "sounds/magic-holy-1.wav"
40
+ ],
41
+ "complete": [
42
+ "sounds/fanfare-short.wav",
43
+ "sounds/heal.wav",
44
+ "sounds/dwarf-laugh.wav"
45
+ ],
46
+ "error": [
47
+ "sounds/explosion.wav",
48
+ "sounds/flame-big.wav",
49
+ "sounds/lightning.wav",
50
+ "sounds/magic-dark.wav"
51
+ ],
52
+ "blocked": [
53
+ "sounds/wolf-growl-1.wav",
54
+ "sounds/gryphon-shriek-1.wav",
55
+ "sounds/magic-missile-1.wav"
56
+ ]
57
+ }
58
+ }
@@ -0,0 +1,42 @@
1
+ import { readConfig, writeConfig, VALID_MODES } from '../config.js';
2
+
3
+ const VALID_KEYS = ['activePack', 'mode', 'specificSound'];
4
+
5
+ export default function config(args) {
6
+ const [key, ...rest] = args;
7
+ const value = rest.join(' ') || undefined;
8
+
9
+ // No args: show full config
10
+ if (!key) {
11
+ const cfg = readConfig();
12
+ console.log(JSON.stringify(cfg, null, 2));
13
+ return;
14
+ }
15
+
16
+ // Validate key
17
+ if (!VALID_KEYS.includes(key)) {
18
+ console.error(`Unknown config key: ${key}`);
19
+ console.error(`Valid keys: ${VALID_KEYS.join(', ')}`);
20
+ process.exit(1);
21
+ }
22
+
23
+ // One arg: show value
24
+ if (value === undefined) {
25
+ const cfg = readConfig();
26
+ console.log(cfg[key] ?? '(not set)');
27
+ return;
28
+ }
29
+
30
+ // Validate mode values
31
+ if (key === 'mode' && !VALID_MODES.includes(value)) {
32
+ console.error(`Invalid mode: ${value}`);
33
+ console.error(`Valid modes: ${VALID_MODES.join(', ')}`);
34
+ process.exit(1);
35
+ }
36
+
37
+ // Two args: set value
38
+ const cfg = readConfig();
39
+ cfg[key] = value === 'null' ? null : value;
40
+ writeConfig(cfg);
41
+ console.log(`${key} set to: ${cfg[key]}`);
42
+ }
@@ -0,0 +1,8 @@
1
+ export default function install() {
2
+ console.log('Remote pack installation is coming in a future version.');
3
+ console.log('');
4
+ console.log('For now, you can manually install packs by placing them in:');
5
+ console.log(' ~/.config/pingthings/packs/<pack-name>/');
6
+ console.log('');
7
+ console.log('Each pack needs a manifest.json and a sounds/ directory.');
8
+ }
@@ -0,0 +1,25 @@
1
+ import { readConfig } from '../config.js';
2
+ import { listPacks } from '../packs.js';
3
+
4
+ export default function list() {
5
+ const config = readConfig();
6
+ const packs = listPacks();
7
+
8
+ if (packs.length === 0) {
9
+ console.log('No sound packs found.');
10
+ return;
11
+ }
12
+
13
+ console.log('\nAvailable sound packs:\n');
14
+
15
+ for (const pack of packs) {
16
+ const active = pack.name === config.activePack ? ' *' : ' ';
17
+ const source = pack.isBuiltIn ? 'built-in' : 'user';
18
+ console.log(`${active} ${pack.name} (${pack.soundCount} sounds, ${source})`);
19
+ if (pack.description) {
20
+ console.log(` ${pack.description}`);
21
+ }
22
+ }
23
+
24
+ console.log('\n * = active pack\n');
25
+ }