dooray-mail-cli 0.2.3 → 0.2.4

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 (2) hide show
  1. package/dooray-cli.js +214 -3
  2. package/package.json +1 -1
package/dooray-cli.js CHANGED
@@ -14,6 +14,10 @@ const os = require('os');
14
14
  const CONFIG_PATH = path.join(os.homedir(), '.dooray-config.json');
15
15
  const CACHE_PATH = path.join(os.homedir(), '.dooray-mail-cache.json');
16
16
 
17
+ // 버전 정보
18
+ const packageJson = require('./package.json');
19
+ const VERSION = packageJson.version;
20
+
17
21
  // CLI 명령어 파서
18
22
  const args = process.argv.slice(2);
19
23
  const command = args[0];
@@ -107,6 +111,14 @@ async function handleCommand() {
107
111
  case 'test':
108
112
  await testCommand();
109
113
  break;
114
+ case 'version':
115
+ case '--version':
116
+ case '-v':
117
+ console.log(`dooray-cli v${VERSION}`);
118
+ break;
119
+ case 'install-skill':
120
+ await installSkillCommand();
121
+ break;
110
122
  case 'help':
111
123
  case '--help':
112
124
  case '-h':
@@ -119,6 +131,54 @@ async function handleCommand() {
119
131
  }
120
132
  }
121
133
 
134
+ // 비밀번호 입력 (숨김 처리)
135
+ function readPassword(prompt) {
136
+ return new Promise((resolve) => {
137
+ const stdin = process.stdin;
138
+ const stdout = process.stdout;
139
+
140
+ stdout.write(prompt);
141
+
142
+ let password = '';
143
+ stdin.setRawMode(true);
144
+ stdin.resume();
145
+ stdin.setEncoding('utf8');
146
+
147
+ const onData = (char) => {
148
+ char = char.toString('utf8');
149
+
150
+ switch (char) {
151
+ case '\n':
152
+ case '\r':
153
+ case '\u0004':
154
+ stdin.setRawMode(false);
155
+ stdin.pause();
156
+ stdin.removeListener('data', onData);
157
+ stdout.write('\n');
158
+ resolve(password);
159
+ break;
160
+ case '\u0003':
161
+ process.exit();
162
+ break;
163
+ case '\u007f': // Backspace
164
+ if (password.length > 0) {
165
+ password = password.slice(0, -1);
166
+ stdout.write('\b \b');
167
+ }
168
+ break;
169
+ default:
170
+ if (char.charCodeAt(0) >= 32) {
171
+ password += char;
172
+ stdout.write('*');
173
+ }
174
+ break;
175
+ }
176
+ };
177
+
178
+ stdin.on('data', onData);
179
+ });
180
+ }
181
+
122
182
  // config: 설정 저장
123
183
  async function configCommand() {
124
184
  const readline = require('readline').createInterface({
@@ -132,7 +192,9 @@ async function configCommand() {
132
192
  console.log('\n📧 Dooray Configuration Setup\n');
133
193
 
134
194
  const email = await question('Email: ');
135
- const password = await question('Password: ');
195
+ readline.close();
196
+
197
+ const password = await readPassword('Password: ');
136
198
 
137
199
  const security = new SecurityManager();
138
200
  const encryptedPassword = await security.encryptToken(password);
@@ -146,8 +208,9 @@ async function configCommand() {
146
208
 
147
209
  saveConfig(config);
148
210
  console.log(`\n✅ Configuration saved to ${CONFIG_PATH}`);
149
- } finally {
211
+ } catch (error) {
150
212
  readline.close();
213
+ throw error;
151
214
  }
152
215
  }
153
216
 
@@ -831,6 +894,149 @@ async function testCommand() {
831
894
  }
832
895
  }
833
896
 
897
+ // OpenClaw 설치 위치 찾기
898
+ function findOpenClawInstallation() {
899
+ const { execSync } = require('child_process');
900
+
901
+ try {
902
+ // where (Windows) 또는 which (Unix) 명령어로 실행 파일 찾기
903
+ const command = process.platform === 'win32' ? 'where openclaw' : 'which openclaw';
904
+ const result = execSync(command, { encoding: 'utf8', stdio: ['pipe', 'pipe', 'ignore'] });
905
+ const openclawPath = result.trim().split('\n')[0];
906
+
907
+ if (openclawPath && fs.existsSync(openclawPath)) {
908
+ // 실행 파일의 디렉토리에서 상위로 올라가며 skills 폴더 찾기
909
+ let currentPath = path.dirname(openclawPath);
910
+ for (let i = 0; i < 5; i++) {
911
+ const skillsPath = path.join(currentPath, 'skills');
912
+ if (fs.existsSync(skillsPath)) {
913
+ return skillsPath;
914
+ }
915
+ const newPath = path.dirname(currentPath);
916
+ if (newPath === currentPath) break;
917
+ currentPath = newPath;
918
+ }
919
+
920
+ return path.dirname(openclawPath);
921
+ }
922
+ } catch (error) {
923
+ // OpenClaw 실행 파일을 찾지 못함
924
+ }
925
+
926
+ return null;
927
+ }
928
+
929
+ // install-skill: OpenClaw Skill 자동 설치
930
+ async function installSkillCommand() {
931
+ const readline = require('readline').createInterface({
932
+ input: process.stdin,
933
+ output: process.stdout
934
+ });
935
+
936
+ const question = (q) => new Promise(resolve => readline.question(q, resolve));
937
+
938
+ try {
939
+ console.log('\n📦 Installing Dooray Skill for OpenClaw...\n');
940
+
941
+ // 1. SKILL.md 위치 찾기
942
+ const currentDir = __dirname || path.dirname(process.argv[1]);
943
+ const localSkillMd = path.join(currentDir, 'SKILL.md');
944
+
945
+ if (!fs.existsSync(localSkillMd)) {
946
+ console.error('❌ SKILL.md not found in package directory');
947
+ console.log('💡 Try reinstalling: npm install -g dooray-mail-cli');
948
+ readline.close();
949
+ process.exit(1);
950
+ }
951
+
952
+ // 2. OpenClaw 설치 위치 찾기
953
+ console.log('🔍 Searching for OpenClaw installation...');
954
+ const openclawInstall = findOpenClawInstallation();
955
+
956
+ if (openclawInstall) {
957
+ console.log(`✅ Found OpenClaw installation: ${openclawInstall}`);
958
+ } else {
959
+ console.log('⚠️ OpenClaw executable not found in PATH');
960
+ }
961
+
962
+ // 3. OpenClaw skills 디렉토리 찾기 (여러 가능한 위치)
963
+ const possiblePaths = [
964
+ openclawInstall ? path.join(openclawInstall, 'skills') : null,
965
+ path.join(os.homedir(), 'skills'),
966
+ path.join(os.homedir(), '.openclaw', 'skills'),
967
+ path.join(os.homedir(), 'OpenClaw', 'skills'),
968
+ path.join(os.homedir(), '.config', 'openclaw', 'skills'),
969
+ ].filter(p => p !== null);
970
+
971
+ let skillsDir = null;
972
+
973
+ // 기존 skills 폴더 찾기
974
+ for (const dir of possiblePaths) {
975
+ if (fs.existsSync(dir)) {
976
+ skillsDir = dir;
977
+ console.log(`✅ Found OpenClaw skills directory: ${skillsDir}`);
978
+ break;
979
+ }
980
+ }
981
+
982
+ // 찾지 못한 경우 사용자에게 물어보기
983
+ if (!skillsDir) {
984
+ console.log('\n⚠️ OpenClaw skills directory not found in common locations.');
985
+ console.log('\nCommon locations:');
986
+ possiblePaths.forEach((p, i) => console.log(` ${i + 1}. ${p}`));
987
+ console.log(' 0. Enter custom path');
988
+
989
+ const choice = await question('\nSelect location (0-' + possiblePaths.length + '): ');
990
+ const idx = parseInt(choice);
991
+
992
+ if (idx === 0) {
993
+ const customPath = await question('Enter skills directory path: ');
994
+ skillsDir = customPath.trim();
995
+ } else if (idx >= 1 && idx <= possiblePaths.length) {
996
+ skillsDir = possiblePaths[idx - 1];
997
+ } else {
998
+ skillsDir = possiblePaths[0]; // 기본값
999
+ }
1000
+
1001
+ console.log(`\nUsing: ${skillsDir}`);
1002
+ }
1003
+
1004
+ const dooraySkillDir = path.join(skillsDir, 'dooray');
1005
+
1006
+ // 디렉토리 생성
1007
+ if (!fs.existsSync(skillsDir)) {
1008
+ fs.mkdirSync(skillsDir, { recursive: true });
1009
+ console.log(`✅ Created skills directory: ${skillsDir}`);
1010
+ }
1011
+
1012
+ if (!fs.existsSync(dooraySkillDir)) {
1013
+ fs.mkdirSync(dooraySkillDir, { recursive: true });
1014
+ console.log(`✅ Created dooray skill directory: ${dooraySkillDir}`);
1015
+ }
1016
+
1017
+ // 4. SKILL.md 복사
1018
+ const targetSkillMd = path.join(dooraySkillDir, 'SKILL.md');
1019
+ fs.copyFileSync(localSkillMd, targetSkillMd);
1020
+
1021
+ console.log(`✅ SKILL.md copied to: ${targetSkillMd}`);
1022
+ console.log('\n🎉 Dooray Skill installed successfully!');
1023
+ console.log('\n💡 Next steps:');
1024
+ console.log(' 1. Restart OpenClaw');
1025
+ console.log(' 2. Try: "dooray 메일 확인해줘"');
1026
+ console.log(`\nSkill location: ${dooraySkillDir}`);
1027
+
1028
+ } catch (error) {
1029
+ console.error('❌ Installation failed:', error.message);
1030
+ console.log('\n💡 Manual installation:');
1031
+ console.log(` 1. Find your OpenClaw skills directory`);
1032
+ console.log(` 2. Create subdirectory: dooray`);
1033
+ console.log(` 3. Copy SKILL.md to: [skills]/dooray/SKILL.md`);
1034
+ process.exit(1);
1035
+ } finally {
1036
+ readline.close();
1037
+ }
1038
+ }
1039
+
834
1040
  // help: 도움말
835
1041
  function showHelp() {
836
1042
  console.log(`
@@ -881,7 +1087,10 @@ Commands:
881
1087
  Search before date
882
1088
  unread Show unread mail count
883
1089
  test Test IMAP/SMTP connection
884
- help Show this help message
1090
+ install-skill Install Dooray skill for OpenClaw
1091
+ version, -v, --version
1092
+ Show version number
1093
+ help, -h, --help Show this help message
885
1094
 
886
1095
  Examples:
887
1096
  dooray-cli config
@@ -910,6 +1119,8 @@ Examples:
910
1119
  dooray-cli search "report" --since "2026-01-01"
911
1120
  dooray-cli search "invoice" --before "2026-02-01"
912
1121
  dooray-cli unread
1122
+ dooray-cli install-skill
1123
+ dooray-cli --version
913
1124
 
914
1125
  Configuration file: ${CONFIG_PATH}
915
1126
  `);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "dooray-mail-cli",
3
- "version": "0.2.3",
3
+ "version": "0.2.4",
4
4
  "description": "Dooray mail CLI for OpenClaw Skill - IMAP/SMTP integration",
5
5
  "main": "./dist/mail-client.js",
6
6
  "bin": {