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.
- package/dooray-cli.js +214 -3
- 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
|
-
|
|
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
|
-
}
|
|
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
|
-
|
|
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
|
`);
|