1
0
mirror of https://shylinux.com/x/icebergs synced 2025-05-12 23:40:15 +08:00

Compare commits

..

891 Commits

Author SHA1 Message Date
shy
7d26b0afb0 add some 2025-05-12 11:10:51 +08:00
shy
1f9e8d756f add some 2025-05-04 08:48:56 +08:00
shy
705f3d074e add some 2025-05-02 01:36:47 +08:00
shy
b0c7feb56e add some 2025-04-25 18:23:55 +08:00
shy
7e5cff6b81 add some 2025-03-22 12:54:06 +08:00
shy
6c0e3a0a58 add some 2025-03-15 20:27:05 +08:00
shy
08f2f1626d add some 2025-03-10 18:38:39 +08:00
shy
5260027c9f add some 2025-03-08 08:38:13 +08:00
shy
26e62a1b22 add some 2025-03-05 23:33:47 +08:00
shy
e008f4d417 add some 2025-03-05 08:55:30 +08:00
shy
5fc5ccd0ea add some 2025-03-04 14:52:57 +08:00
shy
35c1407d29 add some 2025-03-03 22:13:05 +08:00
shy
55a0c3d120 add some 2025-03-03 18:39:51 +08:00
shy
968d9389c9 opt some 2025-03-02 22:10:17 +08:00
shy
7fea8e88a4 add some 2025-03-01 11:36:50 +08:00
shy
8fa2f6e8b3 add some 2025-02-28 14:17:28 +08:00
shy
fe1a6d30aa opt some 2025-02-27 17:56:24 +08:00
shy
02962f9d20 add some 2025-02-27 16:39:54 +08:00
shy
612ecdf4a6 add some 2025-02-27 16:29:06 +08:00
shy
c3f37f626b add some 2025-02-27 16:27:42 +08:00
shy
b4627b2975 add some 2025-02-26 21:51:32 +08:00
shy
f3bc5eb1e1 opt some 2025-02-25 21:57:33 +08:00
shy
03990b839e add some 2025-02-25 21:54:41 +08:00
shy
473826664a add some 2025-02-25 12:14:41 +08:00
root
be66627287 add some 2025-02-25 10:52:06 +08:00
shy
030c018877 add some 2025-02-25 09:59:30 +08:00
root
0071ba89d9 add some 2025-02-25 07:32:49 +08:00
shy
c067576dd6 add some 2025-02-23 09:58:37 +08:00
shy
96d812612b add some 2025-02-23 08:03:37 +08:00
root
a33bc88dcc add some 2025-02-19 21:00:50 +08:00
shy
2f715c5233 opt some 2025-02-18 11:26:19 +08:00
root
8a27ce7d66 add some 2025-02-18 11:18:22 +08:00
root
da81284b37 add some 2025-02-17 19:54:36 +08:00
root
bbb0ae9de9 add some 2025-02-16 08:44:53 +08:00
shy
7bb197ed94 add some 2025-02-16 08:27:23 +08:00
shy
bc94d8e1e4 add some 2025-02-15 18:35:15 +08:00
shy
942606d750 add some 2025-02-15 12:32:06 +08:00
shy
c418c8c070 add some 2025-02-13 22:35:33 +08:00
shy
87c96c880d opt some 2025-02-10 23:03:10 +08:00
shy
cdaa2d7984 opt some 2025-02-10 10:11:34 +08:00
root
38b7942c1b add some 2025-02-10 08:30:04 +08:00
root
240a0c88bf add some 2025-02-08 15:00:09 +08:00
root
297c299694 add some 2025-02-08 12:02:50 +08:00
root
324cd9dc57 add some 2025-02-06 16:21:11 +08:00
shy
1829822e43 add some 2025-02-05 17:37:25 +08:00
shy
a8b365dc31 add some 2025-02-05 09:49:32 +08:00
root
b64a3b5725 add some 2025-02-05 09:44:27 +08:00
root
0ef29edbad add some 2025-02-04 14:10:16 +08:00
shy
6fc5cbde02 add publish 2025-02-04 12:01:02 +08:00
shy
85e1f1dcb6 add some 2025-02-04 10:26:51 +08:00
root
cd5882b2ee add some 2025-02-04 08:52:06 +08:00
shy
259aa7639a add some 2025-02-03 20:42:02 +08:00
shy
91f4578d63 add some 2025-02-02 23:54:43 +08:00
root
54211e220d add some 2025-02-02 23:53:03 +08:00
shy
00d0a3f449 add some 2025-01-31 10:26:51 +08:00
root
8782b192e3 add some 2025-01-30 10:49:34 +08:00
root
92a2fcac3c add some 2025-01-29 12:00:59 +08:00
shy
c045033e55 add some 2025-01-25 15:15:48 +08:00
shy
c022852de3 add some 2025-01-23 21:36:46 +08:00
shy
fa73c5c940 add some 2025-01-23 18:59:31 +08:00
shy
0be5c0f6f3 add some 2025-01-22 16:23:02 +08:00
shy
524bbf6430 add some 2025-01-22 16:12:23 +08:00
root
50ba5c3a3f add some 2025-01-22 15:32:30 +08:00
shy
d9fcacd679 opt some 2025-01-17 21:18:36 +08:00
root
c661ed4f12 add some 2025-01-14 08:42:01 +08:00
root
193a2ab917 add some 2025-01-13 18:02:50 +08:00
shy
aa756c2bc3 add some 2025-01-12 21:53:42 +08:00
shy
7551a8dfab add some 2025-01-10 15:04:47 +08:00
shy
be8c60d97c add some 2025-01-06 21:38:46 +08:00
root
61b81cf089 add some 2025-01-05 20:36:15 +08:00
shy
813ec2b17a add some 2025-01-05 12:45:21 +08:00
shy
d4c73ce195 add some 2025-01-05 12:01:27 +08:00
shy
472f72889a add some 2025-01-03 12:36:17 +08:00
shy
a3e4861989 add some 2025-01-02 20:48:29 +08:00
root
18d65c81e5 add some 2025-01-02 20:42:58 +08:00
root
f59b7cc461 add some 2025-01-02 18:29:31 +08:00
shy
ec961b40fb add some 2025-01-01 09:49:06 +08:00
shy
a075aa7975 add some 2025-01-01 09:23:30 +08:00
root
287083f9ca add some 2024-12-31 19:22:00 +08:00
shy
2e0131a331 add some 2024-12-31 12:33:48 +08:00
root
7dcf68b0d8 add some 2024-12-16 16:02:46 +08:00
shy
66033654c5 add some 2024-12-08 22:27:31 +08:00
shy
6540f3f3f1 add some 2024-12-03 22:45:07 +08:00
shy
37fe3b44b0 add some 2024-11-28 12:32:02 +08:00
shy
bcdce97856 add some 2024-11-26 23:12:53 +08:00
shy
ff0590852d add some 2024-11-25 10:02:13 +08:00
shy
a352374bb4 add some 2024-11-24 07:46:53 +08:00
shy
d30b4e2034 add some 2024-11-23 16:51:24 +08:00
shy
131858f4b1 opt some 2024-11-23 10:11:56 +08:00
shy
e042dc832c add some 2024-11-20 22:49:56 +08:00
shy
8f10a46fb5 add some 2024-11-19 09:32:17 +08:00
root
313b7d4c95 add some 2024-11-18 09:11:37 +08:00
shy
f8af90a71e add some 2024-11-15 20:09:08 +08:00
root
52b47dee2a add some 2024-11-15 09:56:30 +08:00
root
5776c42f7b add some 2024-11-10 13:07:07 +08:00
root
73c32ccc9b add some 2024-11-09 11:35:33 +08:00
root
f9932b5dba add some 2024-11-04 10:27:19 +08:00
root
5afc3781a6 add some 2024-10-25 17:49:24 +08:00
root
dc242dfa54 add some 2024-10-22 07:35:48 +08:00
root
e02517a57e add some 2024-10-20 22:55:19 +08:00
root
f6a009c7fa add some 2024-10-20 08:16:21 +08:00
root
be0a295b52 add some 2024-10-18 14:45:24 +08:00
root
39a5ce360e add some 2024-10-18 14:08:56 +08:00
root
928666d2c9 add some 2024-10-17 23:45:20 +08:00
root
51ae44aeb3 add some 2024-10-17 12:13:39 +08:00
root
d3ba62cc61 add some 2024-10-17 09:38:54 +08:00
root
07111495dd add some 2024-10-16 11:18:41 +08:00
shy
e34752141a opt some 2024-10-16 10:27:26 +08:00
root
95b45c2f15 add some 2024-10-15 18:25:37 +08:00
root
b2b4616ec1 add some 2024-10-13 18:25:36 +08:00
root
1060a60a5e add some 2024-10-12 11:06:29 +08:00
shy
4d892e03d3 add some 2024-10-10 22:23:51 +08:00
shy
ca734d3baf add some 2024-10-09 14:41:19 +08:00
shy
2deff32468 add some 2024-10-06 22:19:03 +08:00
shy
ed39ff23e7 add some 2024-10-04 12:23:39 +08:00
shy
d4f4754be8 add some 2024-10-02 22:24:09 +08:00
shy
80807ed1d2 add some 2024-10-01 00:12:59 +08:00
shy
c4b9641a5e add some 2024-09-27 23:58:19 +08:00
shy
0bff96f485 add some 2024-09-25 17:16:22 +08:00
shy
7ab38ec81f add some 2024-09-24 13:10:56 +08:00
shy
56b87e9e78 add some 2024-09-20 20:53:41 +08:00
shy
f174577bde opt some 2024-09-19 21:09:34 +08:00
shy
ed65d194e6 add some 2024-09-18 20:40:55 +08:00
shy
15a79273ac add some 2024-09-18 13:32:50 +08:00
shy
0eac777f6f add some 2024-09-14 00:36:42 +08:00
shy
0f8a77af25 add some 2024-09-10 08:06:53 +08:00
shy
9a192b012f add some 2024-09-07 17:11:52 +08:00
shy
4b27054210 add some 2024-09-05 20:02:56 +08:00
shy
8d1374149c add some 2024-09-04 07:54:59 +08:00
shy
768bca93b1 add some 2024-09-03 22:42:25 +08:00
shy
f45d784af7 add some 2024-09-03 18:29:15 +08:00
shy
329f963a38 add some 2024-09-03 07:35:53 +08:00
shy
53c5a80da6 add some 2024-09-02 17:34:07 +08:00
shy
b1d5d09a80 add some 2024-08-30 21:56:33 +08:00
shy
4a5256c19f add some 2024-08-29 11:09:33 +08:00
shy
e3fb897137 add some 2024-08-26 22:15:14 +08:00
shy
b1bd23cc26 add some 2024-08-24 20:22:51 +08:00
shy
67b1e41db9 add some 2024-08-18 02:26:42 +08:00
shy
ce0735856e add some 2024-08-16 07:53:33 +08:00
jingganjiaoyu
a0ef75490c opt some 2024-08-15 11:48:38 +08:00
jingganjiaoyu
5891f4f621 opt some 2024-08-15 11:38:51 +08:00
shy
d4a5e4df44 add some 2024-08-12 21:06:51 +08:00
shy
25df349028 add some 2024-08-09 17:58:17 +08:00
shy
618218247b add some 2024-08-09 00:04:14 +08:00
shy
15a4603a18 add some 2024-08-06 19:10:22 +08:00
shy
2f33ff38de add some 2024-08-06 01:35:21 +08:00
shy
972c9fc97f opt some 2024-08-05 23:47:16 +08:00
shy
41cea7f8b0 add some 2024-08-05 23:20:52 +08:00
shy
5a4b79b4eb add some 2024-08-05 02:10:09 +08:00
shy
a7014de914 add some 2024-08-04 14:55:09 +08:00
shy
eb73841a72 add some 2024-08-04 01:49:24 +08:00
shy
704519e336 add some 2024-08-02 18:41:44 +08:00
shy
2f4e941aa0 add some 2024-07-31 22:20:28 +08:00
shy
e29a4fa6b8 add some 2024-07-29 22:49:54 +08:00
shy
af1a9be68e opt portal 2024-07-28 23:21:54 +08:00
shy
a5cd77e87d add some 2024-07-26 21:38:07 +08:00
shy
ccfffd917c opt some 2024-07-24 20:04:32 +08:00
shy
fb99d27694 add some 2024-07-23 23:42:35 +08:00
shy
805cfbcc25 add some 2024-07-23 16:04:42 +08:00
shy
170365ddab add some 2024-07-22 22:45:41 +08:00
shy
271e743c3c add some 2024-07-21 14:50:43 +08:00
shy
d401e8ec2c add some 2024-07-20 20:50:25 +08:00
shy
daa740ffbe add some 2024-07-20 11:05:14 +08:00
shy
9ba006a1da add some 2024-07-19 18:11:03 +08:00
shy
97bdf84965 add some 2024-07-19 00:07:21 +08:00
shy
555be526e3 add some 2024-07-16 22:24:39 +08:00
shy
06a89de015 add some 2024-07-16 19:50:08 +08:00
shy
2fe571f9d6 add some 2024-07-16 18:44:31 +08:00
shy
36f1fe2a7b add some 2024-07-16 10:54:32 +08:00
shy
7214a38d52 add some 2024-07-15 22:26:35 +08:00
shy
0f87c5ac5e add some 2024-07-15 17:55:57 +08:00
shy
8328b4cb69 add some 2024-07-15 09:36:47 +08:00
shy
0742533ce6 add some 2024-07-14 21:51:14 +08:00
shy
889f221e4b add some 2024-07-14 19:23:14 +08:00
shy
77a2cb1a43 add some 2024-07-12 21:05:19 +08:00
shy
6ff235f13a add some 2024-07-12 16:30:09 +08:00
shy
906183a522 opt some 2024-07-11 20:08:39 +08:00
shy
38d74bc01f add web.team.corporation 2024-07-11 01:54:19 +08:00
shy
7b21b28b98 add some 2024-07-09 19:49:29 +08:00
shy
d3001524f2 add some 2024-07-09 12:23:37 +08:00
shy
b9a8678410 opt some 2024-07-09 10:09:53 +08:00
shy
7b8e933bb9 add some 2024-07-09 09:56:18 +08:00
shy
3e63a8c243 opt some 2024-07-08 19:46:17 +08:00
shy
af0d446abc opt some 2024-07-08 19:45:05 +08:00
shy
01bacc73a2 add some 2024-07-07 18:24:15 +08:00
shy
9bf29af91f add some 2024-07-06 02:04:30 +08:00
shy
8b23ad92e0 add some 2024-07-05 20:51:24 +08:00
shy
cc0a5de7a0 add some 2024-07-04 19:34:59 +08:00
shy
eb69a26017 add some 2024-07-04 03:02:13 +08:00
shy
4dcb03c9dc add some 2024-07-03 19:24:34 +08:00
shy
e6c64b7e1f opt some 2024-07-03 14:31:53 +08:00
shy
27064b6aa9 opt some 2024-07-01 20:46:21 +08:00
shy
178a73ae4f add some 2024-07-01 20:42:27 +08:00
shy
c18f363085 opt some 2024-07-01 10:59:26 +08:00
shy
67b4924b9a add some 2024-07-01 10:40:13 +08:00
shy
cfd5db37ca add some 2024-06-30 19:52:35 +08:00
shy
dd974b0980 add some 2024-06-29 23:57:15 +08:00
shy
6f4d324808 add some 2024-06-28 19:35:26 +08:00
shy
96dd7e96de add some 2024-06-28 18:39:11 +08:00
shy
82c0c14dea add some 2024-06-20 20:49:29 +08:00
shy
1aa04477c4 add some 2024-06-20 17:18:16 +08:00
shy
7862121a3c opt some 2024-06-20 15:41:36 +08:00
shy
755aaf72b0 add some 2024-06-19 09:11:43 +08:00
shy
a77f9207c0 add some 2024-06-18 10:11:45 +08:00
shy
adea456e67 add aaa.asign 2024-06-17 18:27:14 +08:00
shy
d69b895983 opt some 2024-06-15 18:48:26 +08:00
shy
35c8a1ca44 add some 2024-06-15 18:45:56 +08:00
shy
0959289870 add some 2024-06-14 19:33:49 +08:00
shy
d264cd3261 add some 2024-06-13 07:33:58 +08:00
shy
558bf677da add some 2024-06-11 22:02:49 +08:00
shy
57035a9fa5 add some 2024-06-11 11:04:23 +08:00
shy
ee32bd8346 add some 2024-06-09 23:32:10 +08:00
shy
bc6e12a6f0 add some 2024-06-09 22:58:23 +08:00
shy
95ba9fc6cd add some 2024-06-09 20:04:31 +08:00
shy
96713c1e75 add some 2024-06-08 23:06:35 +08:00
shy
74075002f1 add some 2024-06-08 10:19:54 +08:00
shy
fda6e6f969 add some 2024-06-08 08:49:02 +08:00
shy
f30bdb9696 add some 2024-06-08 08:01:15 +08:00
shy
4d8a21fd54 add some 2024-06-08 07:56:24 +08:00
shy
c129026c52 opt some 2024-06-06 00:04:07 +08:00
shy
f8ca54a85e add some 2024-06-06 00:02:01 +08:00
shy
5c63a4b467 add some 2024-06-05 15:32:41 +08:00
shy
9d72dd7890 add some 2024-06-04 23:15:28 +08:00
shy
b5d6f7a94c opt some 2024-06-04 11:42:54 +08:00
shy
24e9a8682f add some 2024-06-03 18:36:07 +08:00
shy
0587d4dd75 add some 2024-06-01 23:04:39 +08:00
shy
019f536248 add some 2024-05-31 19:57:53 +08:00
shy
194fd6f5bc add some 2024-05-30 19:56:43 +08:00
shy
22ccf77a66 add some 2024-05-28 22:42:53 +08:00
shy
745ea23b48 add some 2024-05-28 18:48:36 +08:00
shy
4e03450ce2 add some 2024-05-28 07:31:20 +08:00
shy
13afc46682 add some 2024-05-27 19:32:12 +08:00
shy
d4f9ea0f81 add some 2024-05-27 07:29:32 +08:00
shy
3f945f963a add some 2024-05-26 11:27:48 +08:00
shy
120e65bb92 add some 2024-05-26 08:28:03 +08:00
shy
bfaf7380e1 add some 2024-05-26 08:07:13 +08:00
shy
bd7d558208 add some 2024-05-25 20:47:58 +08:00
shy
ac151623c1 add some 2024-05-25 19:56:50 +08:00
shy
9e1ff8d564 add some 2024-05-24 19:27:27 +08:00
shy
598942a836 add some 2024-05-23 23:41:23 +08:00
shy
7830bf0bf7 add some 2024-05-23 19:16:33 +08:00
shy
8021138a80 add some 2024-05-22 23:07:14 +08:00
shy
41c157c6ed add some 2024-05-22 18:44:30 +08:00
shy
c27d82e83e add some 2024-05-21 23:46:04 +08:00
shy
af91084d59 add some 2024-05-21 19:22:43 +08:00
shy
a27fd93686 add some 2024-05-21 07:39:24 +08:00
shy
f7b4edde23 add some 2024-05-20 20:52:40 +08:00
shy
0bfb8673a5 add some 2024-05-20 01:32:07 +08:00
shy
e6607bcd17 add some 2024-05-19 23:49:45 +08:00
shy
f64b141930 add some 2024-05-19 17:02:57 +08:00
shy
ac3241b168 add some 2024-05-18 21:02:28 +08:00
shy
1bc8a05ca6 add some 2024-05-17 19:39:37 +08:00
shy
272c91f469 add some 2024-05-16 08:19:24 +08:00
shy
f359c438fc add some 2024-05-15 18:40:26 +08:00
shy
82415d742a add some 2024-05-15 15:58:50 +08:00
shy
bfa6ecefb2 add some 2024-05-14 23:27:38 +08:00
shy
6b6e20458b add some 2024-05-14 19:13:36 +08:00
shy
b499d09f37 add some 2024-05-14 00:02:33 +08:00
shy
fd324e5f14 add tutor 2024-05-13 20:33:19 +08:00
shy
95ef705c49 add some 2024-05-13 08:08:28 +08:00
shy
12c66f89bb add some 2024-05-12 23:40:58 +08:00
shy
b31a5f8286 add some 2024-05-12 20:37:10 +08:00
shy
73ecfc0cb6 add some 2024-05-12 15:03:57 +08:00
shy
8b0e3ebe55 add some 2024-05-11 18:21:13 +08:00
shy
bcbfb9aaed add some 2024-05-10 08:04:23 +08:00
shy
b5d3ecf103 add some 2024-05-09 23:14:34 +08:00
shy
209d911e25 add some 2024-05-09 13:25:27 +08:00
shy
960748e223 opt some 2024-05-09 07:46:15 +08:00
shy
eac98f23f5 add some 2024-05-09 07:25:24 +08:00
shy
baca546e49 add some 2024-05-08 00:14:16 +08:00
shy
63cbd6d4c0 add some 2024-05-07 15:21:25 +08:00
shy
d8c381a933 add studio 2024-05-06 23:05:57 +08:00
shy
b8c8d1603e add some 2024-05-05 23:24:50 +08:00
shy
555b91fa8f add some 2024-05-05 17:32:25 +08:00
shy
d71d72aa19 add some 2024-05-04 19:20:32 +08:00
shy
bb99205fdb add some 2024-05-04 00:31:52 +08:00
shy
f7e3dcd9ff add some 2024-05-01 18:25:56 +08:00
shy
582519d290 add some 2024-04-30 22:11:58 +08:00
shy
e2babe49a6 add some 2024-04-30 02:35:03 +08:00
shy
172e734f76 add some 2024-04-29 14:49:00 +08:00
shy
d0de69d086 add some 2024-04-28 23:26:46 +08:00
shy
9ecfc80f03 add some 2024-04-27 21:40:39 +08:00
shy
c39b138277 add some 2024-04-27 20:43:12 +08:00
shy
ed06078ce4 opt some 2024-04-27 18:58:24 +08:00
shy
4dfe6269c5 add some 2024-04-27 18:35:13 +08:00
shy
183faff9ce add some 2024-04-27 09:20:51 +08:00
shy
9bdc7af5e9 add some 2024-04-25 21:11:19 +08:00
shy
90469e941d add some 2024-04-25 12:38:15 +08:00
shy
b98b3052d4 add some 2024-04-24 18:10:13 +08:00
shy
e220f82568 add some 2024-04-24 16:26:42 +08:00
shy
fe89d6346c add some 2024-04-24 10:23:18 +08:00
shy
f0ad76fe71 add some 2024-04-22 18:53:28 +08:00
shy
aec9fcf977 add some 2024-04-22 17:15:39 +08:00
eea57c28a4 opt some 2024-04-22 15:37:39 +08:00
shy
30c457bb07 add some 2024-04-22 15:27:41 +08:00
shy
94c2979c93 add some 2024-04-22 08:27:21 +08:00
f79d9b23d7 add windows 2024-04-22 00:36:57 +08:00
b3959aa68d opt some 2024-04-21 16:27:38 +08:00
shy
b980d48390 add some 2024-04-20 22:42:58 +08:00
shy
cfec29c68d add some 2024-04-20 21:57:46 +08:00
shy
a404a7cb08 add some 2024-04-20 19:26:26 +08:00
shy
cc820576f0 add some 2024-04-20 15:56:24 +08:00
shy
5d95320d1e add some 2024-04-20 07:25:48 +08:00
shy
56d4775fed add some 2024-04-19 19:35:46 +08:00
shy
60602bb7a9 add some 2024-04-19 17:58:11 +08:00
shy
43646c5e3e add some 2024-04-19 12:34:12 +08:00
shy
c04c3f0d1d add some 2024-04-18 23:52:02 +08:00
shy
03e18c9325 add some 2024-04-18 23:35:46 +08:00
shy
0c62da9a08 add some 2024-04-18 22:47:39 +08:00
shy
00362e1197 opt border 2024-04-18 22:15:24 +08:00
shy
eea21aaad8 opt some 2024-04-18 13:54:34 +08:00
shy
08b89ece9f add some 2024-04-18 13:40:45 +08:00
shy
41064a2809 add some 2024-04-18 10:51:38 +08:00
shy
86251fb5b3 add some 2024-04-18 10:48:38 +08:00
shy
b56063a183 add some 2024-04-18 00:10:56 +08:00
shy
65697070f4 opt some 2024-04-17 04:15:19 +08:00
shy
4b4179bd04 opt some 2024-04-16 08:21:24 +08:00
shy
158c738970 add some 2024-04-15 12:25:16 +08:00
shy
1564bb6899 add some 2024-04-15 09:08:39 +08:00
shy
3a2fd6d3bb add some 2024-04-14 23:26:13 +08:00
shy
aff83532dd add some 2024-04-14 19:26:34 +08:00
root
ec780aa64c add some 2024-04-14 16:57:47 +08:00
shy
8d3dbc1dea add some 2024-04-14 12:47:31 +08:00
root
77f10bbe69 add some 2024-04-13 23:18:15 +08:00
shy
0d0718e9e8 add some 2024-04-12 22:21:27 +08:00
shy
0338ef7b46 add some 2024-04-11 23:59:37 +08:00
root
74e72d76b9 add some 2024-04-11 21:58:09 +08:00
root
7de837851e add some 2024-04-11 17:08:19 +08:00
shy
25ac2e3a1b opt some 2024-04-11 12:38:38 +08:00
root
29d7a98ec6 add some 2024-04-10 22:58:38 +08:00
root
f802bda23a add some 2024-04-10 22:38:38 +08:00
shy
2075f6e227 add some 2024-04-10 13:33:14 +08:00
shy
144bacc365 add some 2024-04-10 00:32:48 +08:00
shy
3fee88f2bf add some 2024-04-09 18:25:08 +08:00
shy
74358ff30d add some 2024-04-09 13:19:07 +08:00
shy
7bf5ba9d8e opt some 2024-04-08 23:15:56 +08:00
shy
0d6db1c35e add some 2024-04-08 23:00:33 +08:00
shy
21df7f027d add some 2024-04-08 21:05:36 +08:00
shy
5f3e62cf71 add some 2024-04-08 13:31:10 +08:00
shy
4b09f92531 add some 2024-04-08 11:20:17 +08:00
shy
708ed30f74 add some 2024-04-08 00:04:10 +08:00
shy
d0710dc9e2 add some 2024-04-07 23:14:08 +08:00
shy
6154aa93aa add some 2024-04-07 15:33:13 +08:00
shy
bae35d2ce3 add some 2024-04-07 13:28:38 +08:00
shy
603c5ffb0c opt some 2024-04-07 12:20:00 +08:00
shy
1757e0e524 add some 2024-04-07 12:16:47 +08:00
shy
f310a782c4 opt some 2024-04-07 02:06:43 +08:00
shy
03f3d4d8c3 opt some 2024-04-07 01:39:03 +08:00
shy
feb337ba5b add some 2024-04-07 01:22:50 +08:00
shy
5bd4038d15 add some 2024-04-06 22:32:14 +08:00
shy
81f69d34f8 add some 2024-04-06 15:36:29 +08:00
shy
9a9e1b91fd add some 2024-04-06 15:05:27 +08:00
shy
ef7144c908 add some 2024-04-06 00:23:41 +08:00
shy
b00e5d8fb3 add some 2024-04-05 21:15:30 +08:00
shy
23abaae36b add some 2024-04-05 00:24:17 +08:00
shy
2c9cd04a41 add some 2024-04-04 23:11:40 +08:00
shy
da31659105 add some 2024-04-04 15:34:08 +08:00
shy
a840ff12ea add some 2024-04-04 13:49:03 +08:00
shy
e4d0d98702 add some 2024-04-03 14:15:30 +08:00
shy
fd319e30e4 add some 2024-04-03 02:55:42 +08:00
shy
045f57af43 add some 2024-04-03 01:19:04 +08:00
shy
4ea7d66862 opt some 2024-04-03 00:14:33 +08:00
shy
5735299596 add some 2024-04-02 21:49:19 +08:00
shy
b63cdf740c add some 2024-04-02 20:58:17 +08:00
shy
8caf4ece67 add some 2024-04-02 20:14:46 +08:00
shy
f31e56cb10 add some 2024-04-01 22:10:42 +08:00
shy
a42eb5ac4a add some 2024-04-01 20:08:39 +08:00
shy
0028f79073 add some 2024-03-31 04:43:58 +08:00
shy
9ed01c06a9 add some 2024-03-30 22:26:11 +08:00
shy
d477733e23 add some 2024-03-30 22:09:25 +08:00
shy
ae5db88909 add some 2024-03-30 18:08:35 +08:00
shy
34210fb807 add some 2024-03-29 22:32:01 +08:00
shy
38824867b5 add package 2024-03-28 23:45:02 +08:00
shy
36f92bd9a5 add some 2024-03-28 08:56:12 +08:00
shy
8ed6e6df65 add some 2024-03-27 22:19:09 +08:00
shy
1dc5dbf547 add some 2024-03-27 00:03:30 +08:00
shy
37b26a8bfc add some 2024-03-26 15:32:32 +08:00
shy
4f181981df add some 2024-03-25 22:08:33 +08:00
shy
b1ac4e9b38 add some 2024-03-25 12:39:40 +08:00
shy
a281411239 add some 2024-03-23 13:23:26 +08:00
shy
d3e0e06831 add some 2024-03-23 00:22:17 +08:00
shy
b71cf092a2 add some 2024-03-21 14:44:15 +08:00
shy
bacfa95eed add aliyun 2024-03-21 01:55:58 +08:00
shy
6fb1d394b2 add some 2024-03-20 14:19:54 +08:00
shy
96566bf29d add some 2024-03-20 13:18:55 +08:00
shy
46f57dbbb5 add some 2024-03-20 11:55:42 +08:00
shy
632cc3c276 add some 2024-03-19 23:43:15 +08:00
shy
3d9c99ae31 opt some 2024-03-19 22:22:42 +08:00
shy
e0ca977ba1 add some 2024-03-19 22:21:00 +08:00
shy
d2613f1c16 add some 2024-03-19 11:31:27 +08:00
shy
a874d3b0cc add some 2024-03-18 21:24:22 +08:00
shy
1abaf50c40 add some 2024-03-18 13:28:05 +08:00
shy
06eb4a2582 add some 2024-03-18 00:31:30 +08:00
shy
06f8f8ebe1 add some 2024-03-18 00:12:36 +08:00
shy
06314eb331 add some 2024-03-17 23:55:33 +08:00
shy
b3a5b1052b add some 2024-03-17 22:13:09 +08:00
shy
6cac11467e add some 2024-03-17 17:15:00 +08:00
shy
80aba21fcd add some 2024-03-17 15:40:18 +08:00
shy
ae3c7b2656 add some 2024-03-17 13:27:42 +08:00
shy
45f7f5bc8e add some 2024-03-17 12:28:02 +08:00
shy
3b2299b51f add some 2024-03-17 11:54:32 +08:00
shy
ee93cfe5f4 add some 2024-03-16 20:23:57 +08:00
shy
59159a897a opt some 2024-03-16 19:56:46 +08:00
shy
74b1019a1d add some 2024-03-16 16:20:17 +08:00
shy
832b58197a opt some 2024-03-16 15:25:43 +08:00
shy
f5cbe0739c add some 2024-03-16 14:26:26 +08:00
shy
5aff286771 add some 2024-03-16 12:38:41 +08:00
shy
0a98abcc5f add some 2024-03-15 22:37:20 +08:00
shy
5cfe19e5b2 add some 2024-03-15 21:58:15 +08:00
shy
e4102f6c60 add some 2024-03-15 14:41:08 +08:00
shy
ae10996a7b add some 2024-03-15 13:36:08 +08:00
shy
30ac9411bf add some 2024-03-15 12:31:53 +08:00
shy
640b26b2cc add some 2024-03-15 12:14:06 +08:00
shy
dabdc6e11e add some 2024-03-15 10:33:48 +08:00
shy
2498693ee7 opt some 2024-03-15 00:33:36 +08:00
shy
faa4dfb3cc add some 2024-03-15 00:07:19 +08:00
shy
bf91715f8f add some 2024-03-14 20:58:47 +08:00
shy
da8cc86e3a add some 2024-03-14 15:33:21 +08:00
shy
8d3cc5239e add some 2024-03-14 14:54:58 +08:00
shy
66a529cec0 add some 2024-03-14 14:06:42 +08:00
shy
420c3ed8aa add some 2024-03-14 12:48:14 +08:00
shy
ff4fc43c36 add some 2024-03-14 12:05:58 +08:00
shy
781db5caf2 add some 2024-03-14 00:51:15 +08:00
shy
e3bb0b774d add some 2024-03-13 20:35:39 +08:00
shy
ce5e499ce1 add some 2024-03-13 19:40:30 +08:00
shy
76a8c812b2 add some 2024-03-13 16:15:48 +08:00
shy
8f44941f25 opt some 2024-03-13 13:42:57 +08:00
shy
6ecf44962d add some 2024-03-13 11:56:11 +08:00
shy
4bdc6c8347 add some 2024-03-12 22:25:36 +08:00
shy
f40dfeda4d add some 2024-03-12 21:45:32 +08:00
shy
c2a1e36bda add some 2024-03-12 21:02:33 +08:00
shy
1542a364eb add some 2024-03-12 18:15:54 +08:00
shy
b420249a1e add some 2024-03-12 16:23:20 +08:00
shy
e821a8a104 add some 2024-03-12 13:39:48 +08:00
shy
bd3660f02e add some 2024-03-12 13:32:07 +08:00
shy
340c1f15e3 add some 2024-03-12 10:20:22 +08:00
shy
3ef850c581 add some 2024-03-12 09:52:02 +08:00
shy
0d84e0c9ad opt some 2024-03-11 23:32:05 +08:00
shy
082cf02461 add some 2024-03-11 18:41:37 +08:00
shy
290936eaff add some 2024-03-11 15:52:30 +08:00
shy
d8ad68c2ba add some 2024-03-11 15:12:36 +08:00
shy
a859e8f253 opt some 2024-03-11 13:10:01 +08:00
shy
c8e1644cd2 opt some 2024-03-11 13:00:30 +08:00
shy
aa531b17e2 add some 2024-03-10 19:48:51 +08:00
shy
5fce84de25 add some 2024-03-10 13:51:51 +08:00
shy
564d320c7e add some 2024-03-10 10:52:21 +08:00
shy
cae65f34e8 add some 2024-03-09 21:26:43 +08:00
shy
a446216c75 add some 2024-03-09 19:30:11 +08:00
shy
ca4e7aeb53 add some 2024-03-09 16:27:28 +08:00
shy
b91f83adb5 add some 2024-03-09 15:07:46 +08:00
shy
ec3a976337 add some 2024-03-09 12:23:58 +08:00
shy
0fa3965d6e add some 2024-03-09 09:43:33 +08:00
shy
abcddce974 add some 2024-03-08 23:48:50 +08:00
shy
939de032c1 add some 2024-03-08 21:39:48 +08:00
shy
84fe540a9a add some 2024-03-08 19:01:42 +08:00
shy
956f823558 add some 2024-03-08 11:37:42 +08:00
shy
253811a653 add some 2024-03-08 02:16:55 +08:00
shy
ee88456228 add ssh.cloud.tencent 2024-03-07 20:32:23 +08:00
shy
99c99955d5 add some 2024-03-07 10:39:34 +08:00
shy
4160041d01 add some 2024-03-07 08:19:36 +08:00
shy
f450f44088 add some 2024-03-07 00:03:49 +08:00
shy
a72045154d add some 2024-03-06 23:40:49 +08:00
shy
e6450ddc6c add some 2024-03-06 22:30:52 +08:00
shy
5676810436 add some 2024-03-06 19:48:07 +08:00
shy
0eaafa85ef add some 2024-03-06 19:46:44 +08:00
shy
661f77afc1 add some 2024-03-06 14:45:10 +08:00
shy
a8af5a6797 add some 2024-03-06 12:55:57 +08:00
shy
092a8533be add some 2024-03-06 12:43:07 +08:00
shy
53686b9c4b add some 2024-03-06 01:36:38 +08:00
shy
af80b9e2d4 add some 2024-03-05 22:47:43 +08:00
shy
3627f5f900 add some 2024-03-05 21:24:35 +08:00
shy
01f5f90c2a add some 2024-03-05 19:13:49 +08:00
shy
39518a878c opt some 2024-03-05 17:44:21 +08:00
shy
476880c344 opt some 2024-03-05 17:06:45 +08:00
shy
65dae15efb opt some 2024-03-05 17:00:34 +08:00
shy
e8c68bac4b add some 2024-03-05 16:49:47 +08:00
shy
6d2992cf0b add some 2024-03-05 14:14:31 +08:00
shy
4a777bc166 add some 2024-03-05 14:10:07 +08:00
shy
32ca5c81df opt portal 2024-03-05 13:59:02 +08:00
shy
45493499e9 opt portal 2024-03-05 13:55:23 +08:00
shy
21fdda3335 add some 2024-03-04 23:27:48 +08:00
shy
1f0f934ec0 add some 2024-03-04 19:16:39 +08:00
shy
437ec06692 add some 2024-03-04 16:51:39 +08:00
shy
2c791bef93 add some 2024-03-04 12:45:38 +08:00
shy
89f39ae9a4 add some 2024-03-04 10:48:23 +08:00
shy
1460608658 add some 2024-03-04 02:36:16 +08:00
shy
e8aa547c22 add some 2024-03-03 21:14:38 +08:00
shy
3d845cc0b7 add some 2024-03-03 17:17:41 +08:00
shy
d41585e91c add some 2024-03-03 14:26:42 +08:00
shy
338a0a08c0 add some 2024-03-02 23:42:00 +08:00
shy
57b5fdfed1 add some 2024-03-02 19:03:40 +08:00
shy
a12978d028 add some 2024-03-02 17:26:08 +08:00
shy
72bbad483a add some 2024-03-02 14:57:03 +08:00
shy
fbb1fe4413 add some 2024-03-01 21:21:58 +08:00
shy
7fbeb2c15c add some 2024-03-01 20:35:49 +08:00
shy
04a842a1c8 add some 2024-03-01 17:28:23 +08:00
shy
d3221f5453 add some 2024-03-01 16:30:35 +08:00
shy
b6bcf08176 add some 2024-03-01 15:18:32 +08:00
shy
fb516872e9 add some 2024-03-01 13:35:56 +08:00
shy
3a7b04f1d3 add some 2024-03-01 12:01:51 +08:00
shy
53c925d0cc add some 2024-02-29 23:49:03 +08:00
shy
d89e143cb8 add some 2024-02-29 20:14:28 +08:00
shy
d7116def5b add web.stream 2024-02-29 14:04:11 +08:00
shy
9bc165866f add some 2024-02-29 02:36:51 +08:00
shy
8a33ab3b09 add some 2024-02-29 00:29:17 +08:00
shy
432fecca49 add some 2024-02-28 23:29:38 +08:00
shy
76ea69c590 add some 2024-02-28 15:18:25 +08:00
shy
3e1d00f391 add some 2024-02-28 02:14:55 +08:00
shy
7f7a042951 add some 2024-02-27 22:02:19 +08:00
shy
0f5d9e6c8a add some 2024-02-27 17:02:32 +08:00
shy
ac54db626d add some 2024-02-27 13:43:54 +08:00
shy
b360e8a70a add some 2024-02-27 11:37:08 +08:00
shy
0fcf147873 add some 2024-02-27 01:41:29 +08:00
shy
b31c63989f add web.group 2024-02-27 00:58:58 +08:00
shy
6d13a280cd add some 2024-02-26 14:00:01 +08:00
shy
28792874d4 add some 2024-02-26 02:20:07 +08:00
shy
8abffce38c add some 2024-02-25 23:37:04 +08:00
shy
1cc9ad4108 add some 2024-02-25 22:45:51 +08:00
shy
8099e5893c add some 2024-02-25 20:35:00 +08:00
shy
644e80d040 add some 2024-02-25 17:56:11 +08:00
shy
437a01a4c9 add some 2024-02-25 13:22:28 +08:00
shy
ef50bef040 add some 2024-02-25 12:53:53 +08:00
shy
361f4ee8e9 add some 2024-02-25 12:14:26 +08:00
shy
f8880cdf4c add some 2024-02-25 01:28:35 +08:00
shy
2e7c086158 add some 2024-02-25 00:12:19 +08:00
shy
dec30e9ad7 add some 2024-02-24 23:28:03 +08:00
shy
47d01ecea9 add some 2024-02-24 20:39:38 +08:00
shy
a1c7c5307b add some 2024-02-24 18:37:33 +08:00
shy
c959706ba4 add some 2024-02-24 18:18:50 +08:00
shy
62fb71f333 opt some 2024-02-24 15:25:35 +08:00
shy
5fd5cbf774 add some 2024-02-24 14:39:10 +08:00
shy
8f916dca23 add some 2024-02-24 14:35:39 +08:00
shy
a1e8ce22c8 add some 2024-02-24 14:30:05 +08:00
shy
15e1ada00d add some 2024-02-24 13:39:29 +08:00
shy
70dfec6da6 add some 2024-02-24 12:32:41 +08:00
shy
a7ca869a16 add some 2024-02-24 00:32:05 +08:00
shy
ae57fc0271 add some 2024-02-23 23:46:59 +08:00
shy
f052dcf296 add some 2024-02-23 23:32:17 +08:00
shy
b5a2a234f2 add some 2024-02-23 23:05:25 +08:00
shy
8c8238ceb9 opt some 2024-02-23 22:43:20 +08:00
shy
880631418c add some 2024-02-23 19:02:57 +08:00
shy
fc61c4d320 add some 2024-02-23 10:22:09 +08:00
shy
deddfc9457 add some 2024-02-22 14:37:12 +08:00
shy
9568a8c215 add some 2024-02-22 13:37:08 +08:00
shy
8fe47b6ca7 add some 2024-02-22 13:27:49 +08:00
shy
5d386d63e2 add some 2024-02-22 11:27:13 +08:00
shy
94b2266982 add some 2024-02-22 11:16:55 +08:00
shy
377e165765 add some 2024-02-22 11:06:31 +08:00
shy
bfb9f99734 add some 2024-02-22 09:20:01 +08:00
shy
eb1e42295d add some 2024-02-22 08:16:23 +08:00
shy
48f2322d0c add some 2024-02-21 20:40:40 +08:00
shy
ef91a31480 add some 2024-02-21 14:16:22 +08:00
shy
88e3fef444 add some 2024-02-21 01:31:16 +08:00
shy
7831d5343e add some 2024-02-21 00:41:46 +08:00
shy
6b8e6e11f9 add some 2024-02-18 18:48:08 +08:00
shy
a63f5600b7 add some 2024-02-18 12:30:56 +08:00
shy
d33f38d7e7 opt process 2024-02-17 18:15:46 +08:00
shy
83dc4bc12b add some 2024-02-17 08:19:33 +08:00
shy
bb783b794a add some 2024-02-17 08:19:14 +08:00
shy
d1c31ad7a7 add some 2024-02-16 16:11:37 +08:00
shy
d62af7bc90 opt toast 2024-02-16 16:05:33 +08:00
shy
e98b9848fe add some 2024-02-16 00:28:53 +08:00
shy
a2ca5fbecb add some 2024-02-16 00:06:36 +08:00
shy
bb673d80d7 add some 2024-02-15 19:12:01 +08:00
shy
e00dd72ae4 add some 2024-02-15 17:12:42 +08:00
shy
42b45ba0b7 add some 2024-02-15 16:37:17 +08:00
shy
712fe28952 add toast hash 2024-02-15 15:57:53 +08:00
shy
586610ce64 add some 2024-02-15 00:59:21 +08:00
shy
4cc9da13c5 add some 2024-02-14 23:28:59 +08:00
shy
0fe6237649 opt some 2024-02-14 18:03:30 +08:00
shy
8b55171ae5 opt matrix 2024-02-14 17:59:27 +08:00
shy
1277c42256 add some 2024-02-13 21:21:56 +08:00
shy
22be04e823 add some 2024-02-13 19:32:44 +08:00
shy
be63e92893 opt matrix 2024-02-13 18:40:19 +08:00
shy
516f91c8c2 add matrix 2024-02-13 15:48:59 +08:00
shy
e5b1f1cc97 add matrix 2024-02-13 15:48:27 +08:00
shy
acb9cc0eb0 add island.matrix 2024-02-13 03:55:36 +08:00
shy
d98a322d05 add some 2024-02-12 13:16:04 +08:00
shy
30a7ce39b4 add some 2024-02-12 11:12:28 +08:00
shy
248258d71d add some 2024-02-11 22:56:07 +08:00
shy
ca6dc0f3c0 add some 2024-02-09 14:19:22 +08:00
shy
e2e73ba7b3 add some 2024-02-09 14:19:12 +08:00
shy
04ad921dd8 opt some 2024-02-09 11:30:20 +08:00
shy
29c1a023e3 opt traceid 2024-02-08 10:33:05 +08:00
shy
dc9dd86bba add some 2024-02-07 17:45:11 +08:00
shy
df88fbf2b8 add some 2024-02-06 23:33:32 +08:00
shy
96671f03c8 opt gdb 2024-02-06 23:25:14 +08:00
shy
a2a14be186 opt aaa 2024-02-06 17:56:17 +08:00
shy
d4c197c737 opt aaa.apply 2024-02-06 15:08:02 +08:00
shy
69c2d29df7 opt some 2024-02-05 23:03:50 +08:00
shy
ce833a87e3 opt some 2024-02-05 22:45:51 +08:00
shy
78afcfeb60 add some 2024-02-05 13:47:38 +08:00
shy
1b0d0db770 add some 2024-02-04 11:04:22 +08:00
shy
27d8cbad48 opt theme 2024-02-03 17:56:18 +08:00
shy
e1a891fdc0 add some 2024-02-02 22:26:57 +08:00
shy
df4575cf2e add some 2024-02-02 17:49:46 +08:00
shy
83fdeae371 add island 2024-02-02 17:29:56 +08:00
shy
f11eebe099 add some 2024-02-02 00:23:31 +08:00
shy
bd3deec2f9 add island.group 2024-02-02 00:05:53 +08:00
shy
931ff8c428 add some 2024-01-31 23:37:12 +08:00
shy
299f3ea184 add some 2024-01-31 15:16:32 +08:00
shy
6ea1bd5a9d opt process 2024-01-31 14:15:45 +08:00
shy
d7dc4693a2 add some 2024-01-31 09:54:08 +08:00
shy
3655662ad8 add some 2024-01-30 23:52:18 +08:00
shy
6a68dea00c opt some 2024-01-30 21:58:44 +08:00
shy
ae7afafe13 add some 2024-01-30 21:54:02 +08:00
shy
4b6531a015 add some 2024-01-30 19:23:15 +08:00
shy
4eea30cc6e add some 2024-01-30 18:32:47 +08:00
shy
33d6bcc013 add some 2024-01-30 15:07:38 +08:00
shy
4e12b37e33 add some 2024-01-30 13:51:12 +08:00
shy
1a75e9a77e opt count 2024-01-30 12:54:08 +08:00
shy
39908a29b1 add some 2024-01-29 22:33:10 +08:00
shy
ddf48abff8 add some 2024-01-29 22:06:52 +08:00
shy
c145f0cbc7 add some 2024-01-29 21:23:59 +08:00
shy
dc082e7dc5 add some 2024-01-29 20:48:24 +08:00
shy
1ca141e3dc add some 2024-01-29 15:54:26 +08:00
shy
727de55818 add some 2024-01-29 15:19:05 +08:00
shy
2f84ef4c0e opt some 2024-01-29 15:07:55 +08:00
shy
70e91d3822 add some 2024-01-29 10:56:54 +08:00
shy
729a502161 add some 2024-01-28 20:02:06 +08:00
shy
d8115cbf3b add some 2024-01-28 19:11:29 +08:00
shy
2ebabe38dd add some 2024-01-28 14:28:23 +08:00
shy
4b1a228078 opt some 2024-01-28 14:20:24 +08:00
shy
9dc442755d opt some 2024-01-28 13:57:50 +08:00
shy
4057e30de7 add some 2024-01-28 12:27:35 +08:00
shy
05a29fc32e add some 2024-01-28 12:27:29 +08:00
shy
c1b9b86330 add some 2024-01-27 22:38:10 +08:00
shy
56bfde1aa5 add some 2024-01-27 18:14:48 +08:00
shy
0eeb02aa8c add some 2024-01-27 17:35:20 +08:00
shy
20d31f9a14 add some 2024-01-27 17:35:16 +08:00
shy
c15bd851ec add some 2024-01-27 12:08:37 +08:00
shy
67733cbfd2 add some 2024-01-26 22:07:27 +08:00
shy
fa79259c14 add some 2024-01-26 21:41:51 +08:00
shy
9563612448 add some 2024-01-26 20:55:28 +08:00
shy
6249d2584f add some 2024-01-26 18:28:50 +08:00
shy
cf10a5cf36 add some 2024-01-26 17:16:39 +08:00
shy
0ce48b54f4 add some 2024-01-26 16:07:31 +08:00
shy
b54ba9a300 opt const 2024-01-26 10:19:05 +08:00
shy
59461dbba0 add some 2024-01-25 23:58:57 +08:00
shy
c6684e26f1 add some 2024-01-25 15:03:07 +08:00
shy
a4224e5178 add some 2024-01-25 15:03:02 +08:00
shy
5666ec8f1f add chat.message 2024-01-25 13:03:15 +08:00
shy
ac04d6abd3 add some 2024-01-25 00:01:19 +08:00
shy
93be363ce2 add some 2024-01-24 21:43:19 +08:00
shy
e668707738 add chat.message 2024-01-24 19:15:31 +08:00
shy
61b601c3c4 add some 2024-01-24 10:20:43 +08:00
shy
f462d5eca5 add some 2024-01-24 09:29:37 +08:00
shy
000804dd06 add some 2024-01-23 21:14:09 +08:00
shy
45e2bcfeb6 add some 2024-01-23 19:02:58 +08:00
shy
0fccf31d00 add some 2024-01-23 15:16:38 +08:00
shy
e1f72758df add web.store 2024-01-23 14:54:49 +08:00
shy
c56ca8d4e2 add web.store 2024-01-23 14:54:25 +08:00
shy
af481aec3b add script 2024-01-22 22:24:08 +08:00
shy
6023c1506d add some 2024-01-22 17:28:10 +08:00
shy
89518b3333 add some 2024-01-22 14:33:16 +08:00
shy
c869e1fed7 add some 2024-01-22 11:29:14 +08:00
shy
ec2c270301 add some 2024-01-22 11:03:51 +08:00
shy
2c5be00d12 add some 2024-01-21 23:08:11 +08:00
shy
f6d3c2821d add chat.script 2024-01-21 21:18:35 +08:00
shy
c6791d78dc add chat.script 2024-01-21 21:18:17 +08:00
shy
73731c898a add some 2024-01-21 17:02:00 +08:00
shy
2db2f39649 add chat.script 2024-01-21 16:00:59 +08:00
shy
5d8cfa9138 add chat.script 2024-01-21 10:08:12 +08:00
shy
aa9624d62e add some 2024-01-20 22:27:42 +08:00
shy
71f8117415 add ice.port 2024-01-20 22:01:21 +08:00
shy
df1fbade2f add some 2024-01-20 21:14:30 +08:00
shy
6e05c8243e add some 2024-01-20 19:21:10 +08:00
shy
ceb2758c3e add some 2024-01-20 15:03:04 +08:00
shy
e7d136268d add some 2024-01-20 13:50:40 +08:00
shy
a598a58a01 add some 2024-01-20 12:10:47 +08:00
shy
9628216d0f add some 2024-01-19 22:56:31 +08:00
shy
e09f0eb9d9 add some 2024-01-19 18:34:41 +08:00
shy
4f817911cc add some 2024-01-19 14:11:31 +08:00
shy
aea7a148bc add some 2024-01-18 22:10:40 +08:00
shy
82423b9112 add some 2024-01-18 10:21:33 +08:00
shy
01329fe476 add some 2024-01-18 00:11:52 +08:00
shy
53b6706863 add some 2024-01-17 22:46:59 +08:00
shy
ac90f10b41 add some 2024-01-17 19:30:28 +08:00
shy
5bc1e480fa add some 2024-01-17 14:57:18 +08:00
shy
3f8462301f add some 2024-01-17 14:35:19 +08:00
shy
826cd54b79 add some 2024-01-17 11:25:44 +08:00
shy
aeea2a4bad opt some 2024-01-16 22:09:32 +08:00
shy
e076a59eec add some 2024-01-16 18:27:34 +08:00
shy
6e1f498139 add some 2024-01-16 15:28:52 +08:00
shy
1b47f20dae add some 2024-01-16 15:28:44 +08:00
shy
8a36cbfe51 add some 2024-01-16 13:14:59 +08:00
shy
25016141bb add some 2024-01-15 19:11:57 +08:00
shy
a3328f8e83 opt token 2024-01-15 16:14:12 +08:00
shy
ef822f0c5b add some 2024-01-15 14:37:55 +08:00
shy
f22a74210e opt document 2024-01-15 12:19:48 +08:00
shy
70024b0baf opt binpack 2024-01-15 09:43:21 +08:00
shy
dbac8e1380 opt dream 2024-01-15 09:06:56 +08:00
shy
e89e120523 add some 2024-01-14 23:24:11 +08:00
shy
4d117d1bbf add some 2024-01-14 23:15:28 +08:00
shy
62d86ee286 add some 2024-01-14 22:59:20 +08:00
shy
b559e6c92b opt some 2024-01-14 20:21:17 +08:00
shy
be1bbfb2a4 add some 2024-01-14 20:18:38 +08:00
shy
c235a501b1 add spide token 2024-01-14 19:51:16 +08:00
shy
cbaebedd32 opt some 2024-01-14 16:42:21 +08:00
shy
06e16b0e5c add some 2024-01-14 16:15:49 +08:00
shy
e3f99c3042 add some 2024-01-14 16:09:42 +08:00
shy
8fb70fa41d add some 2024-01-14 13:11:19 +08:00
shy
e6e89563ef add some 2024-01-14 01:55:43 +08:00
shy
e67d59d310 opt island 2024-01-13 22:39:30 +08:00
shy
1f0a904767 opt island 2024-01-13 15:32:06 +08:00
shy
bbb4994422 add some 2024-01-13 08:47:16 +08:00
shy
f3612ef710 opt some 2024-01-12 23:53:07 +08:00
shy
4ba8bca6c9 opt island 2024-01-12 23:51:05 +08:00
shy
ef97bf61ca opt island 2024-01-12 23:37:26 +08:00
shy
a12a4836b9 opt some 2024-01-12 17:02:43 +08:00
shy
dc9f44f90e add mdb.DevDataAction 2024-01-12 00:40:54 +08:00
shy
7eb7d7b708 opt layout 2024-01-11 19:03:52 +08:00
shy
d5280d34c9 opt layout 2024-01-11 12:33:19 +08:00
shy
053d2e3bf9 opt layout 2024-01-11 00:07:21 +08:00
shy
9baed62ec9 add some 2024-01-10 21:06:41 +08:00
shy
cc503e37b9 add some 2024-01-10 14:41:14 +08:00
shy
fb3b822496 add some 2024-01-10 14:41:09 +08:00
shy
4d891fd380 add some 2024-01-10 13:31:33 +08:00
shy
3c9db97ffa add some 2024-01-10 13:31:25 +08:00
shy
e2acf4baf2 add some 2024-01-09 23:06:09 +08:00
shy
41ad9afa67 add some 2024-01-09 23:03:27 +08:00
shy
370420adff add some 2024-01-09 20:02:13 +08:00
shy
6e9b941c0b add some 2024-01-09 10:40:29 +08:00
shylinux
165b57f23a add some 2024-01-09 09:03:04 +08:00
shy
e0fec66989 add some 2024-01-08 21:47:46 +08:00
shy
216941a389 opt aaa.offer 2024-01-08 20:57:48 +08:00
shy
3d20218b47 add aaa.SendEmail 2024-01-08 13:18:21 +08:00
shy
830da6b46c add some 2024-01-08 11:13:36 +08:00
shy
fa158fa9ac opt some 2024-01-07 17:46:10 +08:00
shy
b0ac34c86b opt relay 2024-01-06 09:09:51 +08:00
shy
307c1edb5d opt some 2024-01-05 14:26:23 +08:00
shy
1f86d5716d fix ice.MSG_DAEMON 2024-01-05 13:02:15 +08:00
shy
97bcf318c6 opt ice.MSG_DAEMON 2024-01-05 12:25:56 +08:00
shy
0223a40087 add MergeLink 2024-01-04 17:33:30 +08:00
shy
8264f902b8 opt some 2024-01-04 12:51:33 +08:00
shy
a32a22b239 add some 2024-01-04 11:09:18 +08:00
shy
b7d3b9c976 opt dream 2024-01-04 10:50:10 +08:00
shy
480fe1d05d add some 2024-01-04 10:16:46 +08:00
shy
28d8c3a8e2 add some 2024-01-03 22:03:04 +08:00
shy
d400f80172 opt some 2024-01-03 20:15:07 +08:00
shy
9ba57a0b6d add some 2024-01-03 19:42:15 +08:00
shy
ec60322330 opt some 2024-01-03 16:59:57 +08:00
shy
d2e3cada57 opt role 2024-01-03 11:54:12 +08:00
shy
da2b486b7c add some 2024-01-02 21:32:56 +08:00
shylinux
d83dbb501e opt tcp.host 2024-01-02 21:03:25 +08:00
shy
89129568e2 add some 2024-01-02 20:33:32 +08:00
shy
4e2d515c9e fix yac.stack 2024-01-02 18:36:22 +08:00
shy
2727a198ae opt aaa.sesss 2024-01-02 17:37:00 +08:00
shy
85c44706ae opt aaa.sess 2024-01-02 16:15:32 +08:00
shy
8e49c83780 opt aaa.apply 2024-01-02 12:59:48 +08:00
shylinux@163.com
92e7416d82 opt aaa.apply 2024-01-02 12:20:58 +08:00
shy
08aa8cd8f6 add aaa.apply 2024-01-01 20:35:01 +08:00
shy
8b184981b6 opt git 2023-12-31 10:32:56 +08:00
shy
6bb29fed18 fix token 2023-12-30 21:11:51 +08:00
shy
80aa4ce207 opt git 2023-12-30 20:18:48 +08:00
shy
932002cf32 opt git 2023-12-30 20:17:56 +08:00
shy
693ee73a82 opt dream 2023-12-30 11:23:38 +08:00
shy
67a1ffd4b3 opt auto 2023-12-29 22:58:35 +08:00
shy
35e635b3a9 opt url 2023-12-29 17:58:55 +08:00
shylinux
f7bfc31de1 add some 2023-12-29 09:43:45 +08:00
shy
b3aaae590f add status.source 2023-12-28 23:15:59 +08:00
shy
c95da31e37 opt portal 2023-12-28 10:00:40 +08:00
shy
feb4d49d63 opt icon 2023-12-27 08:51:44 +08:00
shy
f315c7d0e7 opt icon 2023-12-26 18:34:47 +08:00
shy
e16c803d87 opt icon 2023-12-26 15:18:35 +08:00
shy
4fb198f2d5 opt desktop 2023-12-26 11:43:46 +08:00
shy
1810041116 opt some 2023-12-25 23:19:57 +08:00
shy
7e958b03fb opt some 2023-12-25 13:43:33 +08:00
shy
b122d1021c opt relay 2023-12-25 11:21:32 +08:00
shy
d60b1fc1a5 opt some 2023-12-25 10:28:18 +08:00
shy
2d1c99af56 add lock 2023-12-24 21:43:21 +08:00
shy
7bdc1bc380 add can.dir 2023-12-24 12:23:12 +08:00
shy
bdb7177091 opt status 2023-12-24 00:18:32 +08:00
shy
0ef623ae25 add git 2023-12-23 17:02:42 +08:00
shy
7c6cfde7ba add some 2023-12-23 16:59:18 +08:00
shy
ef18b21598 opt debug 2023-12-22 22:59:54 +08:00
shy
302a75485e opt debug 2023-12-22 17:49:00 +08:00
shy
7796bf4ce1 opt some 2023-12-21 19:21:24 +08:00
shy
33a62d7f2d add some 2023-12-21 18:54:17 +08:00
shy
563cbec926 add some 2023-12-21 18:37:47 +08:00
shy
e152063510 add some 2023-12-21 16:54:48 +08:00
shy
3d2e964267 add some 2023-12-21 15:54:31 +08:00
shy
3b5659f124 add some 2023-12-21 13:22:21 +08:00
shy
9d24461de8 opt space 2023-12-21 12:29:21 +08:00
shy
9a4e1a266a add some 2023-12-21 00:32:52 +08:00
shy
68dc8bc671 opt repos 2023-12-20 23:59:46 +08:00
shy
eed06ba25c add some 2023-12-20 15:04:32 +08:00
shy
9829b5c3ef add some 2023-12-20 13:53:56 +08:00
shy
038f419c8a add some 2023-12-20 13:48:53 +08:00
shy
ca501f7a12 add some 2023-12-19 19:06:59 +08:00
shy
c7e797e614 add some 2023-12-14 08:53:54 +08:00
shy
d3a7c38d5c add some 2023-12-14 08:53:47 +08:00
shy
c28a382295 opt icons 2023-12-13 19:10:28 +08:00
shy
7d28a1b93d add some 2023-12-13 17:57:44 +08:00
shy
6437fc6c05 add some 2023-12-13 13:27:59 +08:00
shy
e545b34306 add some 2023-12-13 12:40:01 +08:00
shy
f579ad868f add some 2023-12-13 12:23:07 +08:00
shy
4df3d2a5b4 add some 2023-12-13 09:49:12 +08:00
shy
c100727a95 add some 2023-12-13 00:00:27 +08:00
shy
37d2d84381 add some 2023-12-12 21:42:39 +08:00
shy
b54e6b0a01 fix dream.start 2023-12-12 15:59:22 +08:00
shy
0b042abfbe fix git.status 2023-12-12 15:47:14 +08:00
root
a4573dd54a fix sessauth 2023-12-12 12:39:06 +08:00
shy
3ce839ecc9 opt some 2023-12-12 11:32:37 +08:00
shy
4fd30e611d add web 2023-12-12 08:42:16 +08:00
shy
d94284c968 add some 2023-12-11 22:42:53 +08:00
shy
faefc3878b add some 2023-12-11 22:23:19 +08:00
shy
32e5ea4067 add web.count 2023-12-11 22:15:23 +08:00
shy
afdebbdc67 add some 2023-12-11 19:08:33 +08:00
shy
8684e804d3 add some 2023-12-11 16:40:44 +08:00
shy
149412b1a5 add admin 2023-12-11 15:59:30 +08:00
shy
e18395626a add checkbox 2023-12-11 15:38:23 +08:00
shy
93a9591cf7 opt some 2023-12-11 11:47:30 +08:00
shy
beea49d5dd add some 2023-12-10 23:56:55 +08:00
shy
251d28ccc6 fix language 2023-12-10 20:40:18 +08:00
shy
5051a7d2c1 opt ice.MSG_LANGUAGE 2023-12-10 14:59:44 +08:00
shy
aba012a20e opt wx 2023-12-10 09:51:02 +08:00
shy
8ff113403e add wx 2023-12-10 00:16:50 +08:00
shy
072996863d add wx.ide autogen 2023-12-09 18:03:57 +08:00
shy
e5e6f37e3e add wx.ide autogen 2023-12-09 18:03:47 +08:00
shy
ee1ef94a72 add some 2023-12-09 11:27:15 +08:00
shy
8d9b4c7840 add some 2023-12-09 10:33:16 +08:00
shy
b2e8e5b28f opt m.FormatMeta 2023-12-09 08:31:58 +08:00
shy
c434e334a9 opt web.stats 2023-12-08 19:37:25 +08:00
shy
2832fe1819 opt toast icon 2023-12-08 12:42:49 +08:00
shy
a69a06dc5e opt some 2023-12-08 11:59:58 +08:00
shy
d9574b3225 add usr/program/ 2023-12-07 22:47:42 +08:00
shy
f5a4bbfe54 opt some 2023-12-07 11:06:54 +08:00
shy
00c6e8e3e6 fix share 2023-12-07 08:57:23 +08:00
shy
9d96365c66 add some 2023-12-06 20:01:35 +08:00
shy
9e129db29d add relay.go 2023-12-06 13:55:56 +08:00
shy
5bf1c17cf0 add relay.go 2023-12-06 12:51:25 +08:00
shy
a16b7e9c3a add sleep 2023-12-05 23:17:43 +08:00
shy
8dc2aaa35b add some 2023-12-05 21:56:10 +08:00
shy
aad9c09e96 opt ssh/connect.go 2023-12-05 04:03:44 +08:00
shy
e1bb4568d9 opt header 2023-12-04 13:15:19 +08:00
shy
7d76a316b4 add some 2023-12-03 10:51:48 +08:00
shy
6166a5b0af add some 2023-12-02 18:14:56 +08:00
shy
d745552827 add some 2023-12-02 17:04:45 +08:00
shy
ec7f5eba8e add relay 2023-12-02 15:38:36 +08:00
shy
35007a3e6e add boot 2023-12-02 11:13:29 +08:00
shy
2939426a73 add some 2023-12-02 09:59:35 +08:00
shy
67cfeb5e04 add rc_local.sh 2023-12-01 23:32:57 +08:00
shy
37186f3cf4 add some 2023-12-01 14:06:58 +08:00
shy
591b405724 fix some 2023-12-01 12:37:11 +08:00
shy
37cab25dc0 opt mirrors.go 2023-12-01 12:05:26 +08:00
shy
3fef266c10 add some 2023-11-30 14:21:06 +08:00
shy
23c601d309 add some 2023-11-30 14:09:07 +08:00
shy
67fdb0479a add wx 2023-11-30 13:49:08 +08:00
shy
3a87341d26 add some 2023-11-30 13:14:36 +08:00
shy
9d3e1fa3fb opt wx.login 2023-11-30 00:39:05 +08:00
shy
3c63abbbe2 opt wx.ide 2023-11-29 16:10:44 +08:00
shy
a7cc74c80b add some 2023-11-27 13:24:39 +08:00
shy
a530f62cc0 add some 2023-11-27 13:18:52 +08:00
shy
4ba34ff106 add some 2023-11-27 10:57:14 +08:00
shy
5b102c5d63 add some 2023-11-27 00:06:51 +08:00
shy
df2958c76e add main.css 2023-11-26 21:08:51 +08:00
shy
ecbcde55b2 add some 2023-11-26 14:31:55 +08:00
shy
fca822c569 opt desktop 2023-11-26 13:43:07 +08:00
shy
592dff8a9e opt favor 2023-11-26 00:03:40 +08:00
shy
e63626b873 add some 2023-11-24 20:22:04 +08:00
shy
d2bb213a42 add some 2023-11-24 17:46:40 +08:00
shy
181b6b4650 add some 2023-11-23 23:25:09 +08:00
shy
7544359c5c opt theme 2023-11-23 23:02:14 +08:00
shy
74d74886f1 opt css size 2023-11-22 10:17:11 +08:00
shy
abf9afe3e8 add some 2023-11-22 00:03:33 +08:00
shy
e847189720 add some 2023-11-21 21:10:26 +08:00
shy
4679d5475a add mp 2023-11-21 15:53:05 +08:00
shy
593c5a3313 add wifi 2023-11-21 12:25:32 +08:00
shy
1d88096d83 add wx.ide 2023-11-20 22:33:27 +08:00
shy
3909630331 add some 2023-11-20 22:30:14 +08:00
shy
b1d36d832c add login.go 2023-11-19 23:21:44 +08:00
shy
002995b483 add wifi.go 2023-11-19 00:06:55 +08:00
shy
982250df4f add some 2023-11-18 18:58:59 +08:00
shy
832f5f0a43 add some 2023-11-18 16:25:25 +08:00
shy
f28d046358 add mp 2023-11-18 13:06:41 +08:00
shy
7b31a67335 add mp 2023-11-18 13:05:50 +08:00
shy
dcad30341b add mp 2023-11-18 00:04:56 +08:00
shy
61828d28f5 add some 2023-11-16 21:35:40 +08:00
shy
4d34d67ddd add some 2023-11-16 17:39:36 +08:00
shy
104c0752e3 add stats 2023-11-16 16:48:55 +08:00
shy
08befa2f96 add some 2023-11-16 13:53:29 +08:00
shy
15066a6706 add stats 2023-11-16 13:11:03 +08:00
shy
96553ee70c add asset 2023-11-16 00:27:12 +08:00
shy
ea3d45e77b add some 2023-11-15 14:35:54 +08:00
shy
493702da14 add some 2023-11-15 11:11:26 +08:00
shy
859ff766b4 add some 2023-11-14 08:46:23 +08:00
shy
0cf8512bb4 opt header 2023-11-12 10:54:01 +08:00
shy
3c680d6f88 add header 2023-11-12 08:30:11 +08:00
shy
f2c804167a add some 2023-11-11 19:54:03 +08:00
shy
57764d19ba add some 2023-11-11 18:22:39 +08:00
310 changed files with 11835 additions and 4479 deletions

View File

@ -1,6 +1,6 @@
MIT License MIT License
Copyright (c) 2020 shylinux Copyright (c) 2017-2025 shylinux
Permission is hereby granted, free of charge, to any person obtaining a copy Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal of this software and associated documentation files (the "Software"), to deal

View File

@ -1,3 +1,3 @@
# icebergs # icebergs
icebergs 是一个应用框架,通过群化、模块化、集自动化方式,在各种设备上,一键部署完整的个人云计算与云研发平台 icebergs 是一个后端框架,通过集群化、模块化、自动化方式,在各种设备上,即可一键启动完整的云计算服务与云研发环境

View File

@ -1,22 +1,16 @@
package aaa package aaa
import ( import ice "shylinux.com/x/icebergs"
ice "shylinux.com/x/icebergs"
"shylinux.com/x/icebergs/base/mdb"
)
const ( const (
RSA = "rsa" RSA = "rsa"
SIGN = "sign" SIGN = "sign"
CERT = "cert"
VERIFY = "verify" VERIFY = "verify"
BASE64 = "base64" BASE64 = "base64"
) )
const AAA = "aaa" const AAA = "aaa"
var Index = &ice.Context{Name: AAA, Help: "认证模块", Commands: ice.Commands{ var Index = &ice.Context{Name: AAA, Help: "认证模块"}
ice.CTX_INIT: {Hand: func(m *ice.Message, arg ...string) {
ice.Info.Load(m).Cmd(ROLE, ice.CTX_INIT).Cmd(ROLE, mdb.CREATE, TECH, VOID)
}},
}}
func init() { ice.Index.Register(Index, nil, OFFER, EMAIL, USER, TOTP, SESS, ROLE, RSA) } func init() { ice.Index.Register(Index, nil, APPLY, OFFER, EMAIL, USER, TOTP, SESS, ROLE, CERT, RSA) }

View File

@ -2,14 +2,17 @@ package aaa
import ( import (
"net/smtp" "net/smtp"
"strings"
"time" "time"
ice "shylinux.com/x/icebergs" ice "shylinux.com/x/icebergs"
"shylinux.com/x/icebergs/base/mdb" "shylinux.com/x/icebergs/base/mdb"
"shylinux.com/x/icebergs/base/web/html"
kit "shylinux.com/x/toolkits" kit "shylinux.com/x/toolkits"
) )
const ( const (
ADMIN = "admin"
SEND = "send" SEND = "send"
DATE = "date" DATE = "date"
FROM = "from" FROM = "from"
@ -24,32 +27,51 @@ func init() {
const ( const (
ADMIN = "admin" ADMIN = "admin"
SERVICE = "service" SERVICE = "service"
MAILBOX = "mailbox"
NL = "\r\n" NL = "\r\n"
DF = ": " DF = ": "
) )
Index.MergeCommands(ice.Commands{ Index.MergeCommands(ice.Commands{
EMAIL: {Help: "邮件", Actions: ice.MergeActions(ice.Actions{ EMAIL: {Help: "邮件", Actions: ice.MergeActions(ice.Actions{
mdb.CREATE: {Name: "create name*=admin service*='mail.shylinux.com:25' username*='shy@shylinux.com' password*"}, mdb.CREATE: {Name: "create name*=admin service*='smtp.163.com:25' username* password*"},
MAILBOX: {Help: "邮箱", Hand: func(m *ice.Message, arg ...string) { SEND: {Name: "send from=admin to*='shy@shylinux.com' cc subject*=hi content*:textarea=hello", Help: "发送", Icon: "bi bi-send-plus", Hand: func(m *ice.Message, arg ...string) {
if p := mdb.Config(m, MAILBOX); !m.Warn(p == "", ice.ErrNotValid, MAILBOX) { msg := mdb.HashSelects(m.Spawn(), m.OptionDefault(FROM, ADMIN))
m.EchoIFrame(p).ProcessInner() if m.WarnNotFound(msg.Append(SERVICE) == "", m.Option(FROM)) {
}
}},
SEND: {Name: "send to*='shy@shylinux.com' cc subject*=hi content*:textarea=hello", Help: "发送", Hand: func(m *ice.Message, arg ...string) {
msg := mdb.HashSelect(m.Spawn(), m.OptionDefault(mdb.NAME, ADMIN))
if m.Warn(msg.Append(SERVICE) == "", ice.ErrNotValid, SERVICE) {
return return
} }
m.Toast(ice.PROCESS, "", "-1") m.ToastProcess()
defer m.Toast(ice.SUCCESS) content := []byte(kit.JoinKV(DF, NL, kit.Simple(FROM, msg.Append(USERNAME), m.OptionSimple(TO, CC, SUBJECT), DATE, time.Now().Format(time.RFC1123Z), html.ContentType, "text/html; charset=UTF-8")...) + NL + NL + m.Option(CONTENT))
content := []byte(kit.JoinKV(DF, NL, kit.Simple(FROM, msg.Append(USERNAME), m.OptionSimple(TO, CC, SUBJECT), DATE, time.Now().Format(time.RFC1123Z), "Content-Type", "text/html; charset=UTF-8")...) + NL + NL + m.Option(CONTENT))
auth := smtp.PlainAuth("", msg.Append(USERNAME), msg.Append(PASSWORD), kit.Split(msg.Append(SERVICE), ice.DF)[0]) auth := smtp.PlainAuth("", msg.Append(USERNAME), msg.Append(PASSWORD), kit.Split(msg.Append(SERVICE), ice.DF)[0])
m.Logs(EMAIL, SEND, string(content)).Warn(smtp.SendMail(msg.Append(SERVICE), auth, msg.Append(USERNAME), kit.Split(m.Option(TO)), content)) m.Logs(EMAIL, SEND, string(content))
if !m.WarnNotValid(smtp.SendMail(msg.Append(SERVICE), auth, msg.Append(USERNAME), kit.Split(m.Option(TO)), content)) {
m.ToastSuccess()
}
}}, }},
LOGIN: {Hand: func(m *ice.Message, arg ...string) { }, mdb.DevDataAction("name,service,username,password"), mdb.HashAction(mdb.SHORT, mdb.NAME, mdb.FIELD, "time,name,service,username", ice.ACTION, SEND)), Hand: func(m *ice.Message, arg ...string) {
m.Echo("input email: ") if mdb.HashSelect(m, arg...); len(arg) == 0 && m.Length() == 0 {
}}, m.EchoInfoButton(m.Trans("please add admin email", "请配置管理员邮箱"), mdb.CREATE, mdb.DEV_REQUEST)
}, RoleAction(LOGIN), mdb.HashAction(mdb.SHORT, mdb.NAME, mdb.FIELD, "time,name,service,username", ice.ACTION, SEND))}, } else if len(arg) == 0 {
m.Action(mdb.CREATE, mdb.DEV_REQUEST)
}
}},
})
ice.Info.Inputs = append(ice.Info.Inputs, func(m *ice.Message, arg ...string) {
switch kit.TrimPrefix(arg[0], "extra.") {
case TO:
if m.Option(ice.ACTION) != EMAIL {
break
}
fallthrough
case EMAIL:
m.Push(arg[0], "shy@shylinux.com", "shylinux@163.com")
case PASSWORD:
m.SetAppend()
}
}) })
} }
func SendEmail(m *ice.Message, from, to, cc string, arg ...string) {
m.Option(ice.MSG_USERHOST, strings.Split(m.Option(ice.MSG_USERHOST), "://")[1])
m.Cmdy(EMAIL, SEND, kit.Select(mdb.Config(m, EMAIL), from), kit.Select(m.Option(EMAIL), to), cc,
strings.TrimSpace(kit.Select(ice.Render(m, ice.RENDER_TEMPLATE, SUBJECT_HTML), arg, 0)),
kit.Select(ice.Render(m, ice.RENDER_TEMPLATE, CONTENT_HTML), arg, 1),
)
}

View File

@ -1,41 +1,71 @@
package aaa package aaa
import ( import (
"strings"
ice "shylinux.com/x/icebergs" ice "shylinux.com/x/icebergs"
"shylinux.com/x/icebergs/base/gdb"
"shylinux.com/x/icebergs/base/mdb" "shylinux.com/x/icebergs/base/mdb"
"shylinux.com/x/icebergs/base/web/html"
kit "shylinux.com/x/toolkits" kit "shylinux.com/x/toolkits"
) )
func _offer_create(m *ice.Message, arg ...string) {
h := mdb.HashCreate(m.Spawn(), FROM, m.Option(ice.MSG_USERNAME), mdb.STATUS, INVITE, m.OptionSimple(EMAIL, SUBJECT, CONTENT))
SendEmail(m.Options("link", m.Cmdx("host", "publish", m.MergePodCmd("", "", mdb.HASH, h))), m.Option(FROM), "", "")
gdb.Event(m, OFFER_CREATE, mdb.HASH, h, EMAIL, m.Option(EMAIL))
}
func _offer_accept(m *ice.Message, arg ...string) {
msg := mdb.HashSelect(m.Spawn(), m.Option(mdb.HASH))
if ls := kit.Split(msg.Append(EMAIL), mdb.AT); !m.WarnNotFound(msg.Length() == 0 || len(ls) < 2, m.Option(mdb.HASH)) {
m.Spawn().AdminCmd(USER, mdb.CREATE, USERROLE, VOID, USERNAME, msg.Append(EMAIL), USERNICK, ls[0], USERZONE, ls[1])
mdb.HashModify(m, m.OptionSimple(mdb.HASH), mdb.STATUS, ACCEPT)
gdb.Event(m, OFFER_ACCEPT, mdb.HASH, m.Option(mdb.HASH), EMAIL, msg.Append(EMAIL))
m.ProcessLocation(m.MergePod("", ice.MSG_SESSID, SessValid(m.Options(ice.MSG_USERNAME, msg.Append(EMAIL)))))
}
}
const ( const (
INVITE = "invite" INVITE = "invite"
ACCEPT = "accept" ACCEPT = "accept"
SUBJECT_HTML = "subject.html"
CONTENT_HTML = "content.html"
OFFER_CREATE = "offer.create"
OFFER_ACCEPT = "offer.accept"
) )
const APPLY = "apply"
const OFFER = "offer" const OFFER = "offer"
func init() { func init() {
Index.MergeCommands(ice.Commands{ Index.MergeCommands(ice.Commands{
OFFER: {Help: "邀请", Actions: ice.MergeActions(ice.Actions{ OFFER: {Help: "邀请", Role: VOID, Meta: kit.Dict(
mdb.CREATE: {Name: "create email*='shy@shylinux.com' subject content", Help: "邀请", Hand: func(m *ice.Message, arg ...string) { ice.CTX_TRANS, kit.Dict(html.INPUT, kit.Dict("from", "发自")),
h := mdb.HashCreate(m.Spawn(), m.OptionSimple(EMAIL, SUBJECT, CONTENT), INVITE, m.Option(ice.MSG_USERNAME), mdb.STATUS, INVITE) ), Actions: ice.MergeActions(ice.Actions{
m.Cmd(EMAIL, SEND, m.Option(EMAIL), "", m.OptionDefault(SUBJECT, "welcome to contexts, please continue"), mdb.CREATE: {Name: "create from*=admin email*='shy@shylinux.com' subject content", Help: "邀请", Hand: func(m *ice.Message, arg ...string) {
m.OptionDefault(CONTENT, ice.Render(m, ice.RENDER_ANCHOR, m.Cmdx("host", "publish", m.MergePodCmd("", "", mdb.HASH, h)))), _offer_create(m, arg...)
)
}}, }},
ACCEPT: {Help: "接受", Hand: func(m *ice.Message, arg ...string) { ACCEPT: {Help: "接受", Role: VOID, Hand: func(m *ice.Message, arg ...string) {
if m.Warn(m.Option(mdb.HASH) == "", ice.ErrNotValid, mdb.HASH) { if !m.WarnNotValid(m.Option(mdb.HASH), mdb.HASH) {
return _offer_accept(m, arg...)
}
msg := m.Cmd("", m.Option(mdb.HASH))
if ls := kit.Split(msg.Append(EMAIL), mdb.AT); !m.Warn(msg.Length() == 0 || len(ls) < 2, ice.ErrNotValid, m.Option(mdb.HASH)) {
m.Cmd(USER, mdb.CREATE, USERNICK, ls[0], USERNAME, msg.Append(EMAIL), USERZONE, ls[1])
m.ProcessOpen(kit.MergeURL2(m.Option(ice.MSG_USERWEB), ice.PS, ice.MSG_SESSID, SessCreate(m, msg.Append(EMAIL)), mdb.HASH, ""))
mdb.HashModify(m, m.OptionSimple(mdb.HASH), mdb.STATUS, ACCEPT)
} }
}}, }},
}, RoleAction(ACCEPT), mdb.ImportantHashAction(mdb.SHORT, mdb.UNIQ, mdb.FIELD, "time,hash,status,invite,email,title,content")), Hand: func(m *ice.Message, arg ...string) { }, mdb.ImportantHashAction(
if !m.Warn(len(arg) == 0 && m.Option(ice.MSG_USERROLE) == VOID, ice.ErrNotRight) { mdb.SHORT, mdb.UNIQ, mdb.FIELD, "time,hash,from,status,email,subject,content"), EMAIL, ADMIN,
kit.If(mdb.HashSelect(m, arg...).FieldsIsDetail(), func() { m.PushAction(ACCEPT) }) ), Hand: func(m *ice.Message, arg ...string) {
if m.WarnNotRight(len(arg) == 0 && !IsTechOrRoot(m)) {
return
} else if mdb.HashSelect(m, arg...).FieldsIsDetail() {
if m.Option(ice.MSG_USERNAME) == "" {
m.Option(ice.MSG_USERHOST, strings.Split(m.Option(ice.MSG_USERHOST), "://")[1])
m.SetAppend().EchoInfoButton(m.Template(SUBJECT_HTML), ACCEPT)
} else if strings.Contains(m.Option(ice.MSG_USERWEB), "/c/offer") {
m.ProcessLocation(m.MergePod(""))
}
} }
}}, }},
}) })
} }
func OfferAction() ice.Actions {
return gdb.EventsAction(OFFER_CREATE, OFFER_ACCEPT, USER_CREATE, USER_REMOVE)
}

124
base/aaa/portal/apply.go Normal file
View File

@ -0,0 +1,124 @@
package portal
import (
"shylinux.com/x/ice"
"shylinux.com/x/icebergs/base/aaa"
"shylinux.com/x/icebergs/base/cli"
"shylinux.com/x/icebergs/base/ctx"
"shylinux.com/x/icebergs/base/mdb"
"shylinux.com/x/icebergs/base/nfs"
"shylinux.com/x/icebergs/base/web"
kit "shylinux.com/x/toolkits"
)
type apply struct {
ice.Hash
email string `data:"admin"`
checkbox string `data:"true"`
online string `data:"true"`
field string `data:"time,hash,status,email,userrole,username,usernick,icons,agent,system,ip,ua"`
apply string `name:"apply" help:"申请" role:"void"`
agree string `name:"agree userrole=tech,void" help:"同意" icon:"bi bi-check2-square"`
login string `name:"login" help:"登录" role:"void"`
list string `name:"list hash auto sso" help:"注册"`
}
func (s apply) Sso(m *ice.Message, arg ...string) {
m.AddHeaderLogin(cli.QRCODE, cli.QRCODE, "扫码登录", "10")
m.AddHeaderLogin(mdb.PLUGIN, aaa.EMAIL, "邮箱登录", "20", ctx.INDEX, m.ShortKey(), ctx.ARGS, kit.FuncName(s.Login))
m.AddHeaderLogin(mdb.PLUGIN, aaa.APPLY, "注册用户", "30", ctx.INDEX, m.ShortKey(), ctx.ARGS, kit.FuncName(s.Apply))
}
func (s apply) Apply(m *ice.Message, arg ...string) {
if m.IsGetMethod() {
if k := _cookie_key(m); m.Option(k) == "" || s.List(m, m.Option(k)).Length() == 0 && m.Result() == "" {
m.DisplayForm(m, "email*", aaa.USERNICK, s.Apply)
}
} else if !m.WarnAlreadyExists(m.Options(arg).Cmd(aaa.USER, m.Option(aaa.EMAIL)).Length() > 0, m.Option(aaa.EMAIL)) {
m.Options(ice.MSG_USERNAME, m.Option(aaa.EMAIL), ice.MSG_USERNICK, kit.Split(m.Option(aaa.EMAIL), "@")[0])
h := s.Hash.Create(m, kit.Simple(arg, mdb.STATUS, kit.FuncName(s.Apply), web.ParseUA(m.Message))...)
m.ProcessCookie(_cookie_key(m), h)
m.StreamPushRefreshConfirm()
m.ChatMessageInsertPlug(aaa.APPLY, "user.signup", "", m.PrefixKey(), h)
}
}
func (s apply) Agree(m *ice.Message, arg ...string) {
if m.WarnNotValid(m.Option(mdb.HASH) == "", mdb.HASH) {
return
}
msg := s.Hash.List(m.Spawn(), m.Option(mdb.HASH))
if m.WarnNotFound(msg.Length() == 0, m.Option(mdb.HASH)) {
return
}
s.Hash.Modify(m, kit.Simple(m.OptionSimple(mdb.HASH, aaa.USERROLE), mdb.STATUS, s.Agree)...)
// m.UserCreate(m.Option(aaa.USERROLE), msg.Append(aaa.USERNAME), msg.Append(aaa.USERNICK))
m.PushRefresh(msg.Append(cli.DAEMON))
}
func (s apply) Login(m *ice.Message, arg ...string) {
kit.If(m.Option(mdb.HASH) == kit.FuncName(s.Apply), func() { m.Options(mdb.HASH, "") })
if m.IsGetMethod() {
m.DisplayForm("email*", s.Login)
} else if m.Options(arg).Option(aaa.EMAIL) == "" {
if m.WarnNotValid(m.OptionDefault(mdb.HASH, m.Option(_cookie_key(m))) == "", mdb.HASH) {
m.ProcessCookie(_cookie_key(m), "")
return
}
msg := s.Hash.List(m.Spawn(), m.Option(mdb.HASH))
if m.WarnNotFound(msg.Length() == 0, m.Option(mdb.HASH)) {
m.ProcessCookie(_cookie_key(m), "")
return
}
m.UserCreate(m.Option(aaa.USERROLE), msg.Append(aaa.USERNAME), msg.Append(aaa.USERNICK))
web.RenderCookie(m.Message, m.Cmdx(aaa.SESS, mdb.CREATE, msg.Append(aaa.USERNAME)))
s.Hash.Modify(m, kit.Simple(m.OptionSimple(mdb.HASH), mdb.STATUS, s.Login)...)
m.ProcessLocation(nfs.PS)
m.StreamPushRefreshConfirm()
} else {
if m.WarnNotFound(m.Cmd(aaa.USER, m.Option(aaa.EMAIL)).Length() == 0, m.Option(aaa.EMAIL)) {
return
}
m.Options(ice.MSG_USERNAME, m.Option(aaa.EMAIL))
space := kit.Keys(kit.Slice(kit.Split(m.Option(ice.MSG_DAEMON), nfs.PT), 0, -1))
share := m.Cmd(web.SHARE, mdb.CREATE, mdb.TYPE, web.FIELD, mdb.NAME, web.CHAT_GRANT, mdb.TEXT, space, web.SPACE, ice.OPS).Append(mdb.LINK)
m.Options(web.LINK, share).SendEmail("", "", "")
// m.ProcessHold(m.Trans("please auth login in mailbox", "请注意查收邮件"))
m.Echo(m.Trans("please auth login in mailbox", "请注意查收邮件"))
m.ProcessInner()
}
}
func (s apply) List(m *ice.Message, arg ...string) *ice.Message {
kit.If(m.Option(_cookie_key(m)), func(p string) { arg = []string{p} })
kit.If(!m.IsTech(), func() { m.Option(ice.MSG_ONLINE, ice.FALSE) })
if m.IsTech() || (len(arg) > 0 && arg[0] != "") {
s.Hash.List(m, arg...).Table(func(value ice.Maps) {
switch value[mdb.STATUS] {
case kit.FuncName(s.Apply):
m.PushButton(s.Agree, s.Remove)
case kit.FuncName(s.Agree):
m.PushButton(s.Login, s.Remove)
default:
m.PushButton(s.Remove)
}
})
}
if m.Option(_cookie_key(m)) != "" || m.ActionKey() != "" {
switch m.Append(mdb.STATUS) {
case kit.FuncName(s.Login):
if m.ActionKey() == kit.FuncName(s.Apply) {
m.ProcessCookie(_cookie_key(m), "")
} else {
m.SetAppend().ProcessLocation(nfs.PS)
}
case kit.FuncName(s.Agree):
m.SetAppend().EchoInfoButton(m.Trans("please login", "请登录"), s.Login)
case kit.FuncName(s.Apply):
m.SetAppend().EchoInfoButton(m.Trans("please wait admin agree", "请等待管理员同意"), nil)
}
} else if len(arg) == 0 {
m.EchoQRCode(m.MergePodCmd("", "", ctx.ACTION, s.Apply))
}
return m
}
func init() { ice.Cmd("aaa.apply", apply{}) }
func _cookie_key(m *ice.Message) string { return kit.Keys(m.PrefixKey(), mdb.HASH) }

77
base/aaa/portal/asign.go Normal file
View File

@ -0,0 +1,77 @@
package portal
import (
"shylinux.com/x/ice"
"shylinux.com/x/icebergs/base/aaa"
"shylinux.com/x/icebergs/base/ctx"
"shylinux.com/x/icebergs/base/mdb"
kit "shylinux.com/x/toolkits"
)
type asign struct {
ice.Hash
export string `data:"true"`
short string `data:"role"`
field string `data:"time,role"`
shorts string `data:"index"`
fields string `data:"time,index,operate"`
insert string `name:"insert index"`
deploy string `name:"deploy" help:"部署"`
list string `name:"list role auto" help:"分配"`
confer string `name:"confer username" help:"授权"`
}
func (s asign) Inputs(m *ice.Message, arg ...string) {
if arg[0] == "operate" {
m.Search(m.Option(ctx.INDEX), func(key string, cmd *ice.Command) {
for sub, action := range cmd.Actions {
if kit.HasPrefix(sub, "_", "/") {
continue
}
m.Push(arg[0], sub)
m.Push(mdb.NAME, action.Name)
m.Push(mdb.HELP, action.Help)
}
m.Sort(arg[0])
m.Option(ice.TABLE_CHECKBOX, ice.TRUE)
})
} else if arg[0] == aaa.USERNAME {
m.Cmdy(aaa.USER).Cut(aaa.USERNAME, aaa.USERNICK, aaa.USERROLE)
} else {
s.Hash.Inputs(m, arg...)
}
}
func (s asign) Modify(m *ice.Message, arg ...string) {
if m.Option(ctx.INDEX) != "" {
s.Update(m, arg...)
} else {
s.Modify(m, arg...)
}
}
func (s asign) Deploy(m *ice.Message, arg ...string) {
defer m.ToastProcess()()
s.List(m.Spawn()).Table(func(val ice.Maps) {
m.Cmd(aaa.ROLE, mdb.REMOVE, val[aaa.ROLE])
m.Cmd(aaa.ROLE, mdb.CREATE, val[aaa.ROLE])
s.List(m.Spawn(), val[aaa.ROLE]).Table(func(value ice.Maps) {
m.Cmd(aaa.ROLE, aaa.WHITE, val[aaa.ROLE], value[ctx.INDEX])
m.Cmd(aaa.ROLE, aaa.BLACK, val[aaa.ROLE], value[ctx.INDEX], ctx.ACTION)
kit.For(kit.Split(value["operate"]), func(p string) {
m.Cmd(aaa.ROLE, aaa.WHITE, val[aaa.ROLE], value[ctx.INDEX], ctx.ACTION, p)
})
})
})
}
func (s asign) List(m *ice.Message, arg ...string) *ice.Message {
if len(arg) == 0 {
s.Hash.List(m, arg...).Action(s.Create, s.Deploy).PushAction(s.Confer, s.Remove)
} else {
s.Hash.SubList(m, arg[0], arg[1:]...).Action(s.Insert, s.Deploy).PushAction(s.Delete)
}
return m
}
func (s asign) Confer(m *ice.Message, arg ...string) {
m.Cmd(aaa.USER, mdb.MODIFY, aaa.USERNAME, m.Option(aaa.USERNAME), aaa.USERROLE, m.Option(aaa.ROLE))
}
func init() { ice.Cmd("aaa.asign", asign{}) }

View File

@ -35,13 +35,17 @@ func _role_check(value ice.Map, key []string, ok bool) bool {
func _role_right(m *ice.Message, role string, key ...string) (ok bool) { func _role_right(m *ice.Message, role string, key ...string) (ok bool) {
return role == ROOT || len(mdb.HashSelectDetails(m, kit.Select(VOID, role), func(value ice.Map) bool { return _role_check(value, key, role == TECH) })) > 0 return role == ROOT || len(mdb.HashSelectDetails(m, kit.Select(VOID, role), func(value ice.Map) bool { return _role_check(value, key, role == TECH) })) > 0
} }
func _role_list(m *ice.Message, role string) *ice.Message { func _role_list(m *ice.Message, role string, arg ...string) *ice.Message {
mdb.HashSelectDetail(m, kit.Select(VOID, role), func(value ice.Map) { mdb.HashSelectDetail(m, kit.Select(VOID, role), func(value ice.Map) {
kit.For(value[WHITE], func(k string, v ice.Any) { kit.For(value[WHITE], func(k string, v ice.Any) {
m.Push(ROLE, kit.Value(value, mdb.NAME)).Push(mdb.ZONE, WHITE).Push(mdb.KEY, k).Push(mdb.STATUS, v) if len(arg) == 0 || k == arg[0] {
m.Push(ROLE, kit.Value(value, mdb.NAME)).Push(mdb.ZONE, WHITE).Push(mdb.KEY, k).Push(mdb.STATUS, v)
}
}) })
kit.For(value[BLACK], func(k string, v ice.Any) { kit.For(value[BLACK], func(k string, v ice.Any) {
m.Push(ROLE, kit.Value(value, mdb.NAME)).Push(mdb.ZONE, BLACK).Push(mdb.KEY, k).Push(mdb.STATUS, v) if len(arg) == 0 || k == arg[0] {
m.Push(ROLE, kit.Value(value, mdb.NAME)).Push(mdb.ZONE, BLACK).Push(mdb.KEY, k).Push(mdb.STATUS, v)
}
}) })
}) })
return m.Sort(mdb.KEY) return m.Sort(mdb.KEY)
@ -59,6 +63,7 @@ const (
) )
const ( const (
AUTH = "auth" AUTH = "auth"
ACCESS = "access"
PUBLIC = "public" PUBLIC = "public"
PRIVATE = "private" PRIVATE = "private"
CONFIRM = "confirm" CONFIRM = "confirm"
@ -67,10 +72,25 @@ const ROLE = "role"
func init() { func init() {
Index.MergeCommands(ice.Commands{ Index.MergeCommands(ice.Commands{
ROLE: {Name: "role role auto insert filter:text", Help: "角色", Actions: ice.MergeActions(ice.Actions{ ROLE: {Name: "role name key auto", Help: "角色", Actions: ice.MergeActions(ice.Actions{
ice.CTX_INIT: {Hand: func(m *ice.Message, arg ...string) {
m.Cmd(ROLE, mdb.CREATE, VOID, TECH)
has := map[string]bool{VOID: true, TECH: true}
m.Travel(func(p *ice.Context, c *ice.Context, key string, cmd *ice.Command) {
role := map[string][]string{}
kit.For(kit.Split(cmd.Role), func(k string) { role[k] = []string{} })
for sub, action := range cmd.Actions {
kit.For(kit.Split(action.Role), func(k string) { role[k] = append(role[k], sub) })
}
kit.For(role, func(role string, list []string) {
kit.If(!has[role], func() { m.Cmd(ROLE, mdb.CREATE, role); has[role] = true })
roleHandle(m, role, list...)
})
})
m.Cmd(ROLE, WHITE, VOID, ROLE, "action", RIGHT)
}},
mdb.INPUTS: {Hand: func(m *ice.Message, arg ...string) { mdb.INPUTS: {Hand: func(m *ice.Message, arg ...string) {
switch arg[0] { if arg[0] == mdb.KEY {
case mdb.KEY:
mdb.HashInputs(m, ice.INDEX).CutTo(ice.INDEX, arg[0]) mdb.HashInputs(m, ice.INDEX).CutTo(ice.INDEX, arg[0])
} }
}}, }},
@ -79,7 +99,7 @@ func init() {
mdb.Rich(m, ROLE, nil, kit.Dict(mdb.NAME, role, BLACK, kit.Dict(), WHITE, kit.Dict())) mdb.Rich(m, ROLE, nil, kit.Dict(mdb.NAME, role, BLACK, kit.Dict(), WHITE, kit.Dict()))
}) })
}}, }},
mdb.INSERT: {Name: "insert role*=void,tech zone*=white,black key*", Hand: func(m *ice.Message, arg ...string) { mdb.INSERT: {Name: "insert role*=void zone*=white,black key*", Hand: func(m *ice.Message, arg ...string) {
_role_set(m, m.Option(ROLE), m.Option(mdb.ZONE), m.Option(mdb.KEY), true) _role_set(m, m.Option(ROLE), m.Option(mdb.ZONE), m.Option(mdb.KEY), true)
}}, }},
mdb.DELETE: {Hand: func(m *ice.Message, arg ...string) { mdb.DELETE: {Hand: func(m *ice.Message, arg ...string) {
@ -88,32 +108,49 @@ func init() {
WHITE: {Hand: func(m *ice.Message, arg ...string) { _role_white(m, arg[0], _role_keys(arg[1:]...)) }}, WHITE: {Hand: func(m *ice.Message, arg ...string) { _role_white(m, arg[0], _role_keys(arg[1:]...)) }},
BLACK: {Hand: func(m *ice.Message, arg ...string) { _role_black(m, arg[0], _role_keys(arg[1:]...)) }}, BLACK: {Hand: func(m *ice.Message, arg ...string) { _role_black(m, arg[0], _role_keys(arg[1:]...)) }},
RIGHT: {Hand: func(m *ice.Message, arg ...string) { RIGHT: {Hand: func(m *ice.Message, arg ...string) {
kit.If(_role_right(m, arg[0], kit.Split(_role_keys(arg[1:]...), ice.PT)...), func() { m.Echo(ice.OK) }) if len(arg) > 2 {
m.Search(arg[1], func(key string, cmd *ice.Command) {
if _, ok := cmd.Actions[arg[2]]; ok {
arg = kit.Simple(arg[0], arg[1], ice.ACTION, arg[2:])
}
})
}
for _, role := range kit.AddUniq(kit.Split(arg[0]), VOID) {
if _role_right(m, role, kit.Split(_role_keys(arg[1:]...), ice.PT)...) {
m.Echo(ice.OK)
break
}
}
}}, }},
"whiteblack": {Hand: func(m *ice.Message, arg ...string) { }, mdb.HashAction(mdb.SHORT, mdb.NAME, mdb.FIELD, "time,name")), Hand: func(m *ice.Message, arg ...string) {
kit.For(arg, func(cmd string) { m.Cmd(ROLE, WHITE, VOID, cmd); m.Cmd(ROLE, BLACK, VOID, cmd, ice.ACTION) }) if len(arg) == 0 {
}}, mdb.HashSelect(m, arg...)
}, mdb.HashAction(mdb.SHORT, mdb.NAME)), Hand: func(m *ice.Message, arg ...string) { } else {
_role_list(m, kit.Select("", arg, 0)).PushAction(mdb.DELETE) _role_list(m, kit.Select("", arg, 0), kit.Slice(arg, 1)...)
}
}}, }},
}) })
} }
func RoleAction(key ...string) ice.Actions { func roleHandle(m *ice.Message, role string, key ...string) {
return ice.Actions{ice.CTX_INIT: {Hand: func(m *ice.Message, arg ...string) { cmd := m.ShortKey()
cmd := m.PrefixKey() role = kit.Select(VOID, role)
if c, ok := ice.Info.Index[m.CommandKey()].(*ice.Context); ok && c == m.Target() { m.Cmd(ROLE, WHITE, role, cmd)
cmd = m.CommandKey() if cmd == "header" {
} return
m.Cmd(ROLE, WHITE, VOID, cmd) }
m.Cmd(ROLE, BLACK, VOID, cmd, ice.ACTION) m.Cmd(ROLE, BLACK, role, cmd, ice.ACTION)
kit.For(key, func(key string) { m.Cmd(ROLE, WHITE, VOID, cmd, ice.ACTION, key) }) kit.For(key, func(key string) { m.Cmd(ROLE, WHITE, role, cmd, ice.ACTION, key) })
}}}
} }
func WhiteAction(key ...string) ice.Actions { func WhiteAction(role string, key ...string) ice.Actions {
role = kit.Select(VOID, role)
return ice.Actions{ice.CTX_INIT: {Hand: func(m *ice.Message, arg ...string) { return ice.Actions{ice.CTX_INIT: {Hand: func(m *ice.Message, arg ...string) {
m.Cmd(ROLE, WHITE, VOID, m.CommandKey()) cmd := m.CommandKey()
m.Cmd(ROLE, BLACK, VOID, m.CommandKey(), ice.ACTION) m.Cmd(ROLE, WHITE, role, cmd)
kit.For(key, func(key string) { m.Cmd(ROLE, WHITE, VOID, m.CommandKey(), ice.ACTION, key) }) if cmd == "header" {
return
}
m.Cmd(ROLE, BLACK, role, cmd, ice.ACTION)
kit.For(key, func(key string) { m.Cmd(ROLE, WHITE, role, cmd, ice.ACTION, key) })
}}} }}}
} }
func White(m *ice.Message, key ...string) { func White(m *ice.Message, key ...string) {
@ -128,6 +165,8 @@ func Right(m *ice.Message, key ...ice.Any) bool {
} else if len(key) > 0 && key[0] == ice.ETC_PATH { } else if len(key) > 0 && key[0] == ice.ETC_PATH {
return true return true
} }
return m.Option(ice.MSG_USERROLE) == ROOT || !m.Warn(m.Cmdx(ROLE, RIGHT, m.Option(ice.MSG_USERROLE), key, logs.FileLineMeta(-1)) != ice.OK, // m.Option(ice.MSG_TITLE, kit.Keys(m.Option(ice.MSG_USERPOD), m.CommandKey(), m.ActionKey())+" "+logs.FileLine(-2))
ice.ErrNotRight, kit.Keys(key...), USERROLE, m.Option(ice.MSG_USERROLE), logs.FileLineMeta(-1)) return !ice.Info.Important || m.Option(ice.MSG_USERROLE) == ROOT || !m.WarnNotRight(m.Cmdx(ROLE, RIGHT, m.Option(ice.MSG_USERROLE), key, logs.FileLineMeta(-1)) != ice.OK,
kit.Keys(key...), USERROLE, m.Option(ice.MSG_USERROLE))
} }
func IsTechOrRoot(m *ice.Message) bool { return kit.IsIn(m.Option(ice.MSG_USERROLE), TECH, ROOT) }

View File

@ -9,20 +9,22 @@ import (
func _sess_create(m *ice.Message, username string, arg ...string) { func _sess_create(m *ice.Message, username string, arg ...string) {
if msg := m.Cmd(USER, username); msg.Length() > 0 { if msg := m.Cmd(USER, username); msg.Length() > 0 {
mdb.HashCreate(m, msg.AppendSimple(USERNICK, USERNAME, USERROLE), arg) mdb.HashCreate(m, msg.AppendSimple(USERROLE, USERNAME, USERNICK, AVATAR), arg)
} else { } else {
mdb.HashCreate(m, m.OptionSimple(USERNICK, USERNAME, USERROLE), arg) mdb.HashCreate(m, m.OptionSimple(USERROLE, USERNAME, USERNICK, AVATAR), arg)
} }
} }
func _sess_check(m *ice.Message, sessid string) { func _sess_check(m *ice.Message, sessid string) {
if val := mdb.HashSelectDetails(m, sessid, func(value ice.Map) bool { return !m.WarnTimeNotValid(value[mdb.TIME], sessid) }); len(val) > 0 { if val := mdb.HashSelectDetails(m, sessid, func(value ice.Map) bool {
return kit.Format(value[mdb.TIME]) > m.Time()
}); len(val) > 0 {
SessAuth(m, val) SessAuth(m, val)
} }
} }
const ( const (
UA = "ua"
IP = "ip" IP = "ip"
UA = "ua"
) )
const ( const (
CHECK = "check" CHECK = "check"
@ -33,12 +35,12 @@ const SESS = "sess"
func init() { func init() {
Index.MergeCommands(ice.Commands{ Index.MergeCommands(ice.Commands{
SESS: {Help: "会话", Actions: ice.MergeActions(ice.Actions{ SESS: {Name: "sess hash auto", Help: "会话", Actions: ice.MergeActions(ice.Actions{
mdb.CREATE: {Name: "create username*", Hand: func(m *ice.Message, arg ...string) { mdb.CREATE: {Name: "create username*", Hand: func(m *ice.Message, arg ...string) {
_sess_create(m, m.Option(USERNAME), UA, m.Option(ice.MSG_USERUA), IP, m.Option(ice.MSG_USERIP)) _sess_create(m, m.Option(USERNAME), UA, m.Option(ice.MSG_USERUA), IP, m.Option(ice.MSG_USERIP))
}}, }},
CHECK: {Name: "check sessid*", Hand: func(m *ice.Message, arg ...string) { _sess_check(m, m.Option(ice.MSG_SESSID)) }}, CHECK: {Name: "check sessid*", Hand: func(m *ice.Message, arg ...string) { _sess_check(m, m.Option(ice.MSG_SESSID)) }},
}, mdb.ImportantHashAction(mdb.EXPIRE, mdb.MONTH, mdb.SHORT, mdb.UNIQ, mdb.FIELD, "time,hash,usernick,username,userrole,ua,ip"))}, }, mdb.ImportantHashAction("checkbox", ice.TRUE, mdb.EXPIRE, mdb.MONTH, mdb.SHORT, mdb.UNIQ, mdb.FIELD, "time,hash,userrole,username,usernick,avatar,ip,ua"))},
}) })
} }
@ -46,14 +48,22 @@ func SessCreate(m *ice.Message, username string) string {
return m.Option(ice.MSG_SESSID, m.Cmdx(SESS, mdb.CREATE, username)) return m.Option(ice.MSG_SESSID, m.Cmdx(SESS, mdb.CREATE, username))
} }
func SessCheck(m *ice.Message, sessid string) bool { func SessCheck(m *ice.Message, sessid string) bool {
m.Options(ice.MSG_USERNICK, "", ice.MSG_USERNAME, "", ice.MSG_USERROLE, VOID, "aaa.checker", logs.FileLine(-1)) m.Options(ice.MSG_USERNICK, "", ice.MSG_USERNAME, "", ice.MSG_USERROLE, VOID, ice.MSG_CHECKER, logs.FileLine(-1))
return sessid != "" && m.Cmdy(SESS, CHECK, sessid, logs.FileLineMeta(-1)).Option(ice.MSG_USERNAME) != "" return sessid != "" && m.Cmdy(SESS, CHECK, sessid, logs.FileLineMeta(-1)).Option(ice.MSG_USERNAME) != ""
} }
func SessValid(m *ice.Message) string {
if m.Option(ice.MSG_SESSID) == "" || m.Spawn().AdminCmd(SESS, m.Option(ice.MSG_SESSID)).Length() == 0 {
return m.Option(ice.MSG_SESSID, m.Spawn().AdminCmd(SESS, mdb.CREATE, m.Option(ice.MSG_USERNAME)).Result())
}
return m.Option(ice.MSG_SESSID)
}
func SessAuth(m *ice.Message, value ice.Any, arg ...string) *ice.Message { func SessAuth(m *ice.Message, value ice.Any, arg ...string) *ice.Message {
return m.Auth( return m.Auth(
USERNICK, m.Option(ice.MSG_USERNICK, kit.Format(kit.Value(value, USERNICK))),
USERNAME, m.Option(ice.MSG_USERNAME, kit.Format(kit.Value(value, USERNAME))),
USERROLE, m.Option(ice.MSG_USERROLE, kit.Format(kit.Value(value, USERROLE))), USERROLE, m.Option(ice.MSG_USERROLE, kit.Format(kit.Value(value, USERROLE))),
USERNAME, m.Option(ice.MSG_USERNAME, kit.Format(kit.Value(value, USERNAME))),
USERNICK, m.Option(ice.MSG_USERNICK, kit.Format(kit.Value(value, USERNICK))),
LANGUAGE, m.OptionDefault(ice.MSG_LANGUAGE, kit.Format(kit.Value(value, LANGUAGE))),
AVATAR, m.Option(ice.MSG_AVATAR, kit.Format(kit.Value(value, AVATAR))),
arg, logs.FileLineMeta(kit.Select(logs.FileLine(-1), m.Option("aaa.checker"))), arg, logs.FileLineMeta(kit.Select(logs.FileLine(-1), m.Option("aaa.checker"))),
) )
} }

View File

@ -60,9 +60,7 @@ func init() {
m.Echo(m.Append(mdb.VALUE)) m.Echo(m.Append(mdb.VALUE))
} }
}) })
if len(arg) == 0 { kit.If(len(arg) == 0, func() { m.PushAction(mdb.REMOVE).Action(mdb.CREATE, mdb.PRUNES) })
m.PushAction(mdb.REMOVE).Action(mdb.CREATE, mdb.PRUNES)
}
}}, }},
}) })
} }

View File

@ -4,6 +4,7 @@ import (
ice "shylinux.com/x/icebergs" ice "shylinux.com/x/icebergs"
"shylinux.com/x/icebergs/base/gdb" "shylinux.com/x/icebergs/base/gdb"
"shylinux.com/x/icebergs/base/mdb" "shylinux.com/x/icebergs/base/mdb"
"shylinux.com/x/icebergs/base/web/html"
kit "shylinux.com/x/toolkits" kit "shylinux.com/x/toolkits"
) )
@ -11,6 +12,10 @@ func _user_create(m *ice.Message, name string, arg ...string) {
mdb.HashCreate(m, USERNAME, name, arg) mdb.HashCreate(m, USERNAME, name, arg)
gdb.Event(m, USER_CREATE, USER, name) gdb.Event(m, USER_CREATE, USER, name)
} }
func _user_remove(m *ice.Message, name string, arg ...string) {
gdb.Event(m, USER_REMOVE, m.OptionSimple(USERNAME, USERNICK))
mdb.HashRemove(m, m.OptionSimple(USERNAME))
}
const ( const (
BACKGROUND = "background" BACKGROUND = "background"
@ -18,12 +23,15 @@ const (
AVATAR = "avatar" AVATAR = "avatar"
GENDER = "gender" GENDER = "gender"
MOBILE = "mobile" MOBILE = "mobile"
PHONE = "phone"
SECRET = "secret" SECRET = "secret"
THEME = "theme" THEME = "theme"
LANGUAGE = "language" LANGUAGE = "language"
LOCATION = "location"
LONGITUDE = "longitude" LONGITUDE = "longitude"
LATITUDE = "latitude" LATITUDE = "latitude"
COMPANY = "company"
PROVINCE = "province" PROVINCE = "province"
COUNTRY = "country" COUNTRY = "country"
CITY = "city" CITY = "city"
@ -36,12 +44,13 @@ const (
USERZONE = "userzone" USERZONE = "userzone"
USER_CREATE = "user.create" USER_CREATE = "user.create"
USER_REMOVE = "user.remove"
) )
const USER = "user" const USER = "user"
func init() { func init() {
Index.MergeCommands(ice.Commands{ Index.MergeCommands(ice.Commands{
USER: {Help: "用户", Actions: ice.MergeActions(ice.Actions{ USER: {Help: "用户", Icon: "Contacts.png", Actions: ice.MergeActions(ice.Actions{
mdb.INPUTS: {Hand: func(m *ice.Message, arg ...string) { mdb.INPUTS: {Hand: func(m *ice.Message, arg ...string) {
switch mdb.HashInputs(m, arg); arg[0] { switch mdb.HashInputs(m, arg); arg[0] {
case USERNICK: case USERNICK:
@ -49,47 +58,55 @@ func init() {
case USERNAME: case USERNAME:
m.Push(arg[0], m.Option(ice.MSG_USERNAME)) m.Push(arg[0], m.Option(ice.MSG_USERNAME))
} }
if arg[0] == USERROLE {
m.Option(ice.TABLE_CHECKBOX, ice.TRUE)
}
}}, }},
mdb.CREATE: {Name: "create usernick username* userrole=void,tech userzone", Hand: func(m *ice.Message, arg ...string) { mdb.CREATE: {Name: "create userrole=void,tech username* usernick language userzone email avatar", Hand: func(m *ice.Message, arg ...string) {
_user_create(m, m.Option(USERNAME), m.OptionSimple(USERNICK, USERROLE, USERZONE, BACKGROUND, AVATAR, AVATAR_URL, LANGUAGE, EMAIL)...) _user_create(m, m.Option(USERNAME), m.OptionSimple(USERROLE, USERNICK, LANGUAGE, AVATAR, BACKGROUND, USERZONE, EMAIL)...)
}}, }},
}, mdb.ImportantHashAction(mdb.SHORT, USERNAME, mdb.FIELD, "time,usernick,username,userrole,userzone"))}, mdb.REMOVE: {Hand: func(m *ice.Message, arg ...string) { _user_remove(m, m.Option(USERNAME)) }},
}, mdb.ImportantHashAction(mdb.SHORT, USERNAME, mdb.FIELD, "time,userrole,username,usernick,language,avatar,background,userzone", html.CHECKBOX, ice.TRUE))},
}) })
} }
func UserInfo(m *ice.Message, name ice.Any, key, meta string) (value string) { func UserInfo(m *ice.Message, name ice.Any, key, meta string) (value string) {
if m.Cmd(USER, kit.Select(m.Option(ice.MSG_USERNAME), name), func(val ice.Maps) { value = val[key] }).Length() == 0 && kit.Format(name) == m.Option(ice.MSG_USERNAME) { if m.Cmd(USER, kit.Select(m.Option(ice.MSG_USERNAME), name), func(val ice.Maps) { value = val[key] }).Length() == 0 || value == "" {
return m.Option(meta) return m.Option(meta)
} }
return return
} }
func UserEmail(m *ice.Message, username ice.Any) (nick string) { func UserRole(m *ice.Message, username ice.Any) (role string) {
return UserInfo(m, username, EMAIL, EMAIL) if username == "" {
return VOID
} else if role = VOID; username == ice.Info.Username {
return ROOT
} else {
return UserInfo(m, username, USERROLE, ice.MSG_USERROLE)
}
} }
func UserNick(m *ice.Message, username ice.Any) (nick string) { func UserNick(m *ice.Message, username ice.Any) (nick string) {
return UserInfo(m, username, USERNICK, ice.MSG_USERNICK) return UserInfo(m, username, USERNICK, ice.MSG_USERNICK)
} }
func UserRole(m *ice.Message, username ice.Any) (role string) { func UserLang(m *ice.Message, username ice.Any) (nick string) {
if username == "" { return UserInfo(m, username, LANGUAGE, ice.MSG_LANGUAGE)
return VOID
}
if role = VOID; username == ice.Info.Username {
return ROOT
}
return UserInfo(m, username, USERROLE, ice.MSG_USERROLE)
} }
func UserZone(m *ice.Message, username ice.Any) (zone string) { func UserZone(m *ice.Message, username ice.Any) (zone string) {
return UserInfo(m, username, USERZONE, ice.MSG_USERZONE) return UserInfo(m, username, USERZONE, ice.MSG_USERZONE)
} }
func UserRoot(m *ice.Message, arg ...string) *ice.Message { func UserEmail(m *ice.Message, username ice.Any) (nick string) {
userzone := kit.Select("", arg, 3) return UserInfo(m, username, EMAIL, EMAIL)
userrole := kit.Select(ROOT, arg, 2) }
username := kit.Select(ice.Info.Username, arg, 1) func UserRoot(m *ice.Message, arg ...string) *ice.Message {
usernick := kit.Select(UserNick(m, username), arg, 0) userrole := kit.Select(TECH, arg, 0)
background := kit.Select("usr/icons/background.jpg", UserInfo(m, username, BACKGROUND, "")) username := kit.Select(ice.Info.Username, arg, 1)
if len(arg) > 0 { usernick := kit.Select(UserNick(m, username), arg, 2)
ice.Info.Username = username language := kit.Select(UserLang(m, username), arg, 3)
m.Cmd(USER, mdb.CREATE, usernick, username, userrole, userzone, background) userzone := kit.Select(ice.OPS, arg, 4)
} email := kit.Select(UserEmail(m, username), arg, 5)
return SessAuth(m, kit.Dict(USERNICK, usernick, USERNAME, username, USERROLE, userrole)) if len(arg) > 0 {
kit.If(username != ROOT, func() { ice.Info.Username = username })
m.Cmd(USER, mdb.CREATE, userrole, username, usernick, language, userzone, email)
}
return SessAuth(m, kit.Dict(USERROLE, userrole, USERNAME, username, USERNICK, usernick))
} }

View File

@ -11,4 +11,4 @@ var Index = &ice.Context{Name: CLI, Help: "命令模块"}
func Prefix(arg ...string) string { return kit.Keys(CLI, arg) } func Prefix(arg ...string) string { return kit.Keys(CLI, arg) }
func init() { ice.Index.Register(Index, nil, RUNTIME, SYSTEM, DAEMON, FOREVER, MIRRORS, QRCODE) } func init() { ice.Index.Register(Index, nil, RUNTIME, SYSTEM, DAEMON, FOREVER, MIRRORS, QRCODE, SUDO) }

View File

@ -28,11 +28,18 @@ var _color_map = map[string]color.Color{
SILVER: color.RGBA{0xC0, 0xC0, 0xC0, _DARK}, SILVER: color.RGBA{0xC0, 0xC0, 0xC0, _DARK},
} }
var _color_list = map[string]string{
"navy": "#000080",
"aliceblue": "#f0f8ff",
"firebrick": "#b22222",
}
func _parse_color(str string) color.Color { func _parse_color(str string) color.Color {
if str == RANDOM { if str == RANDOM {
list := kit.SortedKey(_color_map) list := kit.SortedKey(_color_map)
str = list[rand.Intn(len(list))] str = list[rand.Intn(len(list))]
} }
str = kit.Select(str, _color_list[str])
if strings.HasPrefix(str, "#") { if strings.HasPrefix(str, "#") {
kit.If(len(str) == 7, func() { str += "ff" }) kit.If(len(str) == 7, func() { str += "ff" })
if u, e := strconv.ParseUint(str[1:], 16, 64); e == nil { if u, e := strconv.ParseUint(str[1:], 16, 64); e == nil {

View File

@ -30,17 +30,16 @@ func _daemon_exec(m *ice.Message, cmd *exec.Cmd) {
cmd.Stderr = w cmd.Stderr = w
} }
h := mdb.HashCreate(m.Spawn(), STATUS, START, h := mdb.HashCreate(m.Spawn(), STATUS, START,
ice.CMD, kit.Join(cmd.Args, lex.SP), DIR, cmd.Dir, ENV, kit.Select("", cmd.Env), ice.CMD, strings.TrimPrefix(strings.TrimPrefix(kit.JoinWord(cmd.Args...), kit.Path("")+nfs.PS), cmd.Dir+nfs.PS), DIR, cmd.Dir, ENV, kit.Select("", cmd.Env),
m.OptionSimple(CMD_INPUT, CMD_OUTPUT, CMD_ERRPUT, mdb.CACHE_CLEAR_ONEXIT), m.OptionSimple(CMD_INPUT, CMD_OUTPUT, CMD_ERRPUT, mdb.CACHE_CLEAR_ONEXIT),
) )
if e := cmd.Start(); m.Warn(e, ice.ErrNotStart, cmd.Args, err.String()) { if e := cmd.Start(); m.WarnNotValid(e, cmd.Args, err.String()) {
mdb.HashModify(m, h, STATUS, ERROR, ERROR, e) mdb.HashModify(m, h, STATUS, ERROR, ERROR, e)
return return
} }
mdb.HashSelectUpdate(m, h, func(value ice.Map) { value[PID] = cmd.Process.Pid }) mdb.HashSelectUpdate(m, h, func(value ice.Map) { value[PID] = cmd.Process.Pid })
m.Echo("%d", cmd.Process.Pid) m.Echo("%d", cmd.Process.Pid).Go(func() {
m.Go(func() { if e := cmd.Wait(); !m.WarnNotValid(e, cmd.Args, err.String()) && cmd.ProcessState != nil && cmd.ProcessState.Success() {
if e := cmd.Wait(); !m.Warn(e, ice.ErrNotStart, cmd.Args, err.String()) && cmd.ProcessState != nil && cmd.ProcessState.Success() {
mdb.HashModify(m, mdb.HASH, h, STATUS, STOP) mdb.HashModify(m, mdb.HASH, h, STATUS, STOP)
m.Cost(CODE, "0", ctx.ARGS, cmd.Args) m.Cost(CODE, "0", ctx.ARGS, cmd.Args)
} else { } else {
@ -62,12 +61,13 @@ func _daemon_exec(m *ice.Message, cmd *exec.Cmd) {
} }
const ( const (
DIR = "dir" DIR = "dir"
ENV = "env" ENV = "env"
API = "api" API = "api"
MOD = "mod" MOD = "mod"
PID = "pid" PWD = "pwd"
PWD = "pwd" PID = "pid"
PPID = "ppid"
) )
const ( const (
BUILD = "build" BUILD = "build"
@ -77,13 +77,20 @@ const (
BENCH = "bench" BENCH = "bench"
PPROF = "pprof" PPROF = "pprof"
TIMEOUT = "timeout" TIMEOUT = "timeout"
STATUS = "status" STATUS = "status"
ERROR = "error" ERROR = "error"
CLEAR = "clear" CLEAR = "clear"
DELAY = "delay" STASH = "stash"
RELOAD = "reload" DELAY = "delay"
RESTART = "restart" RECORD = "record"
RELOAD = "reload"
REBOOT = "reboot"
RESTART = "restart"
INTERVAL = "interval"
OPTS = "opts"
ARGS = "args"
LOGS = "logs"
BEGIN = "begin" BEGIN = "begin"
END = "end" END = "end"
@ -92,6 +99,7 @@ const (
OPEN = "open" OPEN = "open"
CLOSE = "close" CLOSE = "close"
PLAY = "play"
MAIN = "main" MAIN = "main"
CODE = "code" CODE = "code"
COST = "cost" COST = "cost"
@ -104,15 +112,19 @@ const DAEMON = "daemon"
func init() { func init() {
Index.MergeCommands(ice.Commands{ Index.MergeCommands(ice.Commands{
DAEMON: {Name: "daemon hash auto", Help: "守护进程", Actions: ice.MergeActions(ice.Actions{ DAEMON: {Name: "daemon hash auto", Help: "守护进程", Actions: ice.MergeActions(ice.Actions{
ice.CTX_EXIT: {Hand: func(m *ice.Message, arg ...string) { mdb.HashPrunesValue(m, mdb.CACHE_CLEAR_ONEXIT, ice.TRUE) }}, ice.CTX_EXIT: {Hand: func(m *ice.Message, arg ...string) {
mdb.HashPrunesValue(m, mdb.CACHE_CLEAR_ONEXIT, ice.TRUE)
}},
START: {Name: "start cmd* dir env", Hand: func(m *ice.Message, arg ...string) { START: {Name: "start cmd* dir env", Hand: func(m *ice.Message, arg ...string) {
m.Options(CMD_DIR, m.Option(DIR), CMD_ENV, kit.Split(m.Option(ENV), " =")) m.Options(CMD_DIR, m.Option(DIR), CMD_ENV, kit.Split(m.Option(ENV), " ="))
_daemon_exec(m, _system_cmd(m, kit.Split(m.Option(ice.CMD))...)) _daemon_exec(m, _system_cmd(m, kit.Split(m.Option(ice.CMD))...))
}}, }},
RESTART: {Hand: func(m *ice.Message, arg ...string) { m.Cmdy("", STOP).Sleep3s().Cmdy("", START) }}, RESTART: {Hand: func(m *ice.Message, arg ...string) {
m.Cmdy("", STOP).Sleep3s().Cmdy("", START)
}},
STOP: {Hand: func(m *ice.Message, arg ...string) { STOP: {Hand: func(m *ice.Message, arg ...string) {
h, pid := m.Option(mdb.HASH), m.Option(PID) h, pid := m.Option(mdb.HASH), m.Option(PID)
mdb.HashSelects(m, h).Table(func(value ice.Maps) { mdb.HashSelects(m.Spawn(), h).Table(func(value ice.Maps) {
if h == "" && value[PID] != pid { if h == "" && value[PID] != pid {
return return
} }
@ -122,7 +134,7 @@ func init() {
}}, }},
mdb.REMOVE: {Hand: func(m *ice.Message, arg ...string) { mdb.REMOVE: {Hand: func(m *ice.Message, arg ...string) {
h, pid := m.Option(mdb.HASH), m.Option(PID) h, pid := m.Option(mdb.HASH), m.Option(PID)
mdb.HashSelects(m, h).Table(func(value ice.Maps) { mdb.HashSelects(m.Spawn(), h).Table(func(value ice.Maps) {
if h == "" && value[PID] != pid { if h == "" && value[PID] != pid {
return return
} }
@ -140,7 +152,12 @@ func init() {
}) })
kit.If(len(arg) == 0, func() { m.Action(START, mdb.PRUNES) }) kit.If(len(arg) == 0, func() { m.Action(START, mdb.PRUNES) })
if len(arg) > 0 && m.Length() == 0 { if len(arg) > 0 && m.Length() == 0 {
_daemon_exec(m, _system_cmd(m, kit.Simple(kit.Split(arg[0]), arg[1:])...)) if runtime.GOOS == WINDOWS {
_daemon_exec(m, _system_cmd(m, arg...))
} else {
_daemon_exec(m, _system_cmd(m, arg...))
// _daemon_exec(m, _system_cmd(m, kit.Simple(kit.Split(arg[0]), arg[1:])...))
}
kit.If(IsSuccess(m) && m.Append(CMD_ERR) == "", func() { m.SetAppend() }) kit.If(IsSuccess(m) && m.Append(CMD_ERR) == "", func() { m.SetAppend() })
} }
}}, }},
@ -149,10 +166,9 @@ func init() {
func Opens(m *ice.Message, arg ...string) { func Opens(m *ice.Message, arg ...string) {
if !tcp.IsLocalHost(m, m.Option(ice.MSG_USERIP)) { if !tcp.IsLocalHost(m, m.Option(ice.MSG_USERIP)) {
return // return
} } else if len(arg) == 0 || arg[0] == "" {
if len(arg) == 0 || arg[0] == "" { // return
return
} }
switch runtime.GOOS { switch runtime.GOOS {
case DARWIN: case DARWIN:
@ -172,15 +188,17 @@ func Opens(m *ice.Message, arg ...string) {
func OpenCmds(m *ice.Message, arg ...string) *ice.Message { func OpenCmds(m *ice.Message, arg ...string) *ice.Message {
if !tcp.IsLocalHost(m, m.Option(ice.MSG_USERIP)) { if !tcp.IsLocalHost(m, m.Option(ice.MSG_USERIP)) {
return m return m
} } else if len(arg) == 0 || arg[0] == "" {
if len(arg) == 0 || arg[0] == "" {
return m return m
} }
m.Cmd(SYSTEM, "osascript", "-e", kit.Format(` TellApp(m, "Terminal", kit.Format(`do script %q`, strings.Join(arg, "; ")), "activate")
tell application "Terminal"
do script "%s"
activate
end tell
`, strings.Join(arg, "; ")))
return m return m
} }
func TellApp(m *ice.Message, app string, arg ...string) {
OSAScript(m, kit.Format(`
tell application "%s"
%s
end tell
`, app, strings.Join(arg, lex.NL)))
}
func OSAScript(m *ice.Message, arg ...string) { m.Cmd(SYSTEM, "osascript", "-e", arg) }

View File

@ -29,7 +29,7 @@ func init() {
} }
}) })
m.Options(CMD_ENV, env, CMD_INPUT, os.Stdin, CMD_OUTPUT, os.Stdout, CMD_ERRPUT, os.Stderr) m.Options(CMD_ENV, env, CMD_INPUT, os.Stdin, CMD_OUTPUT, os.Stdout, CMD_ERRPUT, os.Stderr)
kit.If(kit.Env(CTX_LOG), func(p string) { m.Optionv(CMD_ERRPUT, p) }) kit.If(kit.Select("/dev/null", kit.Env(CTX_LOG)), func(p string) { m.Optionv(CMD_ERRPUT, p) })
m.Cmd(FOREVER, STOP) m.Cmd(FOREVER, STOP)
if bin := kit.Select(os.Args[0], ice.BIN_ICE_BIN, nfs.Exists(m, ice.BIN_ICE_BIN)); len(arg) > 0 && arg[0] == ice.SPACE { if bin := kit.Select(os.Args[0], ice.BIN_ICE_BIN, nfs.Exists(m, ice.BIN_ICE_BIN)); len(arg) > 0 && arg[0] == ice.SPACE {
m.Cmdy(FOREVER, bin, ice.SPACE, START, ice.DEV, ice.OPS, arg[1:]) m.Cmdy(FOREVER, bin, ice.SPACE, START, ice.DEV, ice.OPS, arg[1:])

View File

@ -22,6 +22,7 @@ const (
ALPINE = "alpine" ALPINE = "alpine"
BUSYBOX = "busybox" BUSYBOX = "busybox"
RELEASE = "release" RELEASE = "release"
RHEL = "rhel"
ETC_OS_RELEASE = "/etc/os-release" ETC_OS_RELEASE = "/etc/os-release"
ETC_APK_REPOS = "/etc/apk/repositories" ETC_APK_REPOS = "/etc/apk/repositories"
@ -36,26 +37,26 @@ func init() {
CMD: {Name: "cmd cli osid", Hand: func(m *ice.Message, arg ...string) { CMD: {Name: "cmd cli osid", Hand: func(m *ice.Message, arg ...string) {
osid := kit.Select(mdb.Conf(m, RUNTIME, kit.Keys(HOST, OSID)), m.Option(OSID)) osid := kit.Select(mdb.Conf(m, RUNTIME, kit.Keys(HOST, OSID)), m.Option(OSID))
mdb.ZoneSelectCB(m, m.Option(CLI), func(value ice.Map) { mdb.ZoneSelectCB(m, m.Option(CLI), func(value ice.Map) {
kit.If(strings.Contains(osid, kit.Format(value[OSID])), func() { m.Cmdy(kit.Split(kit.Format(value[CMD]))) }) kit.If(strings.Contains(osid, kit.Format(value[OSID])), func() {
m.Cmdy(kit.Split(kit.Format(value[CMD])))
})
}) })
}}, }},
ADD: {Help: "安装", Hand: func(m *ice.Message, arg ...string) { ADD: {Help: "安装", Hand: func(m *ice.Message, arg ...string) {
ice.Info.PushStream(m)
mdb.ZoneSelect(m, m.Option(CLI)).Table(func(value ice.Maps) { mdb.ZoneSelect(m, m.Option(CLI)).Table(func(value ice.Maps) {
ice.Info.PushStream(m) m.ToastProcess()
m.Toast(ice.PROCESS, "", "-1")
if msg := m.Cmd(kit.Split(value[CMD])); IsSuccess(msg) { if msg := m.Cmd(kit.Split(value[CMD])); IsSuccess(msg) {
m.Toast(ice.SUCCESS) m.ToastSuccess()
} else { } else {
m.Toast(ice.FAILURE) m.ToastFailure()
} }
}) })
}}, }},
REPOS: {Name: "repos proxy=mirrors.tencent.com", Help: "镜像", Hand: func(m *ice.Message, arg ...string) { REPOS: {Name: "repos proxy=mirrors.tencent.com", Help: "镜像", Hand: func(m *ice.Message, arg ...string) {
switch { switch {
case strings.Contains(_release, ALPINE): case strings.Contains(_release, ALPINE):
m.Toast(ice.PROCESS, "", "-1") defer m.PushStream().ToastProcess()()
defer m.Toast(ice.SUCCESS)
ice.Info.PushStream(m)
kit.If(m.Option("proxy"), func(p string) { kit.If(m.Option("proxy"), func(p string) {
m.Cmd(nfs.SAVE, ETC_APK_REPOS, strings.ReplaceAll(m.Cmdx(nfs.CAT, ETC_APK_REPOS), "dl-cdn.alpinelinux.org", p)) m.Cmd(nfs.SAVE, ETC_APK_REPOS, strings.ReplaceAll(m.Cmdx(nfs.CAT, ETC_APK_REPOS), "dl-cdn.alpinelinux.org", p))
}) })
@ -78,6 +79,7 @@ func init() {
case strings.Contains(_release, ALPINE): case strings.Contains(_release, ALPINE):
m.Cmdy(nfs.CAT, ETC_APK_REPOS) m.Cmdy(nfs.CAT, ETC_APK_REPOS)
} }
// m.EchoScript(kit.Format("cd %s; %s", kit.Path(""), kit.JoinCmds(kit.Simple(kit.Path(os.Args[0]), os.Args[1:])...)))
}}, }},
}) })
} }
@ -95,7 +97,7 @@ func release(m *ice.Message) string {
} }
return text return text
}) })
_release = strings.Join(list, lex.SP) _release = kit.JoinWord(list...)
return _release return _release
} }
func insert(m *ice.Message, sys, cmd string, arg ...string) bool { func insert(m *ice.Message, sys, cmd string, arg ...string) bool {
@ -103,19 +105,18 @@ func insert(m *ice.Message, sys, cmd string, arg ...string) bool {
return false return false
} }
if len(arg) > 0 { if len(arg) > 0 {
m.GoSleep("300ms", mdb.INSERT, kit.Keys(CLI, MIRRORS), "", mdb.ZONE, arg[0], OSID, sys, CMD, cmd+lex.SP+kit.Select(arg[0], arg, 1)) m.GoSleep300ms(func() {
m.Cmd(mdb.INSERT, kit.Keys(CLI, MIRRORS), "", mdb.ZONE, arg[0], OSID, sys, CMD, cmd+lex.SP+kit.Select(arg[0], arg, 1))
})
} }
return true return true
} }
func IsAlpine(m *ice.Message, arg ...string) bool { func IsAlpine(m *ice.Message, arg ...string) bool {
return insert(m, ALPINE, "system apk add", arg...) return insert(m, ALPINE, "system apk add", arg...)
} }
func IsCentos(m *ice.Message, arg ...string) bool { func IsRedhat(m *ice.Message, arg ...string) bool {
return insert(m, CENTOS, "system yum install -y", arg...) return insert(m, RHEL, "system yum install -y", arg...)
}
func IsUbuntu(m *ice.Message, arg ...string) bool {
return insert(m, UBUNTU, "system apt get -y", arg...)
} }
func IsSystem(m *ice.Message, arg ...string) bool { func IsSystem(m *ice.Message, arg ...string) bool {
return IsAlpine(m, arg...) || IsCentos(m, arg...) || IsUbuntu(m, arg...) return IsAlpine(m, arg...) || IsRedhat(m, arg...)
} }

View File

@ -1,32 +0,0 @@
package cli
import (
"strings"
ice "shylinux.com/x/icebergs"
"shylinux.com/x/icebergs/base/gdb"
"shylinux.com/x/icebergs/base/mdb"
"shylinux.com/x/icebergs/base/nfs"
kit "shylinux.com/x/toolkits"
)
func init() {
Index.MergeCommands(ice.Commands{
PROCINFO: {Name: "procinfo PID auto filter:text terminal monitor docker", Help: "进程列表", Actions: ice.MergeActions(ice.Actions{
PROCKILL: {Help: "结束进程", Hand: func(m *ice.Message, arg ...string) { m.Cmdy(gdb.SIGNAL, gdb.STOP, m.Option("PID")).ProcessRefresh() }},
"terminal": {Help: "终端", Hand: func(m *ice.Message, arg ...string) { Opens(m, "Terminal.app") }},
"monitor": {Help: "监控", Hand: func(m *ice.Message, arg ...string) { Opens(m, "Activity Monitor.app") }},
"docker": {Help: "容器", Hand: func(m *ice.Message, arg ...string) { Opens(m, "Docker Desktop.app") }},
}), Hand: func(m *ice.Message, arg ...string) {
if len(arg) == 0 || arg[0] == "" {
m.Split(m.Cmdx(SYSTEM, "ps", "u")).Sort("COMMAND").PushAction(PROCKILL).StatusTimeCount(m.Cmd(RUNTIME, HOSTINFO).AppendSimple("nCPU,MemTotal,MemFree"))
return
}
m.OptionFields(mdb.DETAIL)
for _, line := range kit.SplitLine(m.Cmdx(nfs.CAT, kit.Format("/proc/%s/status", arg[0]))) {
ls := strings.SplitN(line, nfs.DF, 2)
m.Push(ls[0], ls[1])
}
}},
})
}

View File

@ -1,97 +0,0 @@
package cli
import (
"runtime"
"strings"
"time"
ice "shylinux.com/x/icebergs"
"shylinux.com/x/icebergs/base/aaa"
"shylinux.com/x/icebergs/base/gdb"
"shylinux.com/x/icebergs/base/lex"
"shylinux.com/x/icebergs/base/mdb"
"shylinux.com/x/icebergs/base/nfs"
kit "shylinux.com/x/toolkits"
)
type procstat struct {
utime int64
stime int64
vmsize int64
vmrss int64
user int64
sys int64
idle int64
total int64
free int64
rx int64
tx int64
established int64
time_wait int64
}
func newprocstat(m *ice.Message) (stat procstat) {
if runtime.GOOS != LINUX {
return
}
m.Option(ice.MSG_USERROLE, aaa.ROOT)
if ls := kit.Split(m.Cmdx(nfs.CAT, "/proc/self/stat"), " ()"); len(ls) > 0 {
stat = procstat{utime: kit.Int64(ls[13]), stime: kit.Int64(ls[14]), vmsize: kit.Int64(ls[22]), vmrss: kit.Int64(ls[23]) * 4096}
}
if ls := kit.Split(kit.Select("", strings.Split(m.Cmdx(nfs.CAT, "/proc/stat"), lex.NL), 1)); len(ls) > 0 {
stat.user, stat.sys, stat.idle = kit.Int64(ls[1]), kit.Int64(ls[3]), kit.Int64(ls[4])
}
for _, line := range strings.Split(strings.TrimSpace(m.Cmdx(nfs.CAT, "/proc/meminfo")), lex.NL) {
switch ls := kit.Split(line, ": "); ls[0] {
case "MemTotal":
stat.total = kit.Int64(ls[1]) * 1024
case "MemFree":
stat.free = kit.Int64(ls[1]) * 1024
}
}
for _, line := range strings.Split(strings.TrimSpace(m.Cmdx(nfs.CAT, "/proc/net/dev")), lex.NL)[2:] {
if ls := kit.Split(line, ": "); ls[0] != "lo" {
stat.rx += kit.Int64(ls[1])
stat.tx += kit.Int64(ls[9])
}
}
for _, line := range strings.Split(strings.TrimSpace(m.Cmdx(nfs.CAT, "/proc/net/tcp")), lex.NL)[1:] {
switch ls := kit.Split(line, ": "); ls[5] {
case "01":
stat.established++
case "06":
stat.time_wait++
}
}
return
}
func init() {
var last procstat
Index.MergeCommands(ice.Commands{
PROCSTAT: {Name: "procstat id list page start", Help: "进程统计", Actions: ice.MergeActions(ice.Actions{
ice.CTX_INIT: {Hand: func(m *ice.Message, arg ...string) { last = newprocstat(m) }},
START: {Name: "start interval*=10s least*=360 limit*=720", Hand: func(m *ice.Message, arg ...string) {
m.Cmd(gdb.TIMER, mdb.CREATE, mdb.NAME, m.CommandKey(), gdb.DELAY, "1s", m.OptionSimple(gdb.INTERVAL), mdb.COUNT, "-1", ice.CMD, "cli.procstat insert")
mdb.Config(m, mdb.LEAST, m.Option(mdb.LEAST))
mdb.Config(m, mdb.LIMIT, m.Option(mdb.LIMIT))
}},
mdb.INSERT: {Hand: func(m *ice.Message, arg ...string) {
stat := newprocstat(m)
total := stat.user - last.user + stat.sys - last.sys + stat.idle - last.idle
m.Cmd(mdb.INSERT, m.PrefixKey(), "", mdb.LIST,
"utime", (stat.utime-last.utime+stat.stime-last.stime)*1000/total, "vmrss", stat.vmrss*1000/stat.total,
"user", (stat.user-last.user+stat.sys-last.sys)*1000/total, "idle", (stat.idle-last.idle)*1000/total, "free", stat.free*1000/stat.total,
"rx", (stat.rx-last.rx)*1000/20000000, "tx", (stat.tx-last.tx)*1000/20000000, "established", stat.established, "time_wait", stat.time_wait,
)
last = stat
}},
}, mdb.PageListAction(mdb.FIELD, "time,id,utime,vmrss,user,idle,free,rx,tx,established,time_wait")), Hand: func(m *ice.Message, arg ...string) {
m.OptionDefault(mdb.CACHE_LIMIT, mdb.Config(m, mdb.LEAST))
if mdb.PageListSelect(m, arg...); (len(arg) == 0 || arg[0] == "") && m.Length() > 0 {
m.SortInt(mdb.ID).Display("/plugin/story/trend.js", "view", "折线图", "min", "0", "max", "1000", COLOR, "yellow,cyan,red,green,blue,purple,purple")
m.StatusTime(mdb.TIME, m.Append(mdb.TIME), "span", kit.FmtDuration(time.Duration(kit.Time(m.Time())-kit.Time(m.Append(mdb.TIME)))), m.AppendSimple(mdb.Config(m, mdb.FIELD)), "cursor", "0")
}
}},
})
}

View File

@ -4,9 +4,11 @@ import (
"encoding/base64" "encoding/base64"
ice "shylinux.com/x/icebergs" ice "shylinux.com/x/icebergs"
"shylinux.com/x/icebergs/base/aaa"
"shylinux.com/x/icebergs/base/lex" "shylinux.com/x/icebergs/base/lex"
"shylinux.com/x/icebergs/base/mdb" "shylinux.com/x/icebergs/base/mdb"
"shylinux.com/x/icebergs/base/tcp" "shylinux.com/x/icebergs/base/tcp"
"shylinux.com/x/icebergs/base/web/html"
"shylinux.com/x/icebergs/misc/qrcode" "shylinux.com/x/icebergs/misc/qrcode"
kit "shylinux.com/x/toolkits" kit "shylinux.com/x/toolkits"
) )
@ -35,7 +37,7 @@ func _qrcode_web(m *ice.Message, text string) string {
sc.ForegroundColor = ParseColor(m.Option(FG)) sc.ForegroundColor = ParseColor(m.Option(FG))
sc.BackgroundColor = ParseColor(m.Option(BG)) sc.BackgroundColor = ParseColor(m.Option(BG))
if data, err := sc.PNG(kit.Int(m.Option(SIZE))); m.Assert(err) { if data, err := sc.PNG(kit.Int(m.Option(SIZE))); m.Assert(err) {
m.Echo(`<img src="data:image/png;base64,%s" title='%s'>`, base64.StdEncoding.EncodeToString(data), text) m.Echo(`<img class="qrcode" src="data:image/png;base64,%s" title='%s'>`, base64.StdEncoding.EncodeToString(data), text)
} }
return text return text
} }
@ -47,32 +49,38 @@ const QRCODE = "qrcode"
func init() { func init() {
Index.MergeCommands(ice.Commands{ Index.MergeCommands(ice.Commands{
QRCODE: {Name: "qrcode text fg@key bg@key size auto", Help: "二维码", Actions: ice.Actions{ QRCODE: {Name: "qrcode text fg@key bg@key size auto", Help: "二维码", Icon: "Chess.png", Role: aaa.VOID, Meta: kit.Dict(
ice.CTX_TRANS, kit.Dict(html.INPUT, kit.Dict(mdb.TEXT, "文本", BG, "背景色", FG, "字体色")),
), Actions: ice.MergeActions(ice.Actions{
ice.CTX_INIT: {Hand: func(m *ice.Message, arg ...string) { ice.CTX_INIT: {Hand: func(m *ice.Message, arg ...string) {
ice.AddRender(ice.RENDER_QRCODE, func(m *ice.Message, args ...ice.Any) string { ice.AddRender(ice.RENDER_QRCODE, func(m *ice.Message, args ...ice.Any) string {
if m.IsMobileUA() {
m.Option(SIZE, "280")
}
return m.Cmd(Prefix(QRCODE), kit.Simple(args...)).Result() return m.Cmd(Prefix(QRCODE), kit.Simple(args...)).Result()
}) })
}}, }},
mdb.INPUTS: {Hand: func(m *ice.Message, arg ...string) { mdb.INPUTS: {Hand: func(m *ice.Message, arg ...string) {
switch arg[0] { switch arg[0] {
case FG, BG: case FG, BG:
m.Push(arg[0], BLACK, WHITE) m.Push(arg[0], kit.SortedKey(_color_map))
} }
}}, }},
}, Hand: func(m *ice.Message, arg ...string) { }), Hand: func(m *ice.Message, arg ...string) {
if m.IsCliUA() { if m.IsCliUA() {
m.OptionDefault(FG, BLACK, BG, WHITE) m.OptionDefault(FG, BLACK, BG, WHITE)
_qrcode_cli(m, kit.Select(kit.Select(ice.Info.Make.Domain, ice.Info.Domain), arg, 0)) _qrcode_cli(m, kit.Select(kit.Select(ice.Info.Make.Domain, ice.Info.Domain), arg, 0))
} else { } else {
m.Option(FG, kit.Select(m.Option("--plugin-fg-color"), arg, 1)) // m.OptionDefault(SIZE, kit.Select("360", "280", m.IsMobileUA()))
m.Option(BG, kit.Select(m.Option("--plugin-bg-color"), arg, 2)) m.Option(FG, kit.Select(m.Option(ice.MSG_FG), arg, 1))
m.Option(BG, kit.Select(m.Option(ice.MSG_BG), arg, 2))
m.Option(SIZE, kit.Select(m.OptionDefault(SIZE, "320"), arg, 3))
switch m.Option(ice.MSG_THEME) { switch m.Option(ice.MSG_THEME) {
case LIGHT, WHITE: case LIGHT, WHITE:
m.OptionDefault(FG, BLACK, BG, WHITE) m.OptionDefault(FG, BLACK, BG, WHITE)
default: default:
m.OptionDefault(FG, WHITE, BG, BLACK) m.OptionDefault(FG, WHITE, BG, BLACK)
} }
m.OptionDefault(SIZE, "360")
m.StatusTime(mdb.LINK, _qrcode_web(m, tcp.PublishLocalhost(m, kit.Select(m.Option(ice.MSG_USERWEB), arg, 0)))) m.StatusTime(mdb.LINK, _qrcode_web(m, tcp.PublishLocalhost(m, kit.Select(m.Option(ice.MSG_USERWEB), arg, 0))))
} }
}}, }},

View File

@ -1,43 +0,0 @@
package cli
import (
"debug/elf"
"debug/macho"
"runtime"
"strings"
ice "shylinux.com/x/icebergs"
"shylinux.com/x/icebergs/base/nfs"
kit "shylinux.com/x/toolkits"
)
func init() {
Index.MergeCommands(ice.Commands{
"readelf": {Name: "readelf path=bin/ice.bin auto", Hand: func(m *ice.Message, arg ...string) {
if len(arg) == 0 || strings.HasSuffix(arg[0], nfs.PS) {
m.Cmdy(nfs.DIR, arg)
return
}
if f, e := nfs.OpenFile(m, arg[0]); !m.Warn(e) {
defer f.Close()
buf := make([]byte, 1024)
n, e := f.Read(buf)
if m.Warn(e) {
return
}
switch runtime.GOOS {
case LINUX:
f, _ := elf.Open(arg[0])
m.Echo("%v", kit.Formats(f))
case DARWIN:
f, _ := macho.Open(arg[0])
m.Echo("%v", kit.Formats(f))
}
for i := 0; i < n; i++ {
kit.If(i%16 == 0, func() { m.Push("addr", kit.Format("%04x", i)) })
m.Push(kit.Format("%02x", i%16), kit.Format("%02x", buf[i]))
}
}
}},
})
}

View File

@ -1,7 +1,6 @@
package cli package cli
import ( import (
"bytes"
"os" "os"
"path" "path"
"runtime" "runtime"
@ -11,7 +10,6 @@ import (
ice "shylinux.com/x/icebergs" ice "shylinux.com/x/icebergs"
"shylinux.com/x/icebergs/base/aaa" "shylinux.com/x/icebergs/base/aaa"
"shylinux.com/x/icebergs/base/ctx" "shylinux.com/x/icebergs/base/ctx"
"shylinux.com/x/icebergs/base/gdb"
"shylinux.com/x/icebergs/base/lex" "shylinux.com/x/icebergs/base/lex"
"shylinux.com/x/icebergs/base/mdb" "shylinux.com/x/icebergs/base/mdb"
"shylinux.com/x/icebergs/base/nfs" "shylinux.com/x/icebergs/base/nfs"
@ -21,6 +19,7 @@ import (
func _runtime_init(m *ice.Message) { func _runtime_init(m *ice.Message) {
count := kit.Int(m.Conf(RUNTIME, kit.Keys(BOOT, mdb.COUNT))) count := kit.Int(m.Conf(RUNTIME, kit.Keys(BOOT, mdb.COUNT)))
defer m.Conf(RUNTIME, kit.Keys(BOOT, mdb.COUNT), count+1)
kit.For(kit.UnMarshal(kit.Format(ice.Info.Make)), func(k string, v ice.Any) { m.Conf(RUNTIME, kit.Keys(MAKE, strings.ToLower(k)), v) }) kit.For(kit.UnMarshal(kit.Format(ice.Info.Make)), func(k string, v ice.Any) { m.Conf(RUNTIME, kit.Keys(MAKE, strings.ToLower(k)), v) })
m.Conf(RUNTIME, kit.Keys(HOST, GOARCH), runtime.GOARCH) m.Conf(RUNTIME, kit.Keys(HOST, GOARCH), runtime.GOARCH)
m.Conf(RUNTIME, kit.Keys(HOST, GOOS), runtime.GOOS) m.Conf(RUNTIME, kit.Keys(HOST, GOOS), runtime.GOOS)
@ -29,34 +28,44 @@ func _runtime_init(m *ice.Message) {
m.Conf(RUNTIME, kit.Keys(HOST, PWD), kit.Path("")) m.Conf(RUNTIME, kit.Keys(HOST, PWD), kit.Path(""))
m.Conf(RUNTIME, kit.Keys(HOST, HOME), kit.HomePath("")) m.Conf(RUNTIME, kit.Keys(HOST, HOME), kit.HomePath(""))
m.Conf(RUNTIME, kit.Keys(HOST, MAXPROCS), runtime.GOMAXPROCS(0)) m.Conf(RUNTIME, kit.Keys(HOST, MAXPROCS), runtime.GOMAXPROCS(0))
kit.For(ENV_LIST, func(k string) { ice.Info.System = m.Conf(RUNTIME, kit.Keys(HOST, OSID))
m.Conf(RUNTIME, kit.Keys(CONF, k), kit.Env(k)) kit.For(ENV_LIST, func(k string) { m.Conf(RUNTIME, kit.Keys(CONF, k), kit.Env(k)) })
kit.If(k == CTX_PID, func() { ice.Info.PidPath = kit.Env(k) }) ice.Info.Lang = m.Conf(RUNTIME, kit.Keys(CONF, LANG))
}) m.Conf(RUNTIME, kit.Keys(BOOT, USERNAME), kit.UserName())
m.Conf(RUNTIME, kit.Keys(BOOT, HOSTNAME), kit.Env("HOSTNAME")) m.Conf(RUNTIME, kit.Keys(BOOT, HOSTNAME), kit.Env("HOSTNAME"))
m.Conf(RUNTIME, kit.Keys(BOOT, PATHNAME), path.Base(kit.Path("")))
if name, e := os.Hostname(); e == nil && name != "" { if name, e := os.Hostname(); e == nil && name != "" {
m.Conf(RUNTIME, kit.Keys(BOOT, HOSTNAME), name) m.Conf(RUNTIME, kit.Keys(BOOT, HOSTNAME), name)
} }
m.Conf(RUNTIME, kit.Keys(BOOT, PATHNAME), path.Base(kit.Path(""))) ice.Info.Username = m.Conf(RUNTIME, kit.Keys(BOOT, USERNAME))
m.Conf(RUNTIME, kit.Keys(BOOT, USERNAME), kit.UserName())
ice.Info.Hostname = m.Conf(RUNTIME, kit.Keys(BOOT, HOSTNAME)) ice.Info.Hostname = m.Conf(RUNTIME, kit.Keys(BOOT, HOSTNAME))
ice.Info.Pathname = m.Conf(RUNTIME, kit.Keys(BOOT, PATHNAME)) ice.Info.Pathname = m.Conf(RUNTIME, kit.Keys(BOOT, PATHNAME))
ice.Info.Username = m.Conf(RUNTIME, kit.Keys(BOOT, USERNAME)) kit.HashSeed = append(kit.HashSeed, ice.Info.Username)
ice.Info.System = m.Conf(RUNTIME, kit.Keys(HOST, OSID)) kit.HashSeed = append(kit.HashSeed, ice.Info.Hostname)
aaa.UserRoot(ice.Pulse, "", ice.Info.Username, aaa.ROOT, ice.OPS) kit.HashSeed = append(kit.HashSeed, ice.Info.Pathname)
aaa.UserRoot(ice.Pulse, "", ice.Info.Make.Username, aaa.TECH, ice.DEV) aaa.UserRoot(ice.Pulse, aaa.TECH, ice.Info.Make.Author, "", "", ice.DEV, ice.Info.Make.Email)
aaa.UserRoot(ice.Pulse, aaa.TECH, ice.Info.Make.Username, "", "", ice.DEV, ice.Info.Make.Email)
aaa.UserRoot(ice.Pulse, aaa.ROOT, ice.Info.Username)
aaa.UserRoot(ice.Pulse, aaa.ROOT, aaa.ROOT)
ice.Info.Time = m.Time()
m.Conf(RUNTIME, kit.Keys(BOOT, mdb.TIME), ice.Info.Time)
if runtime.GOARCH != MIPSLE { if runtime.GOARCH != MIPSLE {
msg := m.Cmd(nfs.DIR, _system_find(m, os.Args[0]), "time,path,size,hash") msg := m.Cmd(nfs.DIR, _system_find(m, os.Args[0]), "time,path,size,hash")
m.Conf(RUNTIME, kit.Keys(BOOT, mdb.TIME), msg.Append(mdb.TIME))
m.Conf(RUNTIME, kit.Keys(BOOT, mdb.HASH), msg.Append(mdb.HASH)) m.Conf(RUNTIME, kit.Keys(BOOT, mdb.HASH), msg.Append(mdb.HASH))
m.Conf(RUNTIME, kit.Keys(BOOT, nfs.SIZE), msg.Append(nfs.SIZE)) m.Conf(RUNTIME, kit.Keys(BOOT, nfs.SIZE), msg.Append(nfs.SIZE))
m.Conf(RUNTIME, kit.Keys(BOOT, ice.BIN), msg.Append(nfs.PATH)) m.Conf(RUNTIME, kit.Keys(BOOT, ice.BIN), msg.Append(nfs.PATH))
ice.Info.Hash = msg.Append(mdb.HASH) ice.Info.Hash = msg.Append(mdb.HASH)
ice.Info.Size = msg.Append(nfs.SIZE) ice.Info.Size = msg.Append(nfs.SIZE)
} }
m.Conf(RUNTIME, kit.Keys(BOOT, mdb.COUNT), count+1) nfs.Exists(m, "/proc/meminfo", func(p string) {
m.Conf(RUNTIME, mdb.META, "") kit.For(kit.SplitLine(m.Cmdx(nfs.CAT, p)), func(p string) {
m.Conf(RUNTIME, mdb.HASH, "") switch ls := kit.Split(p, ": "); kit.Select("", ls, 0) {
case "MemTotal", "MemFree", "MemAvailable":
m.Conf(RUNTIME, kit.Keys(HOST, ls[0]), kit.FmtSize(kit.Int(ls[1])*1024))
}
})
})
m.Conf(m.PrefixKey(), mdb.META, "")
} }
func _runtime_hostinfo(m *ice.Message) { func _runtime_hostinfo(m *ice.Message) {
m.Push("time", ice.Info.Make.Time) m.Push("time", ice.Info.Make.Time)
@ -65,9 +74,15 @@ func _runtime_hostinfo(m *ice.Message) {
m.Push("NumGoroutine", runtime.NumGoroutine()) m.Push("NumGoroutine", runtime.NumGoroutine())
var stats runtime.MemStats var stats runtime.MemStats
runtime.ReadMemStats(&stats) runtime.ReadMemStats(&stats)
m.Push("Sys", kit.FmtSize(int64(stats.Sys))) m.Push("Sys", kit.FmtSize(stats.Sys))
m.Push("Alloc", kit.FmtSize(int64(stats.Alloc))) m.Push("Alloc", kit.FmtSize(stats.Alloc))
m.Push("Objects", stats.HeapObjects) m.Push("TotalAlloc", kit.FmtSize(stats.TotalAlloc))
m.Push("StackSys", kit.FmtSize(stats.StackSys))
m.Push("StackInuse", kit.FmtSize(stats.StackInuse))
m.Push("HeapSys", kit.FmtSize(stats.HeapSys))
m.Push("HeapInuse", kit.FmtSize(stats.HeapInuse))
m.Push("HeapIdle", kit.FmtSize(stats.HeapIdle))
m.Push("HeapReleased", kit.FmtSize(stats.HeapReleased))
m.Push("NumGC", stats.NumGC) m.Push("NumGC", stats.NumGC)
m.Push("LastGC", time.Unix(int64(stats.LastGC)/int64(time.Second), int64(stats.LastGC)%int64(time.Second))) m.Push("LastGC", time.Unix(int64(stats.LastGC)/int64(time.Second), int64(stats.LastGC)%int64(time.Second)))
m.Push("uptime", kit.Split(m.Cmdx(SYSTEM, "uptime"), mdb.FS)[0]) m.Push("uptime", kit.Split(m.Cmdx(SYSTEM, "uptime"), mdb.FS)[0])
@ -86,7 +101,7 @@ func _runtime_hostinfo(m *ice.Message) {
} }
} }
func _runtime_diskinfo(m *ice.Message) { func _runtime_diskinfo(m *ice.Message) {
m.Spawn().Split(kit.Replace(m.Cmdx(SYSTEM, "df", "-h"), "Mounted on", "Mountedon"), "", lex.SP, lex.NL).Table(func(index int, value ice.Maps, head []string) { m.Spawn().Split(kit.Replace(m.Cmdx(SYSTEM, "df", "-h"), "Mounted on", "Mountedon"), "", lex.SP, lex.NL).Table(func(value ice.Maps, index int, head []string) {
kit.If(strings.HasPrefix(value["Filesystem"], "/dev"), func() { m.Push("", value, head) }) kit.If(strings.HasPrefix(value["Filesystem"], "/dev"), func() { m.Push("", value, head) })
}) })
m.RenameAppend("%iused", "piused", "Use%", "Usep") m.RenameAppend("%iused", "piused", "Use%", "Usep")
@ -112,7 +127,16 @@ const (
LINUX = "linux" LINUX = "linux"
MACOS = "macos" MACOS = "macos"
DARWIN = "darwin" DARWIN = "darwin"
WINDOWS = ice.WINDOWS WINDOWS = "windows"
COMMIT_TIME = "commitTime"
COMPILE_TIME = "compileTime"
BOOT_TIME = "bootTime"
KERNEL = "kernel"
ARCH = "arch"
CPU = "cpu"
OS = "os"
) )
const ( const (
PATH = "PATH" PATH = "PATH"
@ -124,32 +148,37 @@ const (
TZ = "TZ" TZ = "TZ"
) )
const ( const (
CTX_SHY = "ctx_shy" CTX_SHY = "ctx_shy"
CTX_COM = "ctx_com" CTX_DEV = "ctx_dev"
CTX_HUB = "ctx_hub" CTX_DEV_IP = "ctx_dev_ip"
CTX_DEV = "ctx_dev" CTX_OPS = "ctx_ops"
CTX_OPS = "ctx_ops" CTX_REPOS = "ctx_repos"
CTX_NAME = "ctx_name"
CTX_DEMO = "ctx_demo"
CTX_MAIL = "ctx_mail"
CTX_ROOT = "ctx_root"
CTX_DOMAIN = "ctx_domain"
CTX_PID = "ctx_pid" CTX_PID = "ctx_pid"
CTX_LOG = "ctx_log" CTX_LOG = "ctx_log"
CTX_POD = "ctx_pod" CTX_POD = "ctx_pod"
CTX_ENV = "ctx_env" CTX_ENV = "ctx_env"
CTX_CLI = "ctx_cli"
CTX_ARG = "ctx_arg"
) )
var ENV_LIST = []string{TZ, LANG, TERM, SHELL, CTX_SHY, CTX_HUB, CTX_COM, CTX_DEV, CTX_OPS, CTX_PID} var ENV_LIST = []string{TZ, LANG, TERM, SHELL, CTX_SHY, CTX_DEV, CTX_OPS, CTX_DEMO, CTX_MAIL, CTX_ROOT, CTX_PID}
const ( const (
USERNAME = "username"
HOSTNAME = "hostname" HOSTNAME = "hostname"
PATHNAME = "pathname" PATHNAME = "pathname"
USERNAME = "username"
) )
const ( const (
IFCONFIG = "ifconfig" IFCONFIG = "ifconfig"
DISKINFO = "diskinfo" DISKINFO = "diskinfo"
HOSTINFO = "hostinfo" HOSTINFO = "hostinfo"
USERINFO = "userinfo" USERINFO = "userinfo"
PROCSTAT = "procstat"
PROCINFO = "procinfo"
PROCKILL = "prockill"
BOOTINFO = "bootinfo" BOOTINFO = "bootinfo"
MAXPROCS = "maxprocs" MAXPROCS = "maxprocs"
) )
@ -157,35 +186,29 @@ const RUNTIME = "runtime"
func init() { func init() {
Index.MergeCommands(ice.Commands{ Index.MergeCommands(ice.Commands{
RUNTIME: {Name: "runtime info=bootinfo,ifconfig,diskinfo,hostinfo,userinfo,procstat,procinfo,bootinfo,role,api,cli,cmd,mod,env,path,chain,routine auto upgrade restart reboot logs conf", Icon: "Infomation.png", Help: "运行环境", Actions: ice.MergeActions(ice.Actions{ RUNTIME: {Name: "runtime info=bootinfo,ifconfig,diskinfo,hostinfo,userinfo,bootinfo,role,api,cli,cmd,mod,env,path,chain auto upgrade reboot lock", Icon: "Infomation.png", Help: "环境", Actions: ice.MergeActions(ice.Actions{
ice.CTX_INIT: {Hand: func(m *ice.Message, arg ...string) { ice.CTX_INIT: {Hand: func(m *ice.Message, arg ...string) { _runtime_init(m) }},
aaa.White(m, ice.LICENSE) IFCONFIG: {Hand: func(m *ice.Message, arg ...string) { m.Cmdy(tcp.HOST) }},
_runtime_init(m) DISKINFO: {Hand: func(m *ice.Message, arg ...string) { _runtime_diskinfo(m) }},
}}, HOSTINFO: {Hand: func(m *ice.Message, arg ...string) { _runtime_hostinfo(m) }},
IFCONFIG: {Hand: func(m *ice.Message, arg ...string) { m.Cmdy(tcp.HOST) }},
DISKINFO: {Hand: func(m *ice.Message, arg ...string) { _runtime_diskinfo(m) }},
HOSTINFO: {Hand: func(m *ice.Message, arg ...string) { _runtime_hostinfo(m) }},
HOSTNAME: {Hand: func(m *ice.Message, arg ...string) { HOSTNAME: {Hand: func(m *ice.Message, arg ...string) {
if len(arg) > 0 { if len(arg) > 0 {
ice.Info.Hostname = mdb.Conf(m, RUNTIME, kit.Keys(NODE, mdb.NAME), mdb.Conf(m, RUNTIME, kit.Keys(BOOT, HOSTNAME), arg[0])) ice.Info.Hostname = mdb.Conf(m, RUNTIME, kit.Keys(NODE, mdb.NAME), mdb.Conf(m, RUNTIME, kit.Keys(BOOT, HOSTNAME), arg[0]))
} }
m.Echo(ice.Info.Hostname) m.Echo(ice.Info.Hostname)
}}, }},
USERINFO: {Hand: func(m *ice.Message, arg ...string) { m.Split(m.Cmdx(SYSTEM, "who"), "user term time") }},
PROCSTAT: {Hand: func(m *ice.Message, arg ...string) { m.Cmdy(PROCSTAT) }},
PROCINFO: {Hand: func(m *ice.Message, arg ...string) { m.Cmdy(PROCINFO) }},
PROCKILL: {Help: "结束进程", Hand: func(m *ice.Message, arg ...string) { m.Cmdy(gdb.SIGNAL, gdb.STOP, m.Option("PID")).ProcessRefresh() }},
MAXPROCS: {Hand: func(m *ice.Message, arg ...string) { MAXPROCS: {Hand: func(m *ice.Message, arg ...string) {
kit.If(len(arg) > 0, func() { runtime.GOMAXPROCS(kit.Int(mdb.Conf(m, RUNTIME, kit.Keys(HOST, MAXPROCS), arg[0]))) }) kit.If(len(arg) > 0, func() { runtime.GOMAXPROCS(kit.Int(mdb.Conf(m, RUNTIME, kit.Keys(HOST, MAXPROCS), arg[0]))) })
m.Echo("%d", runtime.GOMAXPROCS(0)) m.Echo("%d", runtime.GOMAXPROCS(0))
}}, }},
USERINFO: {Hand: func(m *ice.Message, arg ...string) { m.Split(m.Cmdx(SYSTEM, "who"), "user term time") }},
aaa.ROLE: {Hand: func(m *ice.Message, arg ...string) { aaa.ROLE: {Hand: func(m *ice.Message, arg ...string) {
m.Cmd(aaa.ROLE, func(value ice.Maps) { m.Push(mdb.KEY, kit.Keys(value[aaa.ROLE], value[mdb.ZONE], value[mdb.KEY])) }) m.Cmd(aaa.ROLE, func(value ice.Maps) { m.Push(mdb.KEY, kit.Keys(value[aaa.ROLE], value[mdb.ZONE], value[mdb.KEY])) })
ctx.DisplayStorySpide(m.Options(nfs.DIR_ROOT, "ice."), mdb.FIELD, mdb.KEY, lex.SPLIT, nfs.PT) ctx.DisplayStorySpide(m.Options(nfs.DIR_ROOT, "ice."), mdb.FIELD, mdb.KEY, lex.SPLIT, nfs.PT)
}}, }},
API: {Hand: func(m *ice.Message, arg ...string) { API: {Hand: func(m *ice.Message, arg ...string) {
if len(arg) > 1 { if len(arg) > 1 {
m.Cmdy(ctx.COMMAND, "web.code.inner").Push(ctx.ARGS, kit.Format(nfs.SplitPath(m, m.Option(nfs.FILE)))) m.Cmdy(ctx.COMMAND, "inner").Push(ctx.ARGS, kit.Format(nfs.SplitPath(m, m.Option(nfs.FILE))))
return return
} }
ctx.DisplayStorySpide(m.Options(nfs.DIR_ROOT, nfs.PS), lex.PREFIX, kit.Fields(ctx.ACTION, m.ActionKey())) ctx.DisplayStorySpide(m.Options(nfs.DIR_ROOT, nfs.PS), lex.PREFIX, kit.Fields(ctx.ACTION, m.ActionKey()))
@ -194,7 +217,7 @@ func init() {
}}, }},
CLI: {Hand: func(m *ice.Message, arg ...string) { CLI: {Hand: func(m *ice.Message, arg ...string) {
if len(arg) > 1 { if len(arg) > 1 {
m.Cmdy(ctx.COMMAND, "web.code.inner").Push(ctx.ARGS, kit.Format(nfs.SplitPath(m, m.Option(nfs.FILE)))) m.Cmdy(ctx.COMMAND, "inner").Push(ctx.ARGS, kit.Format(nfs.SplitPath(m, m.Option(nfs.FILE))))
return return
} }
ctx.DisplayStorySpide(m.Options(nfs.DIR_ROOT, "ice."), lex.PREFIX, kit.Fields(ctx.ACTION, m.ActionKey()), mdb.FIELD, mdb.NAME, lex.SPLIT, nfs.PT) ctx.DisplayStorySpide(m.Options(nfs.DIR_ROOT, "ice."), lex.PREFIX, kit.Fields(ctx.ACTION, m.ActionKey()), mdb.FIELD, mdb.NAME, lex.SPLIT, nfs.PT)
@ -209,66 +232,37 @@ func init() {
kit.For(ice.Info.Gomod, func(k string, v string) { m.Push(nfs.MODULE, k).Push(nfs.VERSION, v) }) kit.For(ice.Info.Gomod, func(k string, v string) { m.Push(nfs.MODULE, k).Push(nfs.VERSION, v) })
}}, }},
ENV: {Hand: func(m *ice.Message, arg ...string) { ENV: {Hand: func(m *ice.Message, arg ...string) {
kit.For(os.Environ(), func(v string) { kit.For(os.Environ(), func(v string) { ls := strings.SplitN(v, mdb.EQ, 2); m.Push(mdb.NAME, ls[0]).Push(mdb.VALUE, ls[1]) })
ls := strings.SplitN(v, mdb.EQ, 2)
m.Push(mdb.NAME, ls[0]).Push(mdb.VALUE, ls[1])
})
m.Sort(mdb.NAME) m.Sort(mdb.NAME)
}}, }},
nfs.PATH: {Hand: func(m *ice.Message, arg ...string) { nfs.PATH: {Hand: func(m *ice.Message, arg ...string) {
kit.For(_path_split(os.Getenv(PATH)), func(p string) { m.Push(nfs.PATH, p) }) kit.For(_path_split(os.Getenv(PATH)), func(p string) { m.Push(nfs.PATH, p) })
}}, }},
"chain": {Hand: func(m *ice.Message, arg ...string) { m.Echo(m.FormatChain()) }}, "chain": {Hand: func(m *ice.Message, arg ...string) { m.Echo(m.FormatChain()) }},
"routine": {Hand: func(m *ice.Message, arg ...string) {
status := map[string]int{}
buf := make([]byte, 4096*4096)
runtime.Stack(buf, true)
outer:
for _, v := range bytes.Split(buf, []byte(lex.NL+lex.NL)) {
ls := bytes.Split(v, []byte(lex.NL))
if ls := strings.SplitN(string(ls[0]), " ", 3); len(ls) > 0 {
m.Push(mdb.ID, ls[1]).Push(mdb.STATUS, ls[2])
status[kit.Split(string(ls[2]), " []:")[0]]++
}
for i := 1; i < len(ls); i += 2 {
if bytes.HasPrefix(ls[i], []byte("shylinux.com/x/")) {
m.Push(nfs.PATH, kit.TrimPath(string(ls[i+1]))).Push("func", string(ls[i]))
continue outer
}
}
m.Push(nfs.PATH, kit.TrimPath(string(ls[2]))).Push("func", string(ls[1]))
}
var stats runtime.MemStats
runtime.ReadMemStats(&stats)
m.StatusTimeCount(status, "GOMAXPROCS", runtime.GOMAXPROCS(0), "NumGC", stats.NumGC, "Alloc", kit.FmtSize(int64(stats.Alloc)), "Sys", kit.FmtSize(int64(stats.Sys)))
m.Echo("%v", string(buf))
}},
"upgrade": {Help: "升级", Hand: func(m *ice.Message, arg ...string) { "upgrade": {Help: "升级", Hand: func(m *ice.Message, arg ...string) {
if nfs.Exists(m, ".git") { if nfs.Exists(m, ice.SRC_MAIN_GO) && nfs.Exists(m, ".git") && SystemFind(m, "go") != "" {
m.Cmdy("web.code.compile") m.Cmdy("vimer", "compile")
} else if nfs.Exists(m, ice.BIN_ICE_BIN) {
m.Cmdy("upgrade")
} else { } else {
m.Cmdy("web.code.upgrade") m.Cmdy("", REBOOT)
} }
}}, }},
RESTART: {Help: "重启", Hand: func(m *ice.Message, arg ...string) { REBOOT: {Help: "重启", Hand: func(m *ice.Message, arg ...string) {
m.Go(func() { m.Sleep30ms(ice.EXIT, 1) }) m.Go(func() { m.Sleep30ms(ice.EXIT, 1) })
}}, }},
"reboot": {Help: "清空", Hand: func(m *ice.Message, arg ...string) { "lock": {Help: "锁屏", Icon: "bi bi-file-lock", Hand: func(m *ice.Message, arg ...string) {
m.Cmd(SYSTEM, "git", "stash") switch runtime.GOOS {
m.Go(func() { m.Sleep30ms(ice.QUIT, 1) }) case DARWIN:
}}, TellApp(m, "System Events", `keystroke "q" using {control down, command down}`)
"logs": {Help: "日志", Hand: func(m *ice.Message, arg ...string) { }
OpenCmds(m, kit.Format("cd %s", kit.Path("")), "tail -f var/log/bench.log")
}},
"conf": {Help: "配置", Hand: func(m *ice.Message, arg ...string) {
OpenCmds(m, kit.Format("cd %s", kit.Path("")), "vim etc/init.shy")
}}, }},
}, ctx.ConfAction("")), Hand: func(m *ice.Message, arg ...string) { }, ctx.ConfAction("")), Hand: func(m *ice.Message, arg ...string) {
kit.If(len(arg) > 0 && arg[0] == BOOTINFO, func() { arg = arg[1:] }) kit.If(len(arg) > 0 && arg[0] == BOOTINFO, func() { arg = arg[1:] })
m.Cmdy(ctx.CONFIG, RUNTIME, arg).StatusTime(mdb.TIME, ice.Info.Make.Time, m.Cmdy(ctx.CONFIG, RUNTIME, arg).StatusTime(mdb.TIME, ice.Info.Make.Time,
mdb.HASH, kit.Cut(ice.Info.Hash, 6), nfs.SIZE, ice.Info.Size, mdb.HASH, kit.Cut(ice.Info.Hash, 6), nfs.SIZE, ice.Info.Size,
mdb.NAME, ice.Info.NodeName, nfs.VERSION, ice.Info.Make.Versions(), mdb.NAME, ice.Info.NodeName, nfs.VERSION, ice.Info.Make.Versions(),
).Option(ice.MSG_ACTION, "") ).Action()
ctx.DisplayStoryJSON(m) ctx.DisplayStoryJSON(m)
}}, }},
}) })
@ -277,5 +271,37 @@ func NodeInfo(m *ice.Message, arg ...string) {
mdb.Conf(m, RUNTIME, kit.Keys(NODE, mdb.TIME), m.Time()) mdb.Conf(m, RUNTIME, kit.Keys(NODE, mdb.TIME), m.Time())
ice.Info.NodeName = mdb.Conf(m, RUNTIME, kit.Keys(NODE, mdb.NAME), kit.Select(ice.Info.NodeName, arg, 0)) ice.Info.NodeName = mdb.Conf(m, RUNTIME, kit.Keys(NODE, mdb.NAME), kit.Select(ice.Info.NodeName, arg, 0))
ice.Info.NodeType = mdb.Conf(m, RUNTIME, kit.Keys(NODE, mdb.TYPE), kit.Select(ice.Info.NodeType, arg, 1)) ice.Info.NodeType = mdb.Conf(m, RUNTIME, kit.Keys(NODE, mdb.TYPE), kit.Select(ice.Info.NodeType, arg, 1))
ice.Info.NodeIcon = mdb.Conf(m, RUNTIME, kit.Keys(NODE, mdb.ICON), kit.Select(ice.Info.NodeIcon, arg, 2))
} }
func IsWindows() bool { return runtime.GOOS == WINDOWS } func IsWindows() bool { return runtime.GOOS == WINDOWS }
func ParseMake(str string) []string {
res := kit.UnMarshal(str)
data := kit.Value(res, MAKE)
version := kit.Format(kit.Value(data, nfs.VERSION))
if kit.Format(kit.Value(data, "forword")) != "0" {
version = kit.Join(kit.TrimArg(kit.Simple(
kit.Select("v0.0.0", kit.Format(kit.Value(data, nfs.VERSION))),
kit.Select("0", kit.Format(kit.Value(data, "forword"))),
kit.Cut(kit.Format(kit.Value(data, mdb.HASH)), 6),
)...), "-")
}
return kit.Simple(
mdb.TIME, kit.Format(kit.Value(data, mdb.TIME)),
ice.SPACE, kit.Format(kit.Value(res, kit.Keys(NODE, mdb.NAME))),
nfs.MODULE, kit.Format(kit.Value(data, nfs.MODULE)),
nfs.VERSION, version,
COMMIT_TIME, kit.Format(kit.Value(data, "when")),
COMPILE_TIME, kit.Format(kit.Value(data, mdb.TIME)),
BOOT_TIME, kit.Format(kit.Value(res, kit.Keys(BOOT, mdb.TIME))),
SHELL, kit.Format(kit.Value(res, kit.Keys(CONF, SHELL))),
KERNEL, kit.Format(kit.Value(res, kit.Keys(HOST, GOOS))),
ARCH, kit.Format(kit.Value(res, kit.Keys(HOST, GOARCH))),
)
}
func SimpleMake() []string {
return []string{
nfs.MODULE, ice.Info.Make.Module, nfs.VERSION, ice.Info.Make.Versions(),
COMMIT_TIME, ice.Info.Make.When, COMPILE_TIME, ice.Info.Make.Time, BOOT_TIME, ice.Info.Time,
KERNEL, runtime.GOOS, ARCH, runtime.GOARCH,
}
}

12
base/cli/sudo.go Normal file
View File

@ -0,0 +1,12 @@
package cli
import (
ice "shylinux.com/x/icebergs"
"shylinux.com/x/icebergs/base/mdb"
)
func init() {
Index.MergeCommands(ice.Commands{
SUDO: {Actions: mdb.HashAction(mdb.SHORT, "cmd", mdb.FIELD, "time,cmd")},
})
}

View File

@ -4,6 +4,7 @@ import (
"bytes" "bytes"
"io" "io"
"net/http" "net/http"
"os"
"os/exec" "os/exec"
"path" "path"
"strings" "strings"
@ -51,14 +52,21 @@ func _system_cmd(m *ice.Message, arg ...string) *exec.Cmd {
m.Logs(FIND, "mirrors cmd", bin) m.Logs(FIND, "mirrors cmd", bin)
} }
} }
cmd := exec.Command(kit.Select(arg[0], bin), arg[1:]...) arg[0] = kit.Select(arg[0], bin)
if m.Cmd(SUDO, arg[0]).Length() > 0 {
m.Logs(FIND, "sudo cmd", arg[0])
arg = kit.Simple(SUDO, arg)
}
cmd := exec.Command(arg[0], arg[1:]...)
if cmd.Dir = kit.TrimPath(m.Option(CMD_DIR)); len(cmd.Dir) > 0 { if cmd.Dir = kit.TrimPath(m.Option(CMD_DIR)); len(cmd.Dir) > 0 {
if m.Logs(EXEC, CMD_DIR, cmd.Dir); !nfs.Exists(m, cmd.Dir) { if m.Logs(EXEC, CMD_DIR, cmd.Dir); !nfs.Exists(m, cmd.Dir) {
file.MkdirAll(cmd.Dir, ice.MOD_DIR) file.MkdirAll(cmd.Dir, ice.MOD_DIR)
} }
} }
kit.For(env, func(k, v string) { cmd.Env = append(cmd.Env, kit.Format("%s=%s", k, v)) }) kit.For(env, func(k, v string) { cmd.Env = append(cmd.Env, kit.Format("%s=%s", k, v)) })
kit.If(len(cmd.Env) > 0 && m.IsDebug(), func() { m.Logs(EXEC, CMD_ENV, kit.Format(cmd.Env)) })
kit.If(len(cmd.Env) > 0, func() { m.Logs(EXEC, CMD_ENV, kit.Format(cmd.Env)) }) kit.If(len(cmd.Env) > 0, func() { m.Logs(EXEC, CMD_ENV, kit.Format(cmd.Env)) })
_system_cmds(m, cmd, arg...)
return cmd return cmd
} }
func _system_out(m *ice.Message, out string) io.Writer { func _system_out(m *ice.Message, out string) io.Writer {
@ -90,10 +98,12 @@ func _system_exec(m *ice.Message, cmd *exec.Cmd) {
if m.Echo(out.String()).Echo(err.String()); m.IsErr() { if m.Echo(out.String()).Echo(err.String()); m.IsErr() {
m.Option(ice.MSG_ARGS, kit.Simple(http.StatusBadRequest, cmd.Args, err.String())) m.Option(ice.MSG_ARGS, kit.Simple(http.StatusBadRequest, cmd.Args, err.String()))
m.Echo(strings.TrimRight(err.String(), lex.NL)) m.Echo(strings.TrimRight(err.String(), lex.NL))
m.Info("err: %v", err.String())
m.Info("out: %v", out.String())
} }
}() }()
} }
if e := cmd.Run(); !m.Warn(e, ice.ErrNotValid, cmd.Args) { if e := cmd.Run(); !m.WarnNotValid(e, cmd.Args) {
m.Cost(CODE, _system_code(cmd), EXEC, cmd.Args) m.Cost(CODE, _system_code(cmd), EXEC, cmd.Args)
} }
m.Push(mdb.TIME, m.Time()).Push(CODE, _system_code(cmd)).StatusTime() m.Push(mdb.TIME, m.Time()).Push(CODE, _system_code(cmd)).StatusTime()
@ -104,19 +114,16 @@ func _system_code(cmd *exec.Cmd) string {
func _system_find(m *ice.Message, bin string, dir ...string) string { func _system_find(m *ice.Message, bin string, dir ...string) string {
if strings.Contains(bin, nfs.DF) { if strings.Contains(bin, nfs.DF) {
return bin return bin
} } else if strings.HasPrefix(bin, nfs.PS) {
if strings.HasPrefix(bin, nfs.PS) {
return bin return bin
} } else if strings.HasPrefix(bin, nfs.PWD) {
if strings.HasPrefix(bin, nfs.PWD) {
return bin return bin
} }
kit.If(len(dir) == 0, func() { dir = append(dir, _path_split(kit.Env(PATH))...) }) kit.If(len(dir) == 0, func() { dir = append(dir, _path_split(kit.Env(PATH))...) })
for _, p := range dir { for _, p := range dir {
if nfs.Exists(m, path.Join(p, bin)) { if nfs.Exists(m, path.Join(p, bin)) {
return kit.Path(p, bin) return kit.Path(p, bin)
} } else if IsWindows() && nfs.Exists(m, path.Join(p, bin)+".exe") {
if IsWindows() && nfs.Exists(m, path.Join(p, bin)+".exe") {
return kit.Path(p, bin) + ".exe" return kit.Path(p, bin) + ".exe"
} }
} }
@ -127,6 +134,12 @@ func _system_find(m *ice.Message, bin string, dir ...string) string {
} }
const ( const (
TIME_300ms = "300ms"
TIME_30ms = "30ms"
TIME_30s = "30s"
TIME_3s = "3s"
TIME_1s = "1s"
CMD_DIR = "cmd_dir" CMD_DIR = "cmd_dir"
CMD_ENV = "cmd_env" CMD_ENV = "cmd_env"
@ -137,15 +150,39 @@ const (
CMD_ERR = "cmd_err" CMD_ERR = "cmd_err"
CMD_OUT = "cmd_out" CMD_OUT = "cmd_out"
MAN = "man"
RUN = "run" RUN = "run"
KILL = "kill"
FIND = "find"
GREP = "grep"
EXEC = "exec"
ECHO = "echo"
REST = "rest" REST = "rest"
PARAM = "param"
OPENS = "opens" OPENS = "opens"
RELAY = "relay"
)
const (
SH = "sh"
LN = "ln"
CP = "cp"
MV = "mv"
RM = "rm"
CD = "cd"
CAT = "cat"
FIND = "find"
GREP = "grep"
TAIL = "tail"
WGET = "wget"
CURL = "curl"
SUDO = "sudo"
EXEC = "exec"
EXIT = "exit"
ECHO = "echo"
KILL = "kill"
GO = "go"
GOTAGS = "gotags"
GIT = "git"
MAN = "man"
YUM = "yum"
) )
const SYSTEM = "system" const SYSTEM = "system"
@ -167,28 +204,35 @@ func init() {
m.Echo(SystemCmds(m, "man %s %s|col -b", kit.Select("", arg[1], arg[1] != "1"), arg[0])) m.Echo(SystemCmds(m, "man %s %s|col -b", kit.Select("", arg[1], arg[1] != "1"), arg[0]))
}}, }},
OPENS: {Hand: func(m *ice.Message, arg ...string) { Opens(m, arg...) }}, OPENS: {Hand: func(m *ice.Message, arg ...string) { Opens(m, arg...) }},
}, mdb.HashAction(mdb.SHORT, CMD, mdb.FIELD, "time,cmd,arg")), Hand: func(m *ice.Message, arg ...string) { }), Hand: func(m *ice.Message, arg ...string) {
if len(arg) == 0 { if _system_exec(m, _system_cmd(m, arg...)); IsSuccess(m) && m.Append(CMD_ERR) == "" {
mdb.HashSelect(m)
} else if _system_exec(m, _system_cmd(m, arg...)); IsSuccess(m) && m.Append(CMD_ERR) == "" {
m.SetAppend() m.SetAppend()
} }
}}, }},
}) })
ice.Info.SystemCmd = func(m *ice.Message, arg ...ice.Any) *ice.Message {
msg := m.Cmd(append([]ice.Any{SYSTEM}, arg...)...)
if m.Warn(!IsSuccess(msg), msg.Append(CMD_ERR)) {
}
return msg
}
} }
func SystemFindGit(m *ice.Message) bool { return SystemFind(m, GIT) != "" }
func SystemFindGo(m *ice.Message) bool { return SystemFind(m, GO) != "" }
func SystemFind(m *ice.Message, bin string, dir ...string) string { func SystemFind(m *ice.Message, bin string, dir ...string) string {
dir = append(dir, EtcPath(m)...) dir = append(dir, EtcPath(m)...)
return _system_find(m, bin, append(dir, _path_split(kit.Env(PATH))...)...) return _system_find(m, bin, append(dir, _path_split(kit.Env(PATH))...)...)
} }
func SystemExec(m *ice.Message, arg ...string) string { return strings.TrimSpace(m.Cmdx(SYSTEM, arg)) } func SystemExec(m *ice.Message, arg ...string) string { return strings.TrimSpace(m.Cmdx(SYSTEM, arg)) }
func SystemCmds(m *ice.Message, cmds string, args ...ice.Any) string { func SystemCmds(m *ice.Message, cmds string, args ...ice.Any) string {
return strings.TrimRight(m.Cmdx(SYSTEM, "sh", "-c", kit.Format(cmds, args...), ice.Option{CMD_OUTPUT, ""}), lex.NL) return strings.TrimRight(m.Cmdx(SYSTEM, SH, "-c", kit.Format(cmds, args...), ice.Option{CMD_OUTPUT, ""}), lex.NL)
} }
func IsSuccess(m *ice.Message) bool { return m.Append(CODE) == "" || m.Append(CODE) == "0" } func IsSuccess(m *ice.Message) bool { return m.Append(CODE) == "" || m.Append(CODE) == "0" }
var _cache_path []string var _cache_path []string
func Shell(m *ice.Message) string { return kit.Select(SH, os.Getenv(SHELL)) }
func EtcPath(m *ice.Message) (res []string) { func EtcPath(m *ice.Message) (res []string) {
if len(_cache_path) > 0 { if len(_cache_path) > 0 {
return _cache_path return _cache_path

11
base/cli/system_darwin.go Normal file
View File

@ -0,0 +1,11 @@
package cli
import (
"os/exec"
ice "shylinux.com/x/icebergs"
)
func _system_cmds(m *ice.Message, cmd *exec.Cmd, arg ...string) *exec.Cmd {
return cmd
}

11
base/cli/system_linux.go Normal file
View File

@ -0,0 +1,11 @@
package cli
import (
"os/exec"
ice "shylinux.com/x/icebergs"
)
func _system_cmds(m *ice.Message, cmd *exec.Cmd, arg ...string) *exec.Cmd {
return cmd
}

View File

@ -0,0 +1,11 @@
package cli
import (
"os/exec"
ice "shylinux.com/x/icebergs"
)
func _system_cmds(m *ice.Message, cmd *exec.Cmd, arg ...string) *exec.Cmd {
return cmd
}

View File

@ -7,9 +7,9 @@ import (
ice "shylinux.com/x/icebergs" ice "shylinux.com/x/icebergs"
"shylinux.com/x/icebergs/base/aaa" "shylinux.com/x/icebergs/base/aaa"
"shylinux.com/x/icebergs/base/lex"
"shylinux.com/x/icebergs/base/mdb" "shylinux.com/x/icebergs/base/mdb"
"shylinux.com/x/icebergs/base/nfs" "shylinux.com/x/icebergs/base/nfs"
"shylinux.com/x/icebergs/base/web/html"
kit "shylinux.com/x/toolkits" kit "shylinux.com/x/toolkits"
) )
@ -17,12 +17,26 @@ func _command_list(m *ice.Message, name string) *ice.Message {
if strings.HasPrefix(name, "can.") { if strings.HasPrefix(name, "can.") {
return m.Push(mdb.INDEX, name).Push(mdb.NAME, name).Push(mdb.HELP, "").Push(mdb.META, "").Push(mdb.LIST, "") return m.Push(mdb.INDEX, name).Push(mdb.NAME, name).Push(mdb.HELP, "").Push(mdb.META, "").Push(mdb.LIST, "")
} }
m.Option(ice.MSG_NODENAME, ice.Info.Titles)
m.Option(ice.MSG_NODEICON, m.Resource(ice.Info.NodeIcon))
m.Spawn(m.Source()).Search(name, func(p *ice.Context, s *ice.Context, key string, cmd *ice.Command) { m.Spawn(m.Source()).Search(name, func(p *ice.Context, s *ice.Context, key string, cmd *ice.Command) {
icon := kit.Format(kit.Value(cmd.Meta, kit.Keys(ice.CTX_ICONS, key)))
icons := kit.Select(cmd.Icon, icon, !kit.HasPrefix(icon, "bi ", "{"))
if icons != "" {
icons = m.Resource(icons)
}
m.Push(mdb.INDEX, kit.Keys(s.Prefix(), key)) m.Push(mdb.INDEX, kit.Keys(s.Prefix(), key))
m.Push(mdb.NAME, kit.Format(cmd.Name)) m.Push(mdb.ICONS, icons)
m.Push(mdb.HELP, kit.Format(cmd.Help)) m.Push(mdb.NAME, kit.Format(cmd.Name)).Push(mdb.HELP, kit.Format(cmd.Help))
m.Push(mdb.META, kit.Format(cmd.Meta)) m.Push(mdb.LIST, kit.Format(cmd.List)).Push(mdb.META, kit.Format(cmd.Meta))
m.Push(mdb.LIST, kit.Format(cmd.List)) m.Push("_command", ShortCmd(kit.Keys(s.Prefix(), key)))
if !nfs.Exists(m, kit.Split(cmd.FileLine(), nfs.DF)[0], func(p string) {
m.Push("_fileline", m.FileURI(p))
}) {
m.Push("_fileline", "")
}
m.Push("_role", kit.Select("", ice.OK, aaa.Right(m.Spawn(), name)))
m.Push("_help", GetCmdHelp(m, name))
}) })
return m return m
} }
@ -31,16 +45,10 @@ func _command_search(m *ice.Message, kind, name, text string) {
if IsOrderCmd(key) || !strings.Contains(s.Prefix(key), name) { if IsOrderCmd(key) || !strings.Contains(s.Prefix(key), name) {
return return
} }
m.PushSearch(ice.CTX, kit.PathName(1), m.PushSearch(ice.CTX, kit.PathName(1), ice.CMD, kit.FileName(1),
ice.CMD, kit.FileName(1),
kit.SimpleKV("", s.Prefix(), kit.Select(key, cmd.Name), cmd.Help), kit.SimpleKV("", s.Prefix(), kit.Select(key, cmd.Name), cmd.Help),
CONTEXT, s.Prefix(), INDEX, kit.Keys(s.Prefix(), key))
COMMAND, key, }).Sort(m.OptionFields())
INDEX, kit.Keys(s.Prefix(), key),
mdb.HELP, cmd.Help,
nfs.FILE, FileURI(cmd.FileLine()))
})
m.Sort(m.OptionFields())
} }
const ( const (
@ -50,6 +58,7 @@ const (
OPTS = "opts" OPTS = "opts"
STYLE = "style" STYLE = "style"
DISPLAY = "display" DISPLAY = "display"
PREVIEW = "preview"
ACTION = "action" ACTION = "action"
TOOLS = "tools" TOOLS = "tools"
RUN = "run" RUN = "run"
@ -58,12 +67,13 @@ const (
ICONS = ice.CTX_ICONS ICONS = ice.CTX_ICONS
TRANS = ice.CTX_TRANS TRANS = ice.CTX_TRANS
TITLE = ice.CTX_TITLE TITLE = ice.CTX_TITLE
INPUT = html.INPUT
) )
const COMMAND = "command" const COMMAND = "command"
func init() { func init() {
Index.MergeCommands(ice.Commands{ Index.MergeCommands(ice.Commands{
COMMAND: {Name: "command key auto", Help: "命令", Actions: ice.MergeActions(ice.Actions{ COMMAND: {Name: "command key auto", Help: "命令", Role: aaa.VOID, Actions: ice.MergeActions(ice.Actions{
ice.CTX_INIT: {Hand: func(m *ice.Message, arg ...string) { ice.CTX_INIT: {Hand: func(m *ice.Message, arg ...string) {
TravelCmd(m, func(key, file, line string) { AddFileCmd(file, key) }) TravelCmd(m, func(key, file, line string) { AddFileCmd(file, key) })
m.Travel(func(p *ice.Context, c *ice.Context, key string, cmd *ice.Command) { m.Travel(func(p *ice.Context, c *ice.Context, key string, cmd *ice.Command) {
@ -94,15 +104,28 @@ func init() {
}) })
} }
}}, }},
mdb.EXPORT: {Hand: func(m *ice.Message, arg ...string) { "default": {Hand: func(m *ice.Message, arg ...string) {
TravelCmd(m, func(key, file, line string) { m.Push(mdb.NAME, key).Push(nfs.FILE, file).Push(nfs.LINE, line) }).Sort(mdb.NAME).Table(func(value ice.Maps) { m.Spawn(m.Source()).Search(arg[0], func(key string, cmd *ice.Command) {
m.Echo(`%s %s %s;" f`+lex.NL, value[mdb.NAME], value[nfs.FILE], value[nfs.LINE]) if arg[1] == ACTION {
}).Cmd(nfs.SAVE, nfs.TAGS, m.Result()) list := kit.Value(cmd.Meta, arg[2])
kit.For(arg[3:], func(k, v string) {
kit.For(list, func(value ice.Map) {
kit.If(value[mdb.NAME] == k, func() {
value[mdb.VALUE] = v
})
})
})
return
}
for i, v := range arg[1:] {
kit.Value(cmd.List, kit.Keys(i, mdb.VALUE), v)
}
})
}}, }},
}, aaa.RoleAction()), Hand: func(m *ice.Message, arg ...string) { }), Hand: func(m *ice.Message, arg ...string) {
if len(arg) == 0 { if len(arg) == 0 {
m.Cmdy("", mdb.SEARCH, COMMAND, ice.OptionFields(INDEX)).Action(mdb.EXPORT) m.OptionFields(INDEX)
DisplayStory(m.Options(nfs.DIR_ROOT, "ice."), "spide.js?split=.") m.Cmdy("", mdb.SEARCH, COMMAND)
} else { } else {
kit.For(arg, func(k string) { _command_list(m, k) }) kit.For(arg, func(k string) { _command_list(m, k) })
} }
@ -119,47 +142,28 @@ func Command(m *ice.Message, arg ...string) {
kit.If(!PodCmd(m, COMMAND, arg), func() { m.Cmdy(COMMAND, arg) }) kit.If(!PodCmd(m, COMMAND, arg), func() { m.Cmdy(COMMAND, arg) })
} }
func FileURI(dir string) string {
if dir == "" {
return ""
} else if strings.Contains(dir, "/pkg/mod/") {
dir = strings.Split(dir, "/pkg/mod/")[1]
} else if ice.Info.Make.Path != "" && strings.HasPrefix(dir, ice.Info.Make.Path) {
dir = strings.TrimPrefix(dir, ice.Info.Make.Path)
} else if strings.HasPrefix(dir, kit.Path("")+nfs.PS) {
dir = strings.TrimPrefix(dir, kit.Path("")+nfs.PS)
} else if strings.HasPrefix(dir, ice.ISH_PLUGED) {
dir = strings.TrimPrefix(dir, ice.ISH_PLUGED)
} else if kit.HasPrefix(dir, nfs.PS, ice.HTTP) {
return dir
}
if strings.HasPrefix(dir, ice.USR_VOLCANOS) {
return strings.TrimPrefix(dir, ice.USR)
} else {
return path.Join(nfs.PS, ice.REQUIRE, dir)
}
}
func FileCmd(dir string) string { func FileCmd(dir string) string {
if strings.Index(dir, ":") == 1 { if strings.Index(dir, ":") == 1 {
return FileURI(kit.ExtChange(strings.Join(kit.Slice(strings.Split(dir, ":"), 0, 2), ":"), nfs.GO)) return ice.Pulse.FileURI(kit.ExtChange(strings.Join(kit.Slice(strings.Split(dir, ":"), 0, 2), ":"), nfs.GO))
} }
return FileURI(kit.ExtChange(strings.Split(dir, nfs.DF)[0], nfs.GO)) return ice.Pulse.FileURI(kit.ExtChange(strings.Split(dir, nfs.DF)[0], nfs.GO))
} }
func AddFileCmd(dir, key string) { func AddFileCmd(dir, key string) {
ice.Info.File[FileCmd(dir)] = key
if ls := strings.SplitN(path.Join(kit.Slice(kit.Split(FileCmd(dir), nfs.PS), 1, 4)...), mdb.AT, 2); len(ls) > 1 { if ls := strings.SplitN(path.Join(kit.Slice(kit.Split(FileCmd(dir), nfs.PS), 1, 4)...), mdb.AT, 2); len(ls) > 1 {
_ls := strings.Split(FileCmd(dir), mdb.AT+ls[1]+nfs.PS) _ls := strings.Split(FileCmd(dir), mdb.AT+ls[1]+nfs.PS)
ice.Info.File[path.Join("/require/usr/", path.Base(_ls[0]), _ls[1])] = key ice.Info.File[path.Join(nfs.P, nfs.USR, path.Base(_ls[0]), _ls[1])] = key
ice.Info.Gomod[ls[0]] = ls[1] ice.Info.Gomod[ls[0]] = ls[1]
} else {
ice.Info.File[FileCmd(dir)] = key
} }
} }
func GetFileCmd(dir string) string { func GetFileCmd(dir string) string {
if strings.HasPrefix(dir, ice.REQUIRE+nfs.PS) { if strings.HasPrefix(dir, ice.REQUIRE+nfs.PS) {
dir = nfs.PS + dir dir = nfs.PS + dir
} else if strings.HasPrefix(dir, ice.ISH_PLUGED) { } else if strings.HasPrefix(dir, ice.ISH_PLUGED) {
dir = path.Join(nfs.PS, ice.REQUIRE, strings.TrimPrefix(dir, ice.ISH_PLUGED)) dir = path.Join(nfs.P, strings.TrimPrefix(dir, ice.ISH_PLUGED))
} }
for _, dir := range []string{dir, path.Join(nfs.PS, ice.REQUIRE, ice.Info.Make.Module, dir), path.Join(nfs.PS, ice.REQUIRE, ice.Info.Make.Module, ice.SRC, dir)} { for _, dir := range []string{dir, path.Join(nfs.P, ice.Info.Make.Module, dir), path.Join(nfs.P, ice.Info.Make.Module, ice.SRC, dir)} {
if cmd, ok := ice.Info.File[FileCmd(dir)]; ok { if cmd, ok := ice.Info.File[FileCmd(dir)]; ok {
return cmd return cmd
} }
@ -170,10 +174,17 @@ func GetFileCmd(dir string) string {
} }
return "" return ""
} }
func GetCmdHelp(m *ice.Message, cmds string) (file string) {
file = kit.TrimPrefix(m.FileURI(kit.ExtChange(GetCmdFile(m, cmds), nfs.SHY)), nfs.P, nfs.REQUIRE)
if !nfs.Exists(m, path.Join(nfs.USR_LEARNING_PORTAL, "commands", strings.TrimPrefix(file, nfs.USR_ICEBERGS)), func(p string) { file = p }) {
kit.If(!nfs.Exists(m, file), func() { file = "" })
}
return
}
func GetCmdFile(m *ice.Message, cmds string) (file string) { func GetCmdFile(m *ice.Message, cmds string) (file string) {
m.Search(kit.Select(m.PrefixKey(), cmds), func(key string, cmd *ice.Command) { m.Search(kit.Select(m.PrefixKey(), cmds), func(key string, cmd *ice.Command) {
if file = strings.TrimPrefix(FileURI(kit.Split(cmd.FileLine(), nfs.DF)[0]), "/require/"); !nfs.Exists(m, file) { if file = kit.TrimPrefix(m.FileURI(kit.Split(cmd.FileLine(), nfs.DF)[0]), nfs.P); !nfs.Exists(m, file) {
file = path.Join(ice.ISH_PLUGED, file) file = path.Join(nfs.P, file)
} }
}) })
return return
@ -195,4 +206,22 @@ func TravelCmd(m *ice.Message, cb func(key, file, line string)) *ice.Message {
}) })
return m return m
} }
func IsOrderCmd(key string) bool { return key[0] == '/' || key[0] == '_' } func IsOrderCmd(key string) bool {
return key[0] == '/' || key[0] == '_'
}
func ShortCmd(key string) string {
_key := kit.Select("", kit.Split(key, nfs.PT), -1)
if _p, ok := ice.Info.Index[_key].(*ice.Context); ok && _p.Prefix(_key) == key {
return _key
}
return key
}
func ResourceFile(m *ice.Message, file string, arg ...string) string {
if kit.HasPrefix(file, nfs.PS, ice.HTTP) {
return file
} else if nfs.Exists(m, file) {
return file
} else {
return path.Join(path.Dir(GetCmdFile(m, m.PrefixKey())), file)
}
}

View File

@ -13,24 +13,6 @@ import (
"shylinux.com/x/toolkits/miss" "shylinux.com/x/toolkits/miss"
) )
func _config_format_list(m *ice.Message, v ice.Any) string {
list := []string{"{", lex.NL}
kit.For(v, func(k string, v ice.Any) {
if k == mdb.HASH {
list = append(list, lex.TB, kit.Format("%q", k), nfs.DF, "{", lex.NL)
kit.For(v, func(k string, v ice.Any) {
list = append(list, lex.TB, lex.TB, kit.Format("%q", k), nfs.DF, kit.Format(v), mdb.FS, lex.NL)
})
list = list[:len(list)-2]
list = append(list, lex.TB, lex.NL, lex.TB, "}", mdb.FS, lex.NL)
} else {
list = append(list, lex.TB, kit.Format("%q", k), nfs.DF, kit.Format(v), mdb.FS, lex.NL)
}
})
list = list[:len(list)-2]
list = append(list, lex.NL, "}")
return strings.Join(list, "")
}
func _config_only(v ice.Any, arg ...string) bool { func _config_only(v ice.Any, arg ...string) bool {
switch v := v.(type) { switch v := v.(type) {
case nil: case nil:
@ -42,14 +24,7 @@ func _config_only(v ice.Any, arg ...string) bool {
for k, v := range v { for k, v := range v {
if v, ok := v.(ice.Map); ok && len(v) == 0 { if v, ok := v.(ice.Map); ok && len(v) == 0 {
continue continue
} else { } else if kit.IndexOf(arg, k) == -1 {
for k := range v {
if kit.IsIn(k, mdb.IMPORTANT) && len(v) > 1 {
return false
}
}
}
if kit.IndexOf(arg, k) == -1 {
return false return false
} }
} }
@ -58,9 +33,17 @@ func _config_only(v ice.Any, arg ...string) bool {
return false return false
} }
func _config_save(m *ice.Message, name string, arg ...string) { func _config_save(m *ice.Message, name string, arg ...string) {
if !ice.HasVar() {
return
}
data, msg := ice.Map{}, m.Spawn(m.Source()) data, msg := ice.Map{}, m.Spawn(m.Source())
for _, k := range arg { for _, k := range arg {
if v := mdb.Confv(msg, k); _config_only(v, mdb.META) { if v := mdb.Confv(msg, k); _config_only(v, mdb.META) && _config_only(kit.Value(v, mdb.META),
mdb.IMPORTANT, mdb.EXPIRE, mdb.VENDOR, nfs.SOURCE, nfs.SCRIPT, nfs.PATH, lex.REGEXP,
mdb.SHORT, mdb.FIELD, mdb.SHORTS, mdb.FIELDS,
mdb.ACTION, mdb.SORT, mdb.TOOLS,
"link", "linux", "darwin", "windows",
) {
continue continue
} else { } else {
data[k] = v data[k] = v
@ -71,13 +54,16 @@ func _config_save(m *ice.Message, name string, arg ...string) {
} }
if f, _, e := miss.CreateFile(path.Join(ice.VAR_CONF, name)); m.Assert(e) { if f, _, e := miss.CreateFile(path.Join(ice.VAR_CONF, name)); m.Assert(e) {
defer f.Close() defer f.Close()
if s, e := json.MarshalIndent(data, "", " "); !m.Warn(e) { if s, e := json.MarshalIndent(data, "", " "); !m.WarnNotValid(e) {
if _, e := f.Write(s); !m.Warn(e) { if _, e := f.Write(s); !m.WarnNotValid(e) {
} }
} }
} }
} }
func _config_load(m *ice.Message, name string, arg ...string) { func _config_load(m *ice.Message, name string, arg ...string) {
if !ice.HasVar() {
return
}
if f, e := miss.OpenFile(path.Join(ice.VAR_CONF, name)); e == nil { if f, e := miss.OpenFile(path.Join(ice.VAR_CONF, name)); e == nil {
defer f.Close() defer f.Close()
data, msg := ice.Map{}, m.Spawn(m.Source()) data, msg := ice.Map{}, m.Spawn(m.Source())
@ -93,58 +79,60 @@ func _config_load(m *ice.Message, name string, arg ...string) {
func _config_make(m *ice.Message, key string, arg ...string) { func _config_make(m *ice.Message, key string, arg ...string) {
msg := m.Spawn(m.Source()) msg := m.Spawn(m.Source())
if len(arg) > 1 { if len(arg) > 1 {
kit.If(!kit.IsIn(strings.Split(arg[0], nfs.PT)[0], mdb.META, mdb.HASH, mdb.LIST), func() { arg[0] = kit.Keys(mdb.META, arg[0]) })
kit.If(strings.HasPrefix(arg[1], mdb.AT), func() { arg[1] = msg.Cmdx(nfs.CAT, arg[1][1:]) }) kit.If(strings.HasPrefix(arg[1], mdb.AT), func() { arg[1] = msg.Cmdx(nfs.CAT, arg[1][1:]) })
if !kit.IsIn(strings.Split(arg[0], nfs.PT)[0], mdb.META, mdb.HASH, mdb.LIST) {
arg[0] = kit.Keys(mdb.META, arg[0])
}
mdb.Confv(msg, key, arg[0], kit.Parse(nil, "", arg[1:]...)) mdb.Confv(msg, key, arg[0], kit.Parse(nil, "", arg[1:]...))
} }
if len(arg) > 0 { if len(arg) > 0 {
m.Echo(FormatPretty(mdb.Confv(msg, key, arg[0]), 0, 1)) m.Echo(kit.Formats(mdb.Confv(msg, key, arg[0])))
} else { } else {
m.Echo(FormatPretty(mdb.Confv(msg, key), 0, 1)) m.Echo(kit.Formats(mdb.Confv(msg, key))).StatusTime(mdb.COUNT, kit.Length(mdb.Confv(msg, key, mdb.HASH)))
m.StatusTime(mdb.COUNT, kit.Length(mdb.Confv(msg, key, mdb.HASH)))
} }
} }
func _config_list(m *ice.Message) { func _config_list(m *ice.Message) {
for k, v := range m.Source().Configs { for k, v := range m.Source().Configs {
if IsOrderCmd(k) { if !IsOrderCmd(k) {
continue m.Push(mdb.KEY, k).Push(mdb.NAME, v.Name).Push(mdb.VALUE, kit.Format(v.Value))
} }
m.Push(mdb.KEY, k).Push(mdb.NAME, v.Name).Push(mdb.VALUE, kit.Format(v.Value))
} }
m.Sort(mdb.KEY) m.Sort(mdb.KEY)
} }
const (
SAVE = "save"
LOAD = "load"
)
const CONFIG = "config" const CONFIG = "config"
func init() { func init() {
Index.MergeCommands(ice.Commands{ Index.MergeCommands(ice.Commands{
CONFIG: {Name: "config key auto", Help: "配置", Actions: ice.Actions{ CONFIG: {Name: "config key auto", Help: "配置", Actions: ice.Actions{
SAVE: {Hand: func(m *ice.Message, arg ...string) { _config_save(m, arg[0], arg[1:]...) }}, nfs.SAVE: {Hand: func(m *ice.Message, arg ...string) { _config_save(m, arg[0], arg[1:]...) }},
LOAD: {Hand: func(m *ice.Message, arg ...string) { _config_load(m, arg[0], arg[1:]...) }}, nfs.LOAD: {Hand: func(m *ice.Message, arg ...string) { _config_load(m, arg[0], arg[1:]...) }},
mdb.EXPORT: {Hand: func(m *ice.Message, arg ...string) { m.Cmdy(arg[0], mdb.EXPORT) }}, mdb.EXPORT: {Hand: func(m *ice.Message, arg ...string) { m.Cmdy(arg[0], mdb.EXPORT) }},
mdb.IMPORT: {Hand: func(m *ice.Message, arg ...string) { m.Cmdy(arg[0], mdb.IMPORT) }}, mdb.IMPORT: {Hand: func(m *ice.Message, arg ...string) { m.Cmdy(arg[0], mdb.IMPORT) }},
nfs.TRASH: {Hand: func(m *ice.Message, arg ...string) { nfs.TRASH: {Hand: func(m *ice.Message, arg ...string) {
nfs.Trash(m, path.Join(ice.VAR_DATA, arg[0])) nfs.Trash(m, path.Join(ice.VAR_DATA, arg[0]))
nfs.Trash(m, m.Cmdx(arg[0], mdb.EXPORT)) nfs.Trash(m, m.Cmdx(arg[0], mdb.EXPORT))
mdb.Config(m, arg[0], nil, nil) mdb.Conf(m, arg[0], mdb.HASH, "")
}}, }},
mdb.LIST: {Hand: func(m *ice.Message, arg ...string) { mdb.CREATE: {Name: "create name value", Hand: func(m *ice.Message, arg ...string) {
list := []ice.Any{} m.Confv(m.Option(mdb.KEY), kit.Keys(mdb.META, m.Option(mdb.NAME)), m.Option(mdb.VALUE))
kit.For(arg[2:], func(v string) { list = append(list, v) }) }},
mdb.Confv(m, arg[0], arg[1], list) mdb.REMOVE: {Hand: func(m *ice.Message, arg ...string) {
m.Confv(m.Option(mdb.KEY), kit.Keys(mdb.META, m.Option(mdb.NAME)), "")
}},
mdb.MODIFY: {Hand: func(m *ice.Message, arg ...string) {
if arg[0] == mdb.VALUE {
m.Confv(m.Option(mdb.KEY), kit.Keys(mdb.META, m.Option(mdb.NAME)), arg[1])
}
}}, }},
}, Hand: func(m *ice.Message, arg ...string) { }, Hand: func(m *ice.Message, arg ...string) {
if len(arg) == 0 { if len(arg) == 0 {
_config_list(m) _config_list(m)
} else { } else {
_config_make(m, arg[0], arg[1:]...) _config_make(m, arg[0], arg[1:]...)
m.Action(mdb.EXPORT, mdb.IMPORT, nfs.TRASH) m.Action(mdb.CREATE, mdb.IMPORT, mdb.EXPORT, nfs.TRASH)
kit.For(mdb.Confv(m, arg[0], mdb.META), func(k, v string) {
m.Push(mdb.NAME, k).Push(mdb.VALUE, v).PushButton(mdb.REMOVE)
})
DisplayStoryJSON(m)
} }
}}, }},
}) })
@ -153,17 +141,15 @@ func init() { ice.Info.Save = Save; ice.Info.Load = Load }
func Save(m *ice.Message, arg ...string) *ice.Message { func Save(m *ice.Message, arg ...string) *ice.Message {
kit.If(len(arg) == 0, func() { arg = kit.SortedKey(m.Target().Configs) }) kit.If(len(arg) == 0, func() { arg = kit.SortedKey(m.Target().Configs) })
kit.For(arg, func(i int, k string) { arg[i] = strings.Replace(m.Prefix(k), nfs.PS, "", 1) }) kit.For(arg, func(i int, k string) { arg[i] = strings.Replace(m.Prefix(k), nfs.PS, "", 1) })
return m.Cmd(CONFIG, SAVE, m.Prefix(nfs.JSON), arg) return m.Cmd(prefix(CONFIG), nfs.SAVE, m.Prefix(nfs.JSON), arg)
} }
func Load(m *ice.Message, arg ...string) *ice.Message { func Load(m *ice.Message, arg ...string) *ice.Message {
kit.If(len(arg) == 0, func() { arg = kit.SortedKey(m.Target().Configs) }) kit.If(len(arg) == 0, func() { arg = kit.SortedKey(m.Target().Configs) })
kit.For(arg, func(i int, k string) { arg[i] = strings.Replace(m.Prefix(k), nfs.PS, "", 1) }) kit.For(arg, func(i int, k string) { arg[i] = strings.Replace(m.Prefix(k), nfs.PS, "", 1) })
return m.Cmd(CONFIG, LOAD, m.Prefix(nfs.JSON), arg) return m.Cmd(prefix(CONFIG), nfs.LOAD, m.Prefix(nfs.JSON), arg)
} }
func ConfAction(arg ...ice.Any) ice.Actions { return ice.Actions{ice.CTX_INIT: mdb.AutoConfig(arg...)} } func ConfAction(arg ...ice.Any) ice.Actions {
func ConfigSimple(m *ice.Message, key ...string) (res []string) { return ice.Actions{ice.CTX_INIT: mdb.AutoConfig(arg...)}
kit.For(kit.Split(kit.Join(key)), func(k string) { res = append(res, k, mdb.Config(m, k)) })
return
} }
func ConfigFromOption(m *ice.Message, arg ...string) { func ConfigFromOption(m *ice.Message, arg ...string) {
if len(arg) == 0 { if len(arg) == 0 {
@ -177,59 +163,3 @@ func OptionFromConfig(m *ice.Message, arg ...string) string {
kit.For(arg, func(k string) { m.Option(k, mdb.Config(m, k)) }) kit.For(arg, func(k string) { m.Option(k, mdb.Config(m, k)) })
return m.Option(arg[0]) return m.Option(arg[0])
} }
func FormatPretty(v ice.Any, i, n int) string {
return kit.Formats(v)
switch v := v.(type) {
case map[string]ice.Any:
if n == 0 {
list := []string{"{"}
kit.For(v, func(k string, v ice.Any) {
list = append(list, kit.Format("%q", k), nfs.DF, FormatPretty(v, 0, 0), mdb.FS)
})
list = list[:len(list)-1]
list = append(list, "}")
return strings.Join(list, "")
}
list := []string{"{", lex.NL}
kit.For(v, func(k string, v ice.Any) {
list = append(list, strings.Repeat(lex.TB, i+1), kit.Format("%q", k), nfs.DF)
if i < n && !kit.IsIn(k, mdb.META) && !strings.HasPrefix(k, "_") {
list = append(list, FormatPretty(v, i+1, n))
} else {
list = append(list, FormatPretty(v, 0, 0))
}
list = append(list, mdb.FS, lex.NL)
})
list = append(list[:len(list)-2], lex.NL)
list = append(list, strings.Repeat(lex.TB, i), "}")
return strings.Join(list, "")
case []ice.Any:
if n == 0 {
list := []string{"["}
kit.For(v, func(k string, v ice.Any) {
list = append(list, FormatPretty(v, 0, 0), mdb.FS)
})
list = list[:len(list)-1]
list = append(list, "]")
return strings.Join(list, "")
}
list := []string{"[", lex.NL}
kit.For(v, func(v ice.Any) {
list = append(list, strings.Repeat(lex.TB, i+1))
if i < n {
list = append(list, FormatPretty(v, i+1, n))
} else {
list = append(list, FormatPretty(v, 0, 0))
}
list = append(list, mdb.FS, lex.NL)
})
list = append(list[:len(list)-2], lex.NL)
list = append(list, strings.Repeat(lex.TB, i), "]")
return strings.Join(list, "")
case string:
return kit.Format(v)
return kit.Format("%q", v)
default:
return kit.Format(v)
}
}

View File

@ -11,4 +11,4 @@ var Index = &ice.Context{Name: CTX, Help: "标准模块"}
func init() { ice.Index.Register(Index, nil, CONTEXT, COMMAND, CONFIG) } func init() { ice.Index.Register(Index, nil, CONTEXT, COMMAND, CONFIG) }
func Prefix(arg ...string) string { return kit.Keys(CTX, arg) } func prefix(arg ...string) string { return kit.Keys(CTX, arg) }

View File

@ -2,28 +2,19 @@ package ctx
import ( import (
"path" "path"
"reflect"
"strings" "strings"
ice "shylinux.com/x/icebergs" ice "shylinux.com/x/icebergs"
"shylinux.com/x/icebergs/base/mdb" "shylinux.com/x/icebergs/base/mdb"
"shylinux.com/x/icebergs/base/nfs" "shylinux.com/x/icebergs/base/nfs"
"shylinux.com/x/icebergs/base/web/html"
kit "shylinux.com/x/toolkits" kit "shylinux.com/x/toolkits"
"shylinux.com/x/toolkits/logs"
) )
type displayMessage interface {
Option(key string, arg ...ice.Any) string
Action(arg ...ice.Any) *ice.Message
}
func isLocalFile(p string) bool { func isLocalFile(p string) bool {
return !strings.HasPrefix(p, nfs.PS) && !strings.HasPrefix(p, ice.HTTP) return !strings.HasPrefix(p, nfs.PS) && !strings.HasPrefix(p, ice.HTTP)
} }
func Display(m *ice.Message, file string, arg ...ice.Any) *ice.Message {
kit.If(file == "", func() { file = kit.Keys(kit.FileName(5), nfs.JS) })
kit.If(isLocalFile(file), func() { file = path.Join(nfs.PS, path.Join(path.Dir(FileURI(logs.FileLines(2))), file)) })
return DisplayBase(m, file, arg...)
}
func DisplayTable(m *ice.Message, arg ...ice.Any) *ice.Message { func DisplayTable(m *ice.Message, arg ...ice.Any) *ice.Message {
return DisplayBase(m, ice.PLUGIN_TABLE_JS, arg...) return DisplayBase(m, ice.PLUGIN_TABLE_JS, arg...)
} }
@ -31,10 +22,41 @@ func DisplayTableCard(m *ice.Message, arg ...ice.Any) *ice.Message {
return DisplayTable(m, STYLE, "card") return DisplayTable(m, STYLE, "card")
} }
func DisplayStory(m *ice.Message, file string, arg ...ice.Any) *ice.Message { func DisplayStory(m *ice.Message, file string, arg ...ice.Any) *ice.Message {
kit.If(file == "", func() { file = kit.Keys(kit.FileName(5), nfs.JS) }) kit.If(file == "", func() { file = kit.Keys(m.CommandKey(), nfs.JS) })
kit.If(isLocalFile(file), func() { file = path.Join(ice.PLUGIN_STORY, file) }) kit.If(isLocalFile(file), func() { file = path.Join(ice.PLUGIN_STORY, file) })
return DisplayBase(m, file, arg...) return DisplayBase(m, file, arg...)
} }
func DisplayInput(m *ice.Message, file string, arg ...ice.Any) *ice.Message {
kit.If(file == "", func() { file = kit.Keys(m.CommandKey(), nfs.JS) })
kit.If(isLocalFile(file), func() { file = path.Join(ice.PLUGIN_INPUT, file) })
return DisplayBase(m, file, arg...)
}
func DisplayStoryForm(m *ice.Message, arg ...ice.Any) *ice.Message {
args := kit.List()
for i := range arg {
switch v := arg[i].(type) {
case string:
args = append(args, ice.SplitCmd("list "+v, nil)...)
default:
trans := kit.Value(m.Commands(m.CommandKey()).Meta, ice.CTX_TRANS)
if t := reflect.TypeOf(v); t.Kind() == reflect.Func {
name := kit.FuncName(arg[i])
args = append(args, kit.Dict(mdb.TYPE, html.BUTTON, mdb.NAME, name, mdb.VALUE, kit.Select(name, kit.Value(trans, name), !m.IsEnglish())))
}
}
}
kit.For(args, func(v ice.Map) { m.Push("", v, kit.Split("type,name,value,values,need,action")) })
return DisplayStory(m, "form")
}
func DisplayInputKey(m *ice.Message, arg ...ice.Any) *ice.Message {
return DisplayInput(m, "key", arg...)
}
func DisplayStoryWeight(m *ice.Message, arg ...ice.Any) *ice.Message {
return DisplayStory(m, "weight", arg...)
}
func DisplayStoryPie(m *ice.Message, arg ...ice.Any) *ice.Message {
return DisplayStory(m, "pie", arg...)
}
func DisplayStoryJSON(m *ice.Message, arg ...ice.Any) *ice.Message { func DisplayStoryJSON(m *ice.Message, arg ...ice.Any) *ice.Message {
return DisplayStory(m, "json", arg...) return DisplayStory(m, "json", arg...)
} }
@ -48,21 +70,25 @@ func DisplayStudio(m *ice.Message, cmd ...string) *ice.Message {
for i, k := range cmd { for i, k := range cmd {
kit.If(!strings.Contains(cmd[i], nfs.PT), func() { cmd[i] = m.Prefix(k) }) kit.If(!strings.Contains(cmd[i], nfs.PT), func() { cmd[i] = m.Prefix(k) })
} }
return DisplayStory(m.Cmdy(COMMAND, cmd), "studio.js") return DisplayStory(m.Cmdy(COMMAND, cmd), "studio")
} }
func DisplayLocal(m *ice.Message, file string, arg ...ice.Any) *ice.Message { func DisplayLocal(m *ice.Message, file string, arg ...ice.Any) *ice.Message {
kit.If(file == "", func() { file = path.Join(kit.PathName(5), kit.Keys(kit.FileName(5), nfs.JS)) }) kit.If(file == "", func() { file = strings.ReplaceAll(strings.TrimPrefix(m.PrefixKey(), "web."), nfs.PT, nfs.PS) })
kit.If(isLocalFile(file), func() { file = path.Join(ice.PLUGIN_LOCAL, file) }) kit.If(isLocalFile(file), func() { file = path.Join(ice.PLUGIN_LOCAL, file) })
return DisplayBase(m, file, arg...) return DisplayBase(m, file, arg...)
} }
func DisplayLocalInner(m *ice.Message, arg ...ice.Any) *ice.Message { func DisplayLocalInner(m *ice.Message, arg ...ice.Any) *ice.Message {
return DisplayLocal(m, "code/inner.js", arg...) return DisplayLocal(m, "code/inner", arg...)
} }
func DisplayBase(m *ice.Message, file string, arg ...ice.Any) *ice.Message { func DisplayBase(m *ice.Message, file string, arg ...ice.Any) *ice.Message {
m.Option(ice.MSG_DISPLAY, kit.MergeURL(kit.Select(kit.ExtChange(file, nfs.JS), file, strings.Contains(file, mdb.QS)), arg...)) m.Option(ice.MSG_DISPLAY, kit.MergeURL(kit.Select(kit.ExtChange(file, nfs.JS), file, strings.Contains(file, mdb.QS)), arg...))
Toolkit(m, "") return Toolkit(m, "")
}
func DisplayBaseCSS(m *ice.Message, file string, arg ...ice.Any) *ice.Message {
m.Option(ice.MSG_DISPLAY_CSS, kit.MergeURL(kit.Select(kit.ExtChange(file, nfs.CSS), file, strings.Contains(file, mdb.QS)), arg...))
return m return m
} }
func Toolkit(m *ice.Message, arg ...string) { func Toolkit(m *ice.Message, arg ...string) *ice.Message {
m.Option(ice.MSG_TOOLKIT, kit.Select(mdb.Config(m, mdb.TOOLS), kit.Fields(arg))) m.OptionDefault(ice.MSG_ONLINE, mdb.Config(m, "online"))
return m.Options(ice.MSG_TOOLKIT, kit.Select(mdb.Config(m, mdb.TOOLS), kit.Fields(arg)))
} }

View File

@ -1,67 +1,61 @@
package ctx package ctx
import ( import (
"path"
ice "shylinux.com/x/icebergs" ice "shylinux.com/x/icebergs"
"shylinux.com/x/icebergs/base/aaa" "shylinux.com/x/icebergs/base/aaa"
"shylinux.com/x/icebergs/base/web/html"
kit "shylinux.com/x/toolkits" kit "shylinux.com/x/toolkits"
) )
const PROCESS = "process"
var _process = map[string]ice.Any{}
func AddProcess(key string, val ice.Any) { _process[key] = val }
func ProcessAction() ice.Actions {
return ice.Actions{
ice.CTX_INIT: {Hand: func(m *ice.Message, arg ...string) { AddProcess(m.CommandKey(), m.PrefixKey()) }},
PROCESS: {Hand: func(m *ice.Message, arg ...string) { ProcessField(m, m.PrefixKey(), arg, arg...) }},
}
}
func _process_args(m *ice.Message, args ice.Any) []string { func _process_args(m *ice.Message, args ice.Any) []string {
switch cb := args.(type) { switch cb := args.(type) {
case func():
cb()
return []string{}
case func() string:
return []string{cb()}
case func() []string:
return cb()
case []string: case []string:
return cb return cb
case string: case string:
return []string{cb} return []string{cb}
case func() string:
return []string{cb()}
case func() []string:
return cb()
case func():
cb()
case nil: case nil:
default: default:
m.ErrorNotImplement(args) m.ErrorNotImplement(args)
} }
return nil return nil
} }
func Process(m *ice.Message, key string, args ice.Any, arg ...string) {
switch cb := _process[kit.Select(m.ActionKey(), key)].(type) {
case string:
if !kit.HasPrefixList(arg, ACTION, PROCESS) {
m.Cmdy(cb, PROCESS, _process_args(m, args)).Optionv(ice.FIELD_PREFIX, kit.Simple(m.ActionKey(), m.Optionv(ice.FIELD_PREFIX)))
} else {
m.Cmdy(cb, arg)
}
default:
ProcessField(m, key, args, arg...)
}
}
func ProcessField(m *ice.Message, cmd string, args ice.Any, arg ...string) *ice.Message { func ProcessField(m *ice.Message, cmd string, args ice.Any, arg ...string) *ice.Message {
if cmd = kit.Select(m.ActionKey(), cmd); !kit.HasPrefixList(arg, RUN) { if cmd = kit.Select(m.ActionKey(), cmd); kit.HasPrefixList(arg, RUN) {
if PodCmd(m, COMMAND, cmd) { if !PodCmd(m, cmd, arg[1:]) && aaa.Right(m, cmd, arg[1:]) {
m.Push(ice.SPACE, m.Option(ice.MSG_USERPOD)) m.Cmdy(cmd, arg[1:])
} else {
m.Cmdy(COMMAND, cmd)
} }
m.Push(ARGS, kit.Format(_process_args(m, args))).Options(ice.MSG_INDEX, m.PrefixKey()) return m
m.ProcessField(ACTION, m.ActionKey(), RUN) }
args = kit.Format(_process_args(m, args))
if PodCmd(m, COMMAND, cmd) {
m.Push(ice.SPACE, m.Option(ice.MSG_USERPOD))
} else { } else {
if !PodCmd(m, cmd, arg[1:]) { m.Cmdy(COMMAND, cmd)
kit.If(aaa.Right(m, cmd, arg[1:]), func() { m.Cmdy(cmd, arg[1:]) }) }
} if m.Push(ARGS, args); m.IsMetaKey() {
m.Push(STYLE, html.FLOAT)
}
if m.ActionKey() == "" {
m.ProcessField(ACTION, RUN, cmd)
} else {
m.ProcessField(ACTION, m.ActionKey(), RUN)
} }
return m return m
} }
func ProcessFloat(m *ice.Message, cmd string, args ice.Any, arg ...string) *ice.Message {
if m.IsMetaKey() {
m.ProcessOpen(path.Join("/c/", cmd, path.Join(_process_args(m, args)...)))
return m
} else if !kit.HasPrefixList(arg, RUN) {
defer m.Push(STYLE, html.FLOAT)
}
return ProcessField(m, cmd, args, arg...)
}

View File

@ -1,6 +1,8 @@
package gdb package gdb
import ( import (
"sync"
ice "shylinux.com/x/icebergs" ice "shylinux.com/x/icebergs"
"shylinux.com/x/icebergs/base/mdb" "shylinux.com/x/icebergs/base/mdb"
kit "shylinux.com/x/toolkits" kit "shylinux.com/x/toolkits"
@ -23,9 +25,10 @@ func init() {
HAPPEN: {Name: "happen event*", Help: "触发", Hand: func(m *ice.Message, arg ...string) { HAPPEN: {Name: "happen event*", Help: "触发", Hand: func(m *ice.Message, arg ...string) {
defer m.Cost() defer m.Cost()
m.OptionCB(mdb.SELECT, "") m.OptionCB(mdb.SELECT, "")
mdb.ZoneSelect(m.Spawn(ice.OptionFields("")), arg[1]).Table(func(value ice.Maps) { mdb.ZoneSelectAll(m.Spawn(ice.OptionFields("")), arg[1]).Table(func(value ice.Maps) {
m.Cmdy(kit.Split(value[ice.CMD]), arg[1], arg[2:], ice.OptionFields("")) m.Cmdy(kit.Split(value[ice.CMD]), arg[1], arg[2:], ice.OptionFields(""))
}) })
_waitMap.Range(func(key, cb ice.Any) bool { cb.(func(*ice.Message, ...string))(m, arg...); return true })
}}, }},
}, mdb.ZoneAction(mdb.SHORT, EVENT, mdb.FIELDS, "time,id,cmd"), mdb.ClearOnExitHashAction())}, }, mdb.ZoneAction(mdb.SHORT, EVENT, mdb.FIELDS, "time,id,cmd"), mdb.ClearOnExitHashAction())},
}) })
@ -43,7 +46,7 @@ func EventsAction(arg ...string) ice.Actions {
var list map[string]int = map[string]int{} var list map[string]int = map[string]int{}
func Watch(m *ice.Message, key string, arg ...string) *ice.Message { func Watch(m *ice.Message, key string, arg ...string) *ice.Message {
kit.If(len(arg) == 0, func() { arg = append(arg, m.PrefixKey()) }) kit.If(len(arg) == 0, func() { arg = append(arg, m.ShortKey()) })
return m.Cmd(Prefix(EVENT), LISTEN, EVENT, key, ice.CMD, kit.Join(arg, ice.SP)) return m.Cmd(Prefix(EVENT), LISTEN, EVENT, key, ice.CMD, kit.Join(arg, ice.SP))
} }
func Event(m *ice.Message, key string, arg ...ice.Any) *ice.Message { func Event(m *ice.Message, key string, arg ...ice.Any) *ice.Message {
@ -56,3 +59,17 @@ func EventDeferEvent(m *ice.Message, key string, arg ...ice.Any) func(string, ..
Event(m, key, arg...) Event(m, key, arg...)
return func(key string, args ...ice.Any) { Event(m, key, args...) } return func(key string, args ...ice.Any) { Event(m, key, args...) }
} }
var _waitMap = sync.Map{}
func WaitEvent(m *ice.Message, key string, cb func(*ice.Message, ...string) bool) {
wg := sync.WaitGroup{}
h := kit.HashsUniq()
defer _waitMap.Delete(h)
_waitMap.Store(h, func(m *ice.Message, arg ...string) {
m.Info("WaitEvent %v %v", key, kit.FileLine(cb, 3))
kit.If((key == "" || m.Option(EVENT) == key) && cb(m, arg...), func() { wg.Done() })
})
wg.Add(1)
defer wg.Wait()
}

View File

@ -5,6 +5,7 @@ import (
"os" "os"
"os/signal" "os/signal"
"syscall" "syscall"
"time"
ice "shylinux.com/x/icebergs" ice "shylinux.com/x/icebergs"
"shylinux.com/x/icebergs/base/mdb" "shylinux.com/x/icebergs/base/mdb"
@ -14,20 +15,22 @@ import (
type Frame struct{ s chan os.Signal } type Frame struct{ s chan os.Signal }
func (f *Frame) Begin(m *ice.Message, arg ...string) { f.s = make(chan os.Signal, 10) } func (f *Frame) Begin(m *ice.Message, arg ...string) {
f.s = make(chan os.Signal, 10)
}
func (f *Frame) Start(m *ice.Message, arg ...string) { func (f *Frame) Start(m *ice.Message, arg ...string) {
kit.If(ice.Info.PidPath, func(p string) { if ice.HasVar() {
if f, p, e := logs.CreateFile(p); e == nil { if f, p, e := logs.CreateFile(ice.VAR_LOG_ICE_PID); e == nil {
defer f.Close()
m.Logs("save", "file", p, PID, os.Getpid()) m.Logs("save", "file", p, PID, os.Getpid())
fmt.Fprint(f, os.Getpid()) fmt.Fprint(f, os.Getpid())
f.Close()
} }
}) }
// t := kit.Duration(mdb.Conf(m, TIMER, kit.Keym(TICK))) t := time.NewTicker(kit.Duration(mdb.Conf(m, TIMER, kit.Keym(TICK))))
for { for {
select { select {
// case <-time.Tick(t): case <-t.C:
// m.Cmd(TIMER, HAPPEN, kit.Dict(ice.LOG_DISABLE, ice.TRUE)) m.Options(ice.LOG_DISABLE, ice.TRUE).Cmd(TIMER, HAPPEN)
case s, ok := <-f.s: case s, ok := <-f.s:
if !ok { if !ok {
return return
@ -38,7 +41,6 @@ func (f *Frame) Start(m *ice.Message, arg ...string) {
} }
func (f *Frame) Close(m *ice.Message, arg ...string) { func (f *Frame) Close(m *ice.Message, arg ...string) {
close(f.s) close(f.s)
kit.If(ice.Info.PidPath, func(p string) { os.Remove(p) })
} }
func (f *Frame) listen(m *ice.Message, s int, arg ...string) { func (f *Frame) listen(m *ice.Message, s int, arg ...string) {
signal.Notify(f.s, syscall.Signal(s)) signal.Notify(f.s, syscall.Signal(s))

View File

@ -42,5 +42,5 @@ func init() {
}) })
} }
func Go(m *ice.Message, cb ice.Any, arg ...string) { func Go(m *ice.Message, cb ice.Any, arg ...string) {
m.Cmd(ROUTINE, mdb.CREATE, kit.Select(m.PrefixKey(), arg, 0), logs.FileLine(cb), cb) m.Cmd(ROUTINE, mdb.CREATE, kit.Select(m.ShortKey(), arg, 0), logs.FileLine(cb), cb)
} }

View File

@ -3,7 +3,6 @@ package gdb
import ( import (
"os" "os"
"os/signal" "os/signal"
"runtime"
"syscall" "syscall"
ice "shylinux.com/x/icebergs" ice "shylinux.com/x/icebergs"
@ -21,13 +20,7 @@ func _signal_action(m *ice.Message, arg ...string) {
mdb.HashSelect(m.Spawn(), arg...).Table(func(value ice.Maps) { m.Cmdy(kit.Split(value[ice.CMD])) }) mdb.HashSelect(m.Spawn(), arg...).Table(func(value ice.Maps) { m.Cmdy(kit.Split(value[ice.CMD])) })
} }
func _signal_process(m *ice.Message, p string, s os.Signal) { func _signal_process(m *ice.Message, p string, s os.Signal) {
if p == "" { kit.If(p == "", func() { b, _ := file.ReadFile(ice.VAR_LOG_ICE_PID); p = string(b) })
b, _ := file.ReadFile(ice.Info.PidPath)
p = string(b)
if runtime.GOOS == ice.WINDOWS {
return
}
}
if p, e := os.FindProcess(kit.Int(kit.Select(kit.Format(os.Getpid()), p))); e == nil { if p, e := os.FindProcess(kit.Int(kit.Select(kit.Format(os.Getpid()), p))); e == nil {
p.Signal(s) p.Signal(s)
} }
@ -49,14 +42,7 @@ const SIGNAL = "signal"
func init() { func init() {
Index.MergeCommands(ice.Commands{ Index.MergeCommands(ice.Commands{
SIGNAL: {Help: "信号量", Actions: ice.MergeActions(ice.Actions{ SIGNAL: {Help: "信号量", Actions: ice.MergeActions(ice.Actions{
ice.CTX_INIT: {Hand: func(m *ice.Message, arg ...string) { ice.CTX_INIT: {Hand: func(m *ice.Message, arg ...string) { _signal_init(m, arg...) }},
if runtime.GOOS == ice.WINDOWS {
return
}
_signal_listen(m, 1, mdb.NAME, START, ice.CMD, "runtime")
_signal_listen(m, 2, mdb.NAME, RESTART, ice.CMD, "exit 1")
_signal_listen(m, 3, mdb.NAME, STOP, ice.CMD, "exit 0")
}},
LISTEN: {Name: "listen signal name cmd", Help: "监听", Hand: func(m *ice.Message, arg ...string) { LISTEN: {Name: "listen signal name cmd", Help: "监听", Hand: func(m *ice.Message, arg ...string) {
_signal_listen(m, kit.Int(m.Option(SIGNAL)), arg...) _signal_listen(m, kit.Int(m.Option(SIGNAL)), arg...)
}}, }},

24
base/gdb/signal_darwin.go Normal file
View File

@ -0,0 +1,24 @@
package gdb
import (
"os"
"syscall"
ice "shylinux.com/x/icebergs"
"shylinux.com/x/icebergs/base/mdb"
kit "shylinux.com/x/toolkits"
)
func _signal_init(m *ice.Message, arg ...string) {
_signal_listen(m, 1, mdb.NAME, START, ice.CMD, "runtime")
_signal_listen(m, 2, mdb.NAME, RESTART, ice.CMD, "exit 1")
_signal_listen(m, 3, mdb.NAME, STOP, ice.CMD, "exit 0")
_signal_listen(m, int(syscall.SIGUSR1), mdb.NAME, "info", ice.CMD, "runtime")
}
func SignalProcess(m *ice.Message, pid string) bool {
if proc, err := os.FindProcess(kit.Int(pid)); err == nil && proc.Signal(syscall.SIGUSR1) == nil {
return true
}
return false
}

23
base/gdb/signal_linux.go Normal file
View File

@ -0,0 +1,23 @@
package gdb
import (
"os"
"syscall"
ice "shylinux.com/x/icebergs"
"shylinux.com/x/icebergs/base/mdb"
kit "shylinux.com/x/toolkits"
)
func _signal_init(m *ice.Message, arg ...string) {
_signal_listen(m, 1, mdb.NAME, START, ice.CMD, "runtime")
_signal_listen(m, 2, mdb.NAME, RESTART, ice.CMD, "exit 1")
_signal_listen(m, 3, mdb.NAME, STOP, ice.CMD, "exit 0")
_signal_listen(m, int(syscall.SIGUSR1), mdb.NAME, "info", ice.CMD, "runtime")
}
func SignalProcess(m *ice.Message, pid string) bool {
if proc, err := os.FindProcess(kit.Int(pid)); err == nil && proc.Signal(syscall.SIGUSR1) == nil {
return true
}
return false
}

View File

@ -0,0 +1,15 @@
package gdb
import (
ice "shylinux.com/x/icebergs"
"shylinux.com/x/icebergs/base/mdb"
)
func _signal_init(m *ice.Message, arg ...string) {
_signal_listen(m, 1, mdb.NAME, START, ice.CMD, "runtime")
_signal_listen(m, 2, mdb.NAME, RESTART, ice.CMD, "exit 1")
_signal_listen(m, 3, mdb.NAME, STOP, ice.CMD, "exit 0")
}
func SignalProcess(m *ice.Message, pid string) bool {
return false
}

View File

@ -5,6 +5,7 @@ import (
ice "shylinux.com/x/icebergs" ice "shylinux.com/x/icebergs"
"shylinux.com/x/icebergs/base/mdb" "shylinux.com/x/icebergs/base/mdb"
"shylinux.com/x/icebergs/base/web/html"
kit "shylinux.com/x/toolkits" kit "shylinux.com/x/toolkits"
) )
@ -14,11 +15,10 @@ func _timer_action(m *ice.Message, now time.Time, arg ...string) {
if count == 0 || value[mdb.TIME] > now.Format(ice.MOD_TIME) { if count == 0 || value[mdb.TIME] > now.Format(ice.MOD_TIME) {
return return
} }
m.Option(ice.LOG_DISABLE, ice.FALSE) m.Options(ice.LOG_DISABLE, ice.FALSE)
// m.Cmd(ROUTINE, mdb.CREATE, mdb.NAME, value[mdb.NAME], kit.Keycb(ROUTINE), value[ice.CMD])
m.Cmd(kit.Split(value[ice.CMD])).Cost() m.Cmd(kit.Split(value[ice.CMD])).Cost()
kit.If(count < 0, func() { count++ }) kit.If(count < 0, func() { count++ })
mdb.HashModify(m, mdb.HASH, value[mdb.HASH], mdb.COUNT, count-1, mdb.TIME, m.Time(value[INTERVAL])) mdb.HashModify(m, mdb.NAME, value[mdb.NAME], mdb.COUNT, count-1, mdb.TIME, m.Time(value[INTERVAL]))
}) })
} }
@ -31,7 +31,9 @@ const TIMER = "timer"
func init() { func init() {
Index.MergeCommands(ice.Commands{ Index.MergeCommands(ice.Commands{
TIMER: {Help: "定时器", Actions: ice.MergeActions(ice.Actions{ TIMER: {Help: "定时器", Meta: kit.Dict(
ice.CTX_TRANS, kit.Dict(html.INPUT, kit.Dict(DELAY, "延时", INTERVAL, "间隔", TICK, "周期")),
), Actions: ice.MergeActions(ice.Actions{
mdb.INPUTS: {Hand: func(m *ice.Message, arg ...string) { mdb.INPUTS: {Hand: func(m *ice.Message, arg ...string) {
switch mdb.HashInputs(m, arg); arg[0] { switch mdb.HashInputs(m, arg); arg[0] {
case mdb.COUNT: case mdb.COUNT:
@ -43,7 +45,8 @@ func init() {
mdb.CREATE: {Name: "create name*=hi delay=10ms interval=10s count=3 cmd*=runtime"}, mdb.CREATE: {Name: "create name*=hi delay=10ms interval=10s count=3 cmd*=runtime"},
mdb.PRUNES: {Hand: func(m *ice.Message, arg ...string) { mdb.HashPrunesValue(m, mdb.COUNT, "0") }}, mdb.PRUNES: {Hand: func(m *ice.Message, arg ...string) { mdb.HashPrunesValue(m, mdb.COUNT, "0") }},
HAPPEN: {Hand: func(m *ice.Message, arg ...string) { _timer_action(m, time.Now(), arg...) }}, HAPPEN: {Hand: func(m *ice.Message, arg ...string) { _timer_action(m, time.Now(), arg...) }},
RESTART: {Name: "restart count=3", Hand: func(m *ice.Message, arg ...string) { mdb.HashModify(m, m.OptionSimple(mdb.HashShort(m)), arg) }}, }, mdb.HashAction(mdb.SHORT, mdb.NAME, mdb.FIELD, "time,name,delay,interval,count,cmd", TICK, "10s")), Hand: func(m *ice.Message, arg ...string) {
}, mdb.HashAction(mdb.SHORT, mdb.NAME, mdb.FIELD, "time,name,delay,interval,count,cmd", TICK, "1s"))}, mdb.HashSelect(m, arg...).StatusTimeCount(mdb.ConfigSimple(m, TICK))
}},
}) })
} }

View File

@ -34,6 +34,7 @@ func _split_list(m *ice.Message, file string, arg ...string) ice.Map {
const INDENT = "_indent" const INDENT = "_indent"
stack, indent := []int{}, 0 stack, indent := []int{}, 0
list, line := kit.List(kit.Data(INDENT, -1)), "" list, line := kit.List(kit.Data(INDENT, -1)), ""
err := false
m.Cmd(nfs.CAT, file, func(text string) { m.Cmd(nfs.CAT, file, func(text string) {
if strings.TrimSpace(text) == "" { if strings.TrimSpace(text) == "" {
return return
@ -47,6 +48,9 @@ func _split_list(m *ice.Message, file string, arg ...string) ice.Map {
stack, indent = _split_deep(stack, text) stack, indent = _split_deep(stack, text)
data := kit.Data(INDENT, indent) data := kit.Data(INDENT, indent)
ls := kit.Split(text, m.Option(SPLIT_SPACE), m.Option(SPLIT_BLOCK), m.Option(SPLIT_QUOTE), m.Option(SPLIT_TRANS)) ls := kit.Split(text, m.Option(SPLIT_SPACE), m.Option(SPLIT_BLOCK), m.Option(SPLIT_QUOTE), m.Option(SPLIT_TRANS))
if err {
return
}
switch cb := m.OptionCB(SPLIT).(type) { switch cb := m.OptionCB(SPLIT).(type) {
case func(int, []string): case func(int, []string):
cb(indent, ls) cb(indent, ls)
@ -69,6 +73,7 @@ func _split_list(m *ice.Message, file string, arg ...string) ice.Map {
cb(indent, text, ls) cb(indent, text, ls)
case nil: case nil:
default: default:
err = true
m.ErrorNotImplement(cb) m.ErrorNotImplement(cb)
} }
kit.For(arg, func(k string) { kit.For(arg, func(k string) {

13
base/log/bench.go Normal file
View File

@ -0,0 +1,13 @@
package log
import (
ice "shylinux.com/x/icebergs"
)
const BENCH = "bench"
func init() {
Index.MergeCommands(ice.Commands{
BENCH: {Help: "记录", Hand: func(m *ice.Message, arg ...string) {}},
})
}

View File

@ -1,11 +1,13 @@
package log package log
import ( import (
"regexp"
"strings" "strings"
"time" "time"
"unicode" "unicode"
ice "shylinux.com/x/icebergs" ice "shylinux.com/x/icebergs"
"shylinux.com/x/icebergs/base/cli"
"shylinux.com/x/icebergs/base/ctx" "shylinux.com/x/icebergs/base/ctx"
"shylinux.com/x/icebergs/base/lex" "shylinux.com/x/icebergs/base/lex"
"shylinux.com/x/icebergs/base/mdb" "shylinux.com/x/icebergs/base/mdb"
@ -22,20 +24,24 @@ func init() {
LEVEL = "level" LEVEL = "level"
) )
Index.MergeCommands(ice.Commands{ Index.MergeCommands(ice.Commands{
DEBUG: {Name: "debug level=error,bench,debug,error,watch offset limit filter auto reset doc", Help: "后台日志", Actions: ice.Actions{ DEBUG: {Name: "debug level=error,bench,debug,error,watch offset limit auto reset app doc", Help: "日志", Actions: ice.Actions{
"doc": {Help: "文档", Hand: func(m *ice.Message, arg ...string) { m.ProcessOpen("https://pkg.go.dev/std") }}, "doc": {Help: "文档", Hand: func(m *ice.Message, arg ...string) { m.ProcessOpen("https://pkg.go.dev/std") }},
"reset": {Help: "重置", Hand: func(m *ice.Message, arg ...string) { "reset": {Help: "重置", Hand: func(m *ice.Message, arg ...string) {
m.Cmd(nfs.CAT, _debug_file(arg[0]), func(line string, index int) { m.ProcessRewrite(mdb.OFFSET, index+2, mdb.LIMIT, 1000) }) m.Cmd(nfs.CAT, _debug_file(arg[0]), func(line string, index int) { m.ProcessRewrite(mdb.OFFSET, index+2, mdb.LIMIT, 1000) })
}}, }},
"app": {Hand: func(m *ice.Message, arg ...string) {
cli.OpenCmds(m, kit.Format("cd %s", kit.Path("")), "tail -f var/log/bench.log")
}},
}, Hand: func(m *ice.Message, arg ...string) { }, Hand: func(m *ice.Message, arg ...string) {
offset, limit, stats := kit.Int(kit.Select("0", arg, 1)), kit.Int(kit.Select("1000", arg, 2)), map[string]int{} r := regexp.MustCompile("{.*}")
offset, limit := kit.Int(kit.Select("0", arg, 1)), kit.Int(kit.Select("100", arg, 2))
switch arg[0] { switch arg[0] {
case BENCH, ERROR, DEBUG: case BENCH, ERROR, DEBUG:
m.Cmd(nfs.CAT, _debug_file(arg[0]), func(text string, index int) { m.Cmd(nfs.CAT, _debug_file(arg[0]), func(text string, index int) {
if index < offset || index >= offset+limit || !strings.Contains(text, kit.Select("", arg, 3)) { if index < offset || index >= offset+limit || !strings.Contains(text, kit.Select("", arg, 3)) {
return return
} }
ls := strings.SplitN(strings.ReplaceAll(text, " ", " "), lex.SP, 8) ls := strings.SplitN(strings.ReplaceAll(strings.ReplaceAll(text, " ", " "), " ", " "), lex.SP, 8)
if _, e := time.Parse(kit.Split(ice.MOD_TIMES)[0], ls[0]); e != nil || len(ls) < 8 { if _, e := time.Parse(kit.Split(ice.MOD_TIMES)[0], ls[0]); e != nil || len(ls) < 8 {
m.Push(mdb.TIME, "").Push(ice.LOG_TRACEID, "").Push(mdb.ID, "") m.Push(mdb.TIME, "").Push(ice.LOG_TRACEID, "").Push(mdb.ID, "")
m.Push(nfs.PATH, "").Push(nfs.FILE, "").Push(nfs.LINE, "") m.Push(nfs.PATH, "").Push(nfs.FILE, "").Push(nfs.LINE, "")
@ -62,25 +68,27 @@ func init() {
ls[6], ls[7] = ls[6]+lex.SP+_ls[0], _ls[1] ls[6], ls[7] = ls[6]+lex.SP+_ls[0], _ls[1]
} }
} }
switch ls[6] {
case "recv", "done", "send", "echo":
ls[7] += "\n" + kit.Formats(kit.UnMarshal(r.FindString(ls[7])))
}
m.Push(ctx.SHIP, ls[5]).Push(LEVEL, ls[6]).Push(nfs.CONTENT, ls[7]) m.Push(ctx.SHIP, ls[5]).Push(LEVEL, ls[6]).Push(nfs.CONTENT, ls[7])
stats[ls[6]]++
}) })
case WATCH: case WATCH:
m.Cmd(nfs.CAT, ice.VAR_LOG+arg[0]+".log", func(text string, index int) { m.Cmd(nfs.CAT, ice.VAR_LOG+arg[0]+".log", func(text string, index int) {
if len(arg) > 2 && !strings.Contains(text, arg[2]) || index < offset { if index < offset || index >= offset+limit || !strings.Contains(text, kit.Select("", arg, 3)) {
return return
} }
ls := strings.SplitN(strings.ReplaceAll(text, " ", " "), lex.SP, 8) ls := strings.SplitN(strings.ReplaceAll(strings.ReplaceAll(text, " ", " "), " ", " "), lex.SP, 8)
m.Push(mdb.TIME, ls[0]+lex.SP+ls[1]).Push(ice.LOG_TRACEID, ls[3]).Push(mdb.ID, ls[4]) m.Push(mdb.TIME, ls[0]+lex.SP+ls[1]).Push(ice.LOG_TRACEID, ls[3]).Push(mdb.ID, ls[4])
i := strings.LastIndex(ls[7], lex.SP) i := strings.LastIndex(ls[7], lex.SP)
m.Push(nfs.PATH, ice.USR_ICEBERGS) m.Push(nfs.PATH, ice.USR_ICEBERGS)
m.Push(nfs.FILE, strings.TrimSpace(strings.Split(ls[7][i:], nfs.DF)[0])) m.Push(nfs.FILE, strings.TrimSpace(strings.Split(ls[7][i:], nfs.DF)[0]))
m.Push(nfs.LINE, strings.TrimSpace(strings.Split(ls[7][i:], nfs.DF)[1])) m.Push(nfs.LINE, strings.TrimSpace(strings.Split(ls[7][i:], nfs.DF)[1]))
m.Push(ctx.SHIP, ls[5]).Push(LEVEL, ls[6]).Push(nfs.CONTENT, ls[7][:i]) m.Push(ctx.SHIP, ls[5]).Push(LEVEL, ls[6]).Push(nfs.CONTENT, ls[7][:i])
stats[ls[6]]++
}) })
} }
m.StatusTimeCountTotal(offset+m.Length(), stats) m.StatusTimeCountStats(LEVEL)
}}, }},
}) })
} }

View File

@ -22,18 +22,24 @@ type Log struct {
type Frame struct{ p chan *Log } type Frame struct{ p chan *Log }
func (f *Frame) Begin(m *ice.Message, arg ...string) { func (f *Frame) Begin(m *ice.Message, arg ...string) {
f.p = make(chan *Log, ice.MOD_BUFS)
ice.Info.Log = func(m *ice.Message, p, l, s string) {
f.p <- &Log{c: m.Option(ice.LOG_DEBUG) == ice.TRUE, p: p, l: l, s: s}
}
} }
func (f *Frame) Start(m *ice.Message, arg ...string) { func (f *Frame) Start(m *ice.Message, arg ...string) {
if !ice.HasVar() {
return
}
mdb.Confm(m, FILE, nil, func(k string, v ice.Map) { mdb.Confm(m, FILE, nil, func(k string, v ice.Map) {
if mdb.Conf(m, k, kit.Keym(mdb.DISABLE)) == ice.TRUE {
return
}
if f, p, e := logs.CreateFile(kit.Format(v[nfs.PATH])); e == nil { if f, p, e := logs.CreateFile(kit.Format(v[nfs.PATH])); e == nil {
m.Logs(nfs.SAVE, nfs.FILE, p) m.Logs(nfs.SAVE, nfs.FILE, p)
v[FILE] = bufio.NewWriter(f) v[FILE] = bufio.NewWriter(f)
} }
}) })
f.p = make(chan *Log, ice.MOD_BUFS)
ice.Info.Log = func(m *ice.Message, p, l, s string) {
f.p <- &Log{c: m.Option(ice.LOG_DEBUG) == ice.TRUE, p: p, l: l, s: s}
}
for { for {
select { select {
case l, ok := <-f.p: case l, ok := <-f.p:
@ -44,7 +50,8 @@ func (f *Frame) Start(m *ice.Message, arg ...string) {
if file == "" { if file == "" {
return return
} }
bio := m.Confv(FILE, kit.Keys(file, FILE)).(*bufio.Writer) conf := m.Confv(FILE, file)
bio := kit.Value(conf, FILE).(*bufio.Writer)
if bio == nil { if bio == nil {
return return
} }
@ -59,10 +66,7 @@ func (f *Frame) Start(m *ice.Message, arg ...string) {
} }
} }
} }
func (f *Frame) Close(m *ice.Message, arg ...string) { func (f *Frame) Close(m *ice.Message, arg ...string) { ice.Info.Log = nil; close(f.p) }
ice.Info.Log = nil
close(f.p)
}
const ( const (
PREFIX = "prefix" PREFIX = "prefix"
@ -74,22 +78,25 @@ const (
YELLOW = "yellow" YELLOW = "yellow"
RED = "red" RED = "red"
) )
const (
BENCH = "bench"
)
const ( const (
FILE = "file" FILE = "file"
VIEW = "view" VIEW = "view"
SHOW = "show" SHOW = "show"
) )
const (
BENCH_LOG = "bench.log"
DEBUG_LOG = "debug.log"
ERROR_LOG = "error.log"
WATCH_LOG = "watch.log"
)
const LOG = "log" const LOG = "log"
var Index = &ice.Context{Name: LOG, Help: "日志模块", Configs: ice.Configs{ var Index = &ice.Context{Name: LOG, Help: "日志模块", Configs: ice.Configs{
FILE: {Name: FILE, Help: "日志文件", Value: kit.Dict( FILE: {Name: FILE, Help: "日志文件", Value: kit.Dict(
BENCH, kit.Dict(nfs.PATH, path.Join(ice.VAR_LOG, "bench.log"), mdb.LIST, []string{}), BENCH, kit.Dict(nfs.PATH, path.Join(ice.VAR_LOG, BENCH_LOG), mdb.LIST, []string{}),
DEBUG, kit.Dict(nfs.PATH, path.Join(ice.VAR_LOG, "debug.log"), mdb.LIST, []string{ice.LOG_DEBUG}), DEBUG, kit.Dict(nfs.PATH, path.Join(ice.VAR_LOG, DEBUG_LOG), mdb.LIST, []string{ice.LOG_DEBUG}),
ERROR, kit.Dict(nfs.PATH, path.Join(ice.VAR_LOG, "error.log"), mdb.LIST, []string{ice.LOG_WARN, ice.LOG_ERROR}), ERROR, kit.Dict(nfs.PATH, path.Join(ice.VAR_LOG, ERROR_LOG), mdb.LIST, []string{ice.LOG_WARN, ice.LOG_ERROR}),
WATCH, kit.Dict(nfs.PATH, path.Join(ice.VAR_LOG, "watch.log"), mdb.LIST, []string{mdb.CREATE, mdb.REMOVE, mdb.INSERT, mdb.DELETE, mdb.MODIFY, mdb.EXPORT, mdb.IMPORT}), WATCH, kit.Dict(nfs.PATH, path.Join(ice.VAR_LOG, WATCH_LOG), mdb.LIST, []string{mdb.CREATE, mdb.REMOVE, mdb.INSERT, mdb.DELETE, mdb.MODIFY, mdb.EXPORT, mdb.IMPORT}),
)}, )},
VIEW: {Name: VIEW, Help: "日志格式", Value: kit.Dict( VIEW: {Name: VIEW, Help: "日志格式", Value: kit.Dict(
GREEN, kit.Dict(PREFIX, "\033[32m", SUFFIX, "\033[0m", mdb.LIST, []string{ice.CTX_START, ice.LOG_CMDS}), GREEN, kit.Dict(PREFIX, "\033[32m", SUFFIX, "\033[0m", mdb.LIST, []string{ice.CTX_START, ice.LOG_CMDS}),
@ -99,7 +106,7 @@ var Index = &ice.Context{Name: LOG, Help: "日志模块", Configs: ice.Configs{
SHOW: {Name: SHOW, Help: "日志分流", Value: kit.Dict()}, SHOW: {Name: SHOW, Help: "日志分流", Value: kit.Dict()},
}, Commands: ice.Commands{ }, Commands: ice.Commands{
ice.CTX_INIT: {Hand: func(m *ice.Message, arg ...string) { ice.CTX_INIT: {Hand: func(m *ice.Message, arg ...string) {
ice.Info.Load(m, TAIL) ice.Info.Load(m)
mdb.Confm(m, FILE, nil, func(key string, value ice.Map) { mdb.Confm(m, FILE, nil, func(key string, value ice.Map) {
kit.For(value[mdb.LIST], func(index int, k string) { m.Conf(SHOW, kit.Keys(k, FILE), key) }) kit.For(value[mdb.LIST], func(index int, k string) { m.Conf(SHOW, kit.Keys(k, FILE), key) })
}) })
@ -107,34 +114,40 @@ var Index = &ice.Context{Name: LOG, Help: "日志模块", Configs: ice.Configs{
kit.For(value[mdb.LIST], func(index int, k string) { m.Conf(SHOW, kit.Keys(k, VIEW), key) }) kit.For(value[mdb.LIST], func(index int, k string) { m.Conf(SHOW, kit.Keys(k, VIEW), key) })
}) })
}}, }},
ice.CTX_EXIT: {Hand: func(m *ice.Message, arg ...string) { ice.Info.Save(m, TAIL) }}, ice.CTX_EXIT: {Hand: func(m *ice.Message, arg ...string) {
ice.Info.Save(m)
}},
}} }}
func init() { ice.Index.Register(Index, &Frame{}, TAIL) } func init() { ice.Index.Register(Index, &Frame{}, TAIL) }
func init() { func init() {
ice.Info.Traceid = "short" ice.Info.Traceid = "short"
ice.Pulse.Option(ice.LOG_TRACEID, Traceid()) ice.Pulse.Option("work.id", "0")
ice.Pulse.Option("task.id", "0")
ice.Pulse.Option(ice.LOG_TRACEID, Traceid(ice.Pulse))
} }
var _trace_count int64 var _trace_count int64
func Traceid() (traceid string) { func Traceid(m *ice.Message) (traceid string) {
ls := []string{} ls := []string{}
kit.For(kit.Split(ice.Info.Traceid), func(key string) { kit.For(kit.Split(ice.Info.Traceid), func(key string) {
switch key { switch key {
case "short": case "short":
ls = append(ls, kit.Hashs(mdb.UNIQ)[:6]) if len(ls) == 0 {
ls = append(ls, kit.Hashs(mdb.UNIQ)[:6])
}
case "long": case "long":
ls = append(ls, kit.Hashs(mdb.UNIQ)) if len(ls) == 0 {
ls = append(ls, kit.Hashs(mdb.UNIQ))
}
case "node": case "node":
ls = append(ls, ice.Info.NodeName) ls = append(ls, ice.Info.NodeName)
case "hide": case "hide":
ls = ls[:0] ls = ls[:0]
} }
}) })
kit.If(len(ls) > 0, func() { kit.If(len(ls) > 0, func() { ls = append(ls, kit.Format(atomic.AddInt64(&_trace_count, 1))) })
ls = append(ls, kit.Format(atomic.AddInt64(&_trace_count, 1)))
})
return strings.Join(ls, "-") return strings.Join(ls, "-")
} }

View File

@ -20,7 +20,7 @@ const TAIL = "tail"
func init() { func init() {
Index.MergeCommands(ice.Commands{ Index.MergeCommands(ice.Commands{
TAIL: {Name: "tail name id auto page create", Help: "日志流", Actions: ice.MergeActions(ice.Actions{ TAIL: {Name: "tail name id auto page", Help: "日志流", Actions: ice.MergeActions(ice.Actions{
ice.CTX_INIT: {Hand: func(m *ice.Message, arg ...string) { ice.CTX_INIT: {Hand: func(m *ice.Message, arg ...string) {
mdb.HashSelect(m.Spawn(ice.OptionFields("name,file"))).Table(func(value ice.Maps) { mdb.HashSelect(m.Spawn(ice.OptionFields("name,file"))).Table(func(value ice.Maps) {
m.Cmd("", mdb.CREATE, kit.SimpleKV("name,file", value)) m.Cmd("", mdb.CREATE, kit.SimpleKV("name,file", value))

View File

@ -23,7 +23,7 @@ func init() {
m.Push(ctx.SHIP, ls[3]).Push("operate", ls[4]).Push(nfs.CONTENT, kit.Join(kit.Slice(ls, 5, -1), lex.SP)) m.Push(ctx.SHIP, ls[3]).Push("operate", ls[4]).Push(nfs.CONTENT, kit.Join(kit.Slice(ls, 5, -1), lex.SP))
stats[ls[4]]++ stats[ls[4]]++
}) })
m.Action("filter:text").StatusTimeCount(stats) m.StatusTimeCount(stats)
}}, }},
}) })
} }

View File

@ -3,11 +3,12 @@ package mdb
import ( import (
"encoding/json" "encoding/json"
"io" "io"
"os" "net/http"
"path" "path"
"strings" "strings"
ice "shylinux.com/x/icebergs" ice "shylinux.com/x/icebergs"
"shylinux.com/x/icebergs/base/web/html"
kit "shylinux.com/x/toolkits" kit "shylinux.com/x/toolkits"
"shylinux.com/x/toolkits/logs" "shylinux.com/x/toolkits/logs"
"shylinux.com/x/toolkits/miss" "shylinux.com/x/toolkits/miss"
@ -38,16 +39,11 @@ func _hash_insert(m *ice.Message, prefix, chain string, arg ...string) string {
if arg[0] == HASH { if arg[0] == HASH {
m.Echo(arg[1]).Conf(prefix, kit.Keys(chain, HASH, arg[1]), kit.Data(arg[2:])) m.Echo(arg[1]).Conf(prefix, kit.Keys(chain, HASH, arg[1]), kit.Data(arg[2:]))
} else { } else {
func() { if target, ok := m.Optionv(TARGET).([]string); ok && len(target) == 0 {
switch target := m.Optionv(TARGET).(type) { m.Echo(Rich(m, prefix, chain, kit.Data(arg)))
case []string: } else {
if len(target) == 0 {
m.Echo(Rich(m, prefix, chain, kit.Data(arg)))
return
}
}
m.Echo(Rich(m, prefix, chain, kit.Data(arg, TARGET, m.Optionv(TARGET)))) m.Echo(Rich(m, prefix, chain, kit.Data(arg, TARGET, m.Optionv(TARGET))))
}() }
} }
saveImportant(m, prefix, chain, kit.Simple(INSERT, prefix, chain, HASH, HASH, m.Result(), TIME, m.Time(), arg)...) saveImportant(m, prefix, chain, kit.Simple(INSERT, prefix, chain, HASH, HASH, m.Result(), TIME, m.Time(), arg)...)
return m.Result() return m.Result()
@ -58,17 +54,17 @@ func _hash_delete(m *ice.Message, prefix, chain, field, value string) {
if target, ok := kit.GetMeta(val)[TARGET].(io.Closer); ok { if target, ok := kit.GetMeta(val)[TARGET].(io.Closer); ok {
target.Close() target.Close()
} }
saveImportant(m, prefix, chain, kit.Simple(DELETE, prefix, chain, HASH, HASH, key)...)
m.Logs(DELETE, KEY, path.Join(prefix, chain), field, value, VALUE, kit.Format(val)) m.Logs(DELETE, KEY, path.Join(prefix, chain), field, value, VALUE, kit.Format(val))
m.Conf(prefix, kit.Keys(chain, HASH, key), "") m.Conf(prefix, kit.Keys(chain, HASH, key), "")
saveImportant(m, prefix, chain, kit.Simple(DELETE, prefix, chain, HASH, HASH, key)...)
}) })
} }
func _hash_modify(m *ice.Message, prefix, chain string, field, value string, arg ...string) { func _hash_modify(m *ice.Message, prefix, chain string, field, value string, arg ...string) {
m.Logs(MODIFY, KEY, path.Join(prefix, chain), field, value, arg) m.Logs(MODIFY, KEY, path.Join(prefix, chain), field, value, arg)
defer Lock(m, prefix)() defer Lock(m, prefix)()
Richs(m, prefix, chain, value, func(key string, val Map) { Richs(m, prefix, chain, value, func(key string, val Map) {
saveImportant(m, prefix, chain, kit.Simple(MODIFY, prefix, chain, HASH, HASH, key, arg)...)
_mdb_modify(m, val, field, arg...) _mdb_modify(m, val, field, arg...)
saveImportant(m, prefix, chain, kit.Simple(MODIFY, prefix, chain, HASH, HASH, key, arg)...)
}) })
} }
func _hash_select(m *ice.Message, prefix, chain, field, value string) { func _hash_select(m *ice.Message, prefix, chain, field, value string) {
@ -76,7 +72,13 @@ func _hash_select(m *ice.Message, prefix, chain, field, value string) {
defer m.SortStrR(TIME) defer m.SortStrR(TIME)
fields := _hash_fields(m) fields := _hash_fields(m)
defer RLock(m, prefix)() defer RLock(m, prefix)()
Richs(m, prefix, chain, value, func(key string, value Map) { _mdb_select(m, m.OptionCB(""), key, value, fields, nil) }) if strings.Contains(value, ",") {
kit.For(kit.Split(value), func(value string) {
Richs(m, prefix, chain, value, func(key string, value Map) { _mdb_select(m, m.OptionCB(""), key, value, fields, nil) })
})
} else {
Richs(m, prefix, chain, value, func(key string, value Map) { _mdb_select(m, m.OptionCB(""), key, value, fields, nil) })
}
} }
func _hash_select_field(m *ice.Message, prefix, chain string, key string, field string) (value string) { func _hash_select_field(m *ice.Message, prefix, chain string, key string, field string) (value string) {
defer RLock(m, prefix)() defer RLock(m, prefix)()
@ -99,36 +101,37 @@ func _hash_prunes(m *ice.Message, prefix, chain string, arg ...string) {
}) })
} }
func _hash_export(m *ice.Message, prefix, chain, file string) { func _hash_export(m *ice.Message, prefix, chain, file string) {
defer Lock(m, prefix)() if !ice.HasUsr() {
count := len(Confm(m, prefix, kit.Keys(chain, HASH)))
p := kit.Keys(file, JSON)
if count == 0 {
if s, e := os.Stat(p); e == nil && !s.IsDir() {
os.Remove(p)
}
return return
} }
f, p, e := miss.CreateFile(p) defer Lock(m, prefix)()
if len(Confm(m, prefix, kit.Keys(chain, HASH))) == 0 {
return
}
f, p, e := miss.CreateFile(kit.Keys(file, JSON))
m.Assert(e) m.Assert(e)
defer f.Close() defer f.Close()
defer m.Echo(p) defer m.Echo(p)
m.Logs(EXPORT, KEY, path.Join(prefix, chain), FILE, p, COUNT, count) m.Logs(EXPORT, KEY, path.Join(prefix, chain), FILE, p)
en := json.NewEncoder(f) en := json.NewEncoder(f)
if en.SetIndent("", " "); !m.Warn(en.Encode(m.Confv(prefix, kit.Keys(chain, HASH))), EXPORT, prefix) { if en.SetIndent("", " "); !m.WarnNotValid(en.Encode(m.Confv(prefix, kit.Keys(chain, HASH))), EXPORT, prefix) {
m.Conf(prefix, kit.Keys(chain, HASH), "") // m.Conf(prefix, kit.Keys(chain, HASH), "")
} }
} }
func _hash_import(m *ice.Message, prefix, chain, file string) { func _hash_import(m *ice.Message, prefix, chain, file string) {
if !ice.HasUsr() {
return
}
defer Lock(m, prefix)() defer Lock(m, prefix)()
f, e := ice.Info.Open(m, kit.Keys(file, JSON)) f, e := miss.OpenFile(kit.Keys(file, JSON))
if e != nil && !ice.Info.Important { if e != nil && !ice.Info.Important {
return return
} else if m.Warn(e) { } else if m.WarnNotFound(e) {
return return
} }
defer f.Close() defer f.Close()
data := Map{} data := Map{}
m.Assert(json.NewDecoder(f).Decode(&data)) m.Warn(json.NewDecoder(f).Decode(&data))
m.Logs(IMPORT, KEY, path.Join(prefix, chain), FILE, kit.Keys(file, JSON), COUNT, len(data)) m.Logs(IMPORT, KEY, path.Join(prefix, chain), FILE, kit.Keys(file, JSON), COUNT, len(data))
kit.If(m.Confv(prefix, kit.Keys(chain, HASH)) == nil, func() { m.Confv(prefix, kit.Keys(chain, HASH), ice.Map{}) }) kit.If(m.Confv(prefix, kit.Keys(chain, HASH)) == nil, func() { m.Confv(prefix, kit.Keys(chain, HASH), ice.Map{}) })
kit.For(data, func(k string, v Any) { m.Confv(prefix, kit.Keys(chain, HASH, k), v) }) kit.For(data, func(k string, v Any) { m.Confv(prefix, kit.Keys(chain, HASH, k), v) })
@ -181,6 +184,45 @@ func ExportHashAction(arg ...Any) ice.Actions {
}, HashAction(arg...)) }, HashAction(arg...))
} }
const (
DEV_REQUEST = "devRequest"
DEV_CHOOSE = "devChoose"
DEV_RESPONSE = "devResponse"
DEV_CONFIRM = "devConfirm"
DEV_CREATE = "devCreate"
)
func DevDataAction(fields ...string) ice.Actions {
const (
DAEMON = "daemon"
ORIGIN = "origin"
BACK = "back"
)
return ice.Actions{
DEV_REQUEST: {Name: "request origin*", Help: "请求", Icon: "bi bi-cloud-download", Hand: func(m *ice.Message, arg ...string) {
back := m.Options(ice.MSG_USERWEB, m.Option(ice.MSG_USERHOST)).MergePod("")
m.ProcessOpen(m.Options(ice.MSG_USERWEB, m.Option(ORIGIN), ice.MSG_USERPOD, "").MergePodCmd("", m.PrefixKey(), ACTION, DEV_CHOOSE, BACK, back, DAEMON, m.Option(ice.MSG_DAEMON)))
}},
DEV_CHOOSE: {Hand: func(m *ice.Message, arg ...string) {
HashSelect(m.Options(ice.MSG_FIELDS, kit.Join(fields))).PushAction(DEV_RESPONSE).Options(ice.MSG_ACTION, "")
}},
DEV_RESPONSE: {Help: "选择", Hand: func(m *ice.Message, arg ...string) {
if !m.WarnNotAllow(m.Option(ice.MSG_METHOD) != http.MethodPost) {
m.ProcessReplace(m.ParseLink(m.Option(BACK)).MergePodCmd("", m.PrefixKey(), ACTION, DEV_CONFIRM, m.OptionSimple(DAEMON), m.OptionSimple(fields...)))
}
}},
DEV_CONFIRM: {Hand: func(m *ice.Message, arg ...string) {
m.EchoInfoButton(kit.JoinWord(m.PrefixKey(), m.Cmdx("nfs.cat", "src/template/mdb.hash/savefrom.html"), m.Option(kit.Split(fields[0])[0])), DEV_CREATE)
}},
DEV_CREATE: {Help: "创建", Hand: func(m *ice.Message, arg ...string) {
if !m.WarnNotAllow(m.Option(ice.MSG_METHOD) != http.MethodPost) {
defer kit.If(m.Option(DAEMON), func(p string) { m.Cmd("space", p, "refresh") })
HashCreate(m.ProcessClose(), m.OptionSimple(fields...))
}
}},
}
}
func HashKey(m *ice.Message) string { func HashKey(m *ice.Message) string {
if m.Option(HASH) != "" { if m.Option(HASH) != "" {
return HASH return HASH
@ -191,19 +233,38 @@ func HashShort(m *ice.Message) string {
if m.Option(SHORT) != "" { if m.Option(SHORT) != "" {
return m.Option(SHORT) return m.Option(SHORT)
} }
return kit.Select(HASH, Config(m, SHORT), Config(m, SHORT) != UNIQ) short := ""
if m.Option(SUBKEY) != "" {
if short = Conf(m, m.PrefixKey(), kit.Keys(m.Option(SUBKEY), META, SHORT)); short == "" {
short = Config(m, SHORTS)
}
} else {
short = Config(m, SHORT)
}
return kit.Select(HASH, short, short != UNIQ)
} }
func HashField(m *ice.Message) string { func HashField(m *ice.Message) string {
if m.Option(FIELD) != "" { if m.Option(FIELD) != "" {
return m.Option(FIELD) return m.Option(FIELD)
} }
return kit.Select(HASH_FIELD, Config(m, FIELD)) field := ""
if m.Option(SUBKEY) != "" {
if field = Conf(m, m.PrefixKey(), kit.Keys(m.Option(SUBKEY), META, FIELDS)); field == "" {
field = Config(m, FIELDS)
}
} else {
field = Config(m, FIELD)
}
return kit.Select(HASH_FIELD, field)
} }
func HashInputs(m *ice.Message, arg ...Any) *ice.Message { func HashInputs(m *ice.Message, arg ...Any) *ice.Message {
return m.Cmdy(INPUTS, m.PrefixKey(), m.Option(SUBKEY), HASH, arg) return m.Cmdy(INPUTS, m.PrefixKey(), m.Option(SUBKEY), HASH, arg)
} }
func HashCreate(m *ice.Message, arg ...Any) string { func HashCreate(m *ice.Message, arg ...Any) string {
kit.If(len(arg) == 0 || len(kit.Simple(arg...)) == 0, func() { arg = append(arg, m.OptionSimple(strings.Replace(HashField(m), "hash,", "", 1))) }) kit.If(len(arg) == 0 || len(kit.Simple(arg...)) == 0, func() {
arg = append(arg, m.OptionSimple(kit.Filters(kit.Split(HashField(m)), TIME, HASH)...))
})
kit.If(m.Option(SUBKEY) == "", func() { kit.If(Config(m, SHORTS), func(p string) { arg = append([]ice.Any{SHORT, p}, arg) }) })
return m.Echo(m.Cmdx(append(kit.List(INSERT, m.PrefixKey(), m.Option(SUBKEY), HASH, logs.FileLineMeta(-1)), arg...)...)).Result() return m.Echo(m.Cmdx(append(kit.List(INSERT, m.PrefixKey(), m.Option(SUBKEY), HASH, logs.FileLineMeta(-1)), arg...)...)).Result()
} }
func HashRemove(m *ice.Message, arg ...Any) *ice.Message { func HashRemove(m *ice.Message, arg ...Any) *ice.Message {
@ -221,7 +282,7 @@ func HashModify(m *ice.Message, arg ...Any) *ice.Message {
return m.Cmd(MODIFY, m.PrefixKey(), m.Option(SUBKEY), HASH, arg) return m.Cmd(MODIFY, m.PrefixKey(), m.Option(SUBKEY), HASH, arg)
} }
func HashSelect(m *ice.Message, arg ...string) *ice.Message { func HashSelect(m *ice.Message, arg ...string) *ice.Message {
if len(arg) > 0 && arg[0] == FOREACH { if len(arg) > 0 && (arg[0] == FOREACH || strings.Contains(arg[0], ",")) {
m.Fields(0, HashField(m)) m.Fields(0, HashField(m))
} else { } else {
m.Fields(len(kit.Slice(arg, 0, 1)), HashField(m)) m.Fields(len(kit.Slice(arg, 0, 1)), HashField(m))
@ -229,9 +290,10 @@ func HashSelect(m *ice.Message, arg ...string) *ice.Message {
m.Cmdy(SELECT, m.PrefixKey(), m.Option(SUBKEY), HASH, HashShort(m), arg, logs.FileLineMeta(-1)) m.Cmdy(SELECT, m.PrefixKey(), m.Option(SUBKEY), HASH, HashShort(m), arg, logs.FileLineMeta(-1))
kit.If(kit.Select(Config(m, SHORT), Config(m, SORT)), func(sort string) { kit.If(sort != UNIQ, func() { m.Sort(sort) }) }) kit.If(kit.Select(Config(m, SHORT), Config(m, SORT)), func(sort string) { kit.If(sort != UNIQ, func() { m.Sort(sort) }) })
if m.PushAction(Config(m, ACTION), REMOVE); !m.FieldsIsDetail() { if m.PushAction(Config(m, ACTION), REMOVE); !m.FieldsIsDetail() {
return m.Action(CREATE, PRUNES) m.Options(ice.TABLE_CHECKBOX, Config(m, html.CHECKBOX))
return m.Action(CREATE)
} }
return m return sortByField(m, HashField(m), arg...)
} }
func HashPrunes(m *ice.Message, cb func(Map) bool) *ice.Message { func HashPrunes(m *ice.Message, cb func(Map) bool) *ice.Message {
expire := kit.Select(m.Time("-"+kit.Select(DAYS, Config(m, EXPIRE))), m.Option("before")) expire := kit.Select(m.Time("-"+kit.Select(DAYS, Config(m, EXPIRE))), m.Option("before"))
@ -291,7 +353,7 @@ func HashSelectTarget(m *ice.Message, key string, create Any) (target Any) {
} }
switch create := create.(type) { switch create := create.(type) {
case func(Maps) Any: case func(Maps) Any:
target = create(ToMaps(value)) target = create(kit.ToMaps(value))
case func(Map) Any: case func(Map) Any:
target = create(value) target = create(value)
case func() Any: case func() Any:
@ -306,7 +368,7 @@ func HashSelectTarget(m *ice.Message, key string, create Any) (target Any) {
func HashSelectClose(m *ice.Message) *ice.Message { func HashSelectClose(m *ice.Message) *ice.Message {
HashSelectValue(m, func(value Map) { HashSelectValue(m, func(value Map) {
if c, ok := value[TARGET].(io.Closer); ok { if c, ok := value[TARGET].(io.Closer); ok {
m.Warn(c.Close()) m.WarnNotValid(c.Close())
} }
delete(value, TARGET) delete(value, TARGET)
}) })
@ -329,6 +391,12 @@ func Richs(m *ice.Message, prefix string, chain Any, raw Any, cb Any) (res Map)
if cache == nil { if cache == nil {
return nil return nil
} }
if value := kit.Format(raw); strings.Contains(value, ",") {
kit.For(kit.Split(value), func(value string) {
res = miss.Richs(path.Join(prefix, kit.Keys(chain)), cache, value, cb)
})
return
}
return miss.Richs(path.Join(prefix, kit.Keys(chain)), cache, raw, cb) return miss.Richs(path.Join(prefix, kit.Keys(chain)), cache, raw, cb)
} }
@ -337,3 +405,18 @@ func Rich(m *ice.Message, prefix string, chain Any, data Any) string {
kit.If(cache == nil, func() { cache = kit.Data(); m.Confv(prefix, chain, cache) }) kit.If(cache == nil, func() { cache = kit.Data(); m.Confv(prefix, chain, cache) })
return miss.Rich(path.Join(prefix, kit.Keys(chain)), cache, data) return miss.Rich(path.Join(prefix, kit.Keys(chain)), cache, data)
} }
func sortByField(m *ice.Message, fields string, arg ...string) *ice.Message {
return m.Table(func(value ice.Maps) {
m.SetAppend().FieldsSetDetail()
kit.For(kit.Split(fields), func(key string) {
key = strings.TrimSuffix(key, "*")
if key == HASH {
m.Push(key, kit.Select(value[key], arg, 0))
} else {
m.Push(key, value[key])
}
delete(value, key)
})
kit.For(kit.SortedKey(value), func(k string) { m.Push(k, value[k]) })
})
}

View File

@ -2,6 +2,7 @@ package mdb
import ( import (
"encoding/csv" "encoding/csv"
"os"
"path" "path"
"strings" "strings"
@ -29,14 +30,14 @@ func _list_inputs(m *ice.Message, prefix, chain string, field, value string) {
func _list_insert(m *ice.Message, prefix, chain string, arg ...string) { func _list_insert(m *ice.Message, prefix, chain string, arg ...string) {
m.Logs(INSERT, KEY, path.Join(prefix, chain), arg) m.Logs(INSERT, KEY, path.Join(prefix, chain), arg)
defer Lock(m, prefix)() defer Lock(m, prefix)()
saveImportant(m, prefix, chain, kit.Simple(INSERT, prefix, chain, LIST, TIME, m.Time(), arg)...)
m.Echo("%d", Grow(m, prefix, chain, kit.Dict(arg, TARGET, m.Optionv(TARGET)))) m.Echo("%d", Grow(m, prefix, chain, kit.Dict(arg, TARGET, m.Optionv(TARGET))))
saveImportant(m, prefix, chain, kit.Simple(INSERT, prefix, chain, LIST, TIME, m.Time(), arg)...)
} }
func _list_modify(m *ice.Message, prefix, chain string, field, value string, arg ...string) { func _list_modify(m *ice.Message, prefix, chain string, field, value string, arg ...string) {
m.Logs(MODIFY, KEY, path.Join(prefix, chain), field, value, arg) m.Logs(MODIFY, KEY, path.Join(prefix, chain), field, value, arg)
defer Lock(m, prefix)() defer Lock(m, prefix)()
saveImportant(m, prefix, chain, kit.Simple(MODIFY, prefix, chain, LIST, field, value, arg)...)
Grows(m, prefix, chain, field, value, func(index int, val ice.Map) { _mdb_modify(m, val, field, arg...) }) Grows(m, prefix, chain, field, value, func(index int, val ice.Map) { _mdb_modify(m, val, field, arg...) })
saveImportant(m, prefix, chain, kit.Simple(MODIFY, prefix, chain, LIST, field, value, arg)...)
} }
func _list_select(m *ice.Message, prefix, chain, field, value string) { func _list_select(m *ice.Message, prefix, chain, field, value string) {
defer m.SortIntR(ID) defer m.SortIntR(ID)
@ -48,29 +49,40 @@ func _list_select(m *ice.Message, prefix, chain, field, value string) {
} }
func _list_export(m *ice.Message, prefix, chain, file string) { func _list_export(m *ice.Message, prefix, chain, file string) {
defer Lock(m, prefix)() defer Lock(m, prefix)()
f, p, e := miss.CreateFile(kit.Keys(file, CSV)) p := kit.Keys(file, CSV)
count := kit.Int(Conf(m, prefix, kit.Keys(chain, META, COUNT)))
if count == 0 {
if s, e := os.Stat(p); e == nil && !s.IsDir() {
os.Remove(p)
}
return
}
f, p, e := miss.CreateFile(p)
m.Assert(e) m.Assert(e)
defer f.Close() defer f.Close()
defer m.Echo(p) defer m.Echo(p)
m.Logs(EXPORT, KEY, path.Join(prefix, chain), FILE, p, COUNT, count)
w := csv.NewWriter(f) w := csv.NewWriter(f)
defer w.Flush() defer w.Flush()
count, head := 0, kit.Split(ListField(m)) head := kit.Split(ListField(m))
Grows(m, prefix, chain, "", "", func(index int, value ice.Map) { Grows(m, prefix, chain, "", "", func(index int, value ice.Map) {
if value = kit.GetMeta(value); index == 0 { if value = kit.GetMeta(value); index == 0 {
kit.If(len(head) == 0 || head[0] == ice.FIELDS_DETAIL, func() { head = kit.SortedKey(value) }) kit.If(len(head) == 0 || head[0] == ice.FIELDS_DETAIL, func() { head = kit.SortedKey(value) })
w.Write(head) w.Write(head)
} }
w.Write(kit.Simple(head, func(k string) string { return kit.Format(value[k]) })) w.Write(kit.Simple(head, func(k string) string { return kit.Format(value[k]) }))
count++
}) })
m.Logs(EXPORT, KEY, path.Join(prefix, chain), FILE, p, COUNT, count)
m.Conf(prefix, kit.Keys(chain, kit.Keym(COUNT)), 0) m.Conf(prefix, kit.Keys(chain, kit.Keym(COUNT)), 0)
m.Conf(prefix, kit.Keys(chain, LIST), "") m.Conf(prefix, kit.Keys(chain, LIST), "")
} }
func _list_import(m *ice.Message, prefix, chain, file string) { func _list_import(m *ice.Message, prefix, chain, file string) {
defer Lock(m, prefix)() defer Lock(m, prefix)()
f, e := miss.OpenFile(kit.Keys(file, CSV)) f, e := miss.OpenFile(kit.Keys(file, CSV))
m.Assert(e) if e != nil && !ice.Info.Important {
return
} else if m.WarnNotFound(e) {
return
}
defer f.Close() defer f.Close()
r := csv.NewReader(f) r := csv.NewReader(f)
head, _ := r.Read() head, _ := r.Read()
@ -195,31 +207,23 @@ const (
CACHE_FIELD = "cache.field" CACHE_FIELD = "cache.field"
) )
type Message interface { func Grows(m *ice.Message, prefix string, chain Any, match string, value string, cb Any) Map {
Confv(arg ...Any) (val Any)
Option(key string, arg ...Any) string
}
func Grows(m Message, prefix string, chain Any, match string, value string, cb Any) Map {
cache, ok := m.Confv(prefix, chain).(ice.Map) cache, ok := m.Confv(prefix, chain).(ice.Map)
if cache == nil || !ok { if cache == nil || !ok {
return nil return nil
} } else if begin, limit := kit.Int(m.Option(CACHE_BEGIN)), kit.Int(m.Option(CACHE_LIMIT)); begin != 0 && limit > 0 {
limit := kit.Int(m.Option(CACHE_LIMIT)) if count := kit.Int(m.Option(CACHE_COUNT, kit.Int(kit.Value(cache, kit.Keym(COUNT))))); count-begin < limit {
if begin := kit.Int(m.Option(CACHE_BEGIN)); begin != 0 && limit > 0 { m.Option(CACHE_OFFEND, 0)
count := kit.Int(m.Option(CACHE_COUNT, kit.Int(kit.Value(cache, kit.Keym("count"))))) m.Option(CACHE_LIMIT, count-begin+1)
if begin > 0 {
m.Option(CACHE_OFFEND, count-begin-limit)
} else { } else {
m.Option(CACHE_OFFEND, -begin-limit) m.Option(CACHE_OFFEND, count-begin-limit+1)
} }
} }
return miss.Grows(path.Join(prefix, kit.Keys(chain)), cache, return miss.Grows(path.Join(prefix, kit.Keys(chain)), cache,
kit.Int(kit.Select("0", strings.TrimPrefix(m.Option(CACHE_OFFEND), "-"))), kit.Int(kit.Select("0", strings.TrimPrefix(m.Option(CACHE_OFFEND), "-"))),
kit.Int(kit.Select("10", m.Option(CACHE_LIMIT))), kit.Int(kit.Select("10", m.Option(CACHE_LIMIT))), match, value, cb)
match, value, cb)
} }
func Grow(m Message, prefix string, chain Any, data Any) int { func Grow(m *ice.Message, prefix string, chain Any, data Any) int {
cache, ok := m.Confv(prefix, chain).(ice.Map) cache, ok := m.Confv(prefix, chain).(ice.Map)
if cache == nil || !ok { if cache == nil || !ok {
cache = kit.Data() cache = kit.Data()

View File

@ -8,39 +8,37 @@ import (
"shylinux.com/x/toolkits/task" "shylinux.com/x/toolkits/task"
) )
type configMessage interface {
Option(key string, arg ...Any) string
PrefixKey() string
Confv(...Any) Any
}
var _lock = task.Lock{} var _lock = task.Lock{}
var _locks = map[string]*task.Lock{} var _locks = map[string]*task.Lock{}
func getLock(m configMessage, arg ...string) *task.Lock { func getLock(m *ice.Message, arg ...string) *task.Lock {
key := kit.Select(m.PrefixKey(), kit.Keys(arg)) key := kit.Select(m.PrefixKey(), kit.Keys(arg))
defer _lock.Lock()() defer _lock.Lock()()
l, ok := _locks[key] l, ok := _locks[key]
kit.If(!ok, func() { l = &task.Lock{}; _locks[key] = l }) kit.If(!ok, func() { l = &task.Lock{}; _locks[key] = l })
return l return l
} }
func Lock(m configMessage, arg ...string) func() { return getLock(m, arg...).Lock() } func Lock(m *ice.Message, arg ...string) func() {
func RLock(m configMessage, arg ...string) func() { return getLock(m, arg...).RLock() } return getLock(m, arg...).Lock()
func Config(m configMessage, key string, arg ...Any) string {
return kit.Format(Configv(m, key, arg...))
} }
func ConfigSimple(m configMessage, key ...string) (res []string) { func RLock(m *ice.Message, arg ...string) func() {
return getLock(m, arg...).RLock()
}
func ConfigSimple(m *ice.Message, key ...string) (res []string) {
for _, key := range key { for _, key := range key {
res = append(res, key, kit.Format(Configv(m, key))) res = append(res, key, kit.Format(Configv(m, key)))
} }
return return
} }
func Configv(m configMessage, key string, arg ...Any) Any { func Config(m *ice.Message, key string, arg ...Any) string {
return kit.Format(Configv(m, key, arg...))
}
func Configv(m *ice.Message, key string, arg ...Any) Any {
kit.If(len(arg) > 0, func() { Confv(m, m.PrefixKey(), kit.Keym(key), arg[0]) }) kit.If(len(arg) > 0, func() { Confv(m, m.PrefixKey(), kit.Keym(key), arg[0]) })
return Confv(m, m.PrefixKey(), kit.Keym(key)) return Confv(m, m.PrefixKey(), kit.Keym(key))
} }
func Confv(m configMessage, arg ...Any) Any { func Confv(m *ice.Message, arg ...Any) Any {
key := kit.Select(m.PrefixKey(), kit.Format(arg[0])) key := kit.Select(m.PrefixKey(), kit.Format(arg[0]))
if ctx, ok := ice.Info.Index[key].(*ice.Context); ok { if ctx, ok := ice.Info.Index[key].(*ice.Context); ok {
key = ctx.Prefix(key) key = ctx.Prefix(key)
@ -52,10 +50,8 @@ func Confv(m configMessage, arg ...Any) Any {
} }
return m.Confv(arg...) return m.Confv(arg...)
} }
func Conf(m configMessage, arg ...Any) string { func Conf(m *ice.Message, arg ...Any) string { return kit.Format(Confv(m, arg...)) }
return kit.Format(Confv(m, arg...)) func Confm(m *ice.Message, key string, sub Any, cbs ...Any) Map {
}
func Confm(m configMessage, key string, sub Any, cbs ...Any) Map {
val := m.Confv(key, sub) val := m.Confv(key, sub)
kit.If(len(cbs) > 0, func() { kit.For(val, cbs[0]) }) kit.If(len(cbs) > 0, func() { kit.For(val, cbs[0]) })
value, _ := val.(Map) value, _ := val.(Map)
@ -68,13 +64,12 @@ func Cache(m *ice.Message, key string, add func() Any) Any {
if key = kit.Keys(m.PrefixKey(), key); add == nil { if key = kit.Keys(m.PrefixKey(), key); add == nil {
cache.Delete(key) cache.Delete(key)
return nil return nil
} } else if val, ok := cache.Load(key); ok {
if val, ok := cache.Load(key); ok {
return val return val
} } else if val := add(); val != nil {
if val := add(); val != nil {
cache.Store(key, val) cache.Store(key, val)
return val return val
} else {
return nil
} }
return nil
} }

View File

@ -32,9 +32,10 @@ func _mdb_select(m *ice.Message, cb Any, key string, value Map, fields []string,
case func(Any): case func(Any):
cb(value[TARGET]) cb(value[TARGET])
case func(Maps): case func(Maps):
cb(ToMaps(value)) cb(kit.ToMaps(value))
case string, []string, []Any, nil: case string, []string, []Any, nil:
if m.FieldsIsDetail() { if m.FieldsIsDetail() {
// m.Push(ice.FIELDS_DETAIL, value, nil, kit.Dict(HASH, key))
m.Push(ice.FIELDS_DETAIL, value) m.Push(ice.FIELDS_DETAIL, value)
} else { } else {
m.Push(key, value, fields, val) m.Push(key, value, fields, val)
@ -54,46 +55,57 @@ const (
DICT = kit.MDB_DICT DICT = kit.MDB_DICT
META = kit.MDB_META META = kit.MDB_META
SHORT = kit.MDB_SHORT
FIELD = kit.MDB_FIELD
COUNT = kit.MDB_COUNT
TOTAL = kit.MDB_TOTAL
LIMIT = kit.MDB_LIMIT
LEAST = kit.MDB_LEAST
STORE = kit.MDB_STORE
FSIZE = kit.MDB_FSIZE
UNIQ = kit.MDB_UNIQ UNIQ = kit.MDB_UNIQ
FOREACH = kit.MDB_FOREACH FOREACH = kit.MDB_FOREACH
RANDOMS = kit.MDB_RANDOMS RANDOMS = kit.MDB_RANDOMS
) )
const ( const (
ID = kit.MDB_ID ID = kit.MDB_ID
KEY = kit.MDB_KEY
TIME = kit.MDB_TIME TIME = kit.MDB_TIME
TYPE = kit.MDB_TYPE TYPE = kit.MDB_TYPE
NAME = kit.MDB_NAME NAME = kit.MDB_NAME
TEXT = kit.MDB_TEXT TEXT = kit.MDB_TEXT
ICON = kit.MDB_ICON
SCAN = kit.MDB_SCAN
LINK = kit.MDB_LINK
HELP = kit.MDB_HELP
FILE = kit.MDB_FILE
DATA = kit.MDB_DATA DATA = kit.MDB_DATA
VIEW = kit.MDB_VIEW VIEW = kit.MDB_VIEW
FILE = kit.MDB_FILE
LINK = kit.MDB_LINK
SCAN = kit.MDB_SCAN
SHOW = kit.MDB_SHOW SHOW = kit.MDB_SHOW
HELP = kit.MDB_HELP
ICON = kit.MDB_ICON
INDEX = kit.MDB_INDEX KEY = kit.MDB_KEY
VALUE = kit.MDB_VALUE VALUE = kit.MDB_VALUE
INDEX = kit.MDB_INDEX
EXTRA = kit.MDB_EXTRA EXTRA = kit.MDB_EXTRA
ALIAS = kit.MDB_ALIAS ALIAS = kit.MDB_ALIAS
EXPIRE = kit.MDB_EXPIRE EXPIRE = kit.MDB_EXPIRE
STATUS = kit.MDB_STATUS STATUS = kit.MDB_STATUS
STREAM = kit.MDB_STREAM STREAM = kit.MDB_STREAM
SHORT = kit.MDB_SHORT TOOLS = "tools"
FIELD = kit.MDB_FIELD ICONS = "icons"
TOTAL = kit.MDB_TOTAL UNITS = "units"
COUNT = kit.MDB_COUNT ORDER = "order"
LIMIT = kit.MDB_LIMIT SCORE = "score"
LEAST = kit.MDB_LEAST GROUP = "group"
STORE = kit.MDB_STORE VALID = "valid"
FSIZE = kit.MDB_FSIZE ENABLE = "enable"
MEMBER = "member"
DISABLE = "disable"
EXPIRED = "expired"
INVALID = "invalid"
ICONS = "icons"
TOOLS = "tools"
SOURCE = "_source" SOURCE = "_source"
TARGET = "_target" TARGET = "_target"
IMPORTANT = "important" IMPORTANT = "important"
@ -113,20 +125,25 @@ const (
DETAIL = "detail" DETAIL = "detail"
FIELDS = "fields" FIELDS = "fields"
SHORTS = "shorts"
PARAMS = "params" PARAMS = "params"
OFFEND = "offend" OFFEND = "offend"
OFFSET = "offset" OFFSET = "offset"
RANDOM = "random" RANDOM = "random"
WEIGHT = "weight"
SUBKEY = "mdb.sub" SUBKEY = "mdb.sub"
ACTION = "action" ACTION = "action"
UPLOAD = "upload" UPLOAD = "upload"
RECENT = "recent" RECENT = "recent"
REPEAT = "repeat" REPEAT = "repeat"
REVERT = "revert" REVERT = "revert"
RENAME = "rename" RENAME = "rename"
ORDER = "order" VENDOR = "vendor"
PRUNE = "prune" PRUNE = "prune"
TABLE = "table"
CLASS = "class"
DATABASE = "database"
PAGE = "page" PAGE = "page"
NEXT = "next" NEXT = "next"
@ -207,12 +224,31 @@ var Index = &ice.Context{Name: MDB, Help: "数据模块", Commands: ice.Commands
// LIST, func() { _list_prunes(m, arg[0], arg[1], arg[3:]...) }, // LIST, func() { _list_prunes(m, arg[0], arg[1], arg[3:]...) },
) )
}}, }},
EXPORT: {Name: "export key sub type file", Hand: func(m *ice.Message, arg ...string) { EXPORT: {Name: "export index auto", Help: "导出数据", Actions: ice.MergeActions(ice.Actions{
IMPORT: {Hand: func(m *ice.Message, arg ...string) {
HashSelect(m).Table(func(value ice.Maps) {
if value[ENABLE] != ice.FALSE {
m.Cmd(IMPORT, value[INDEX], "", value[TYPE])
}
})
}},
EXPORT: {Hand: func(m *ice.Message, arg ...string) {
HashSelect(m).Table(func(value ice.Maps) {
if value[ENABLE] != ice.FALSE {
m.Cmd(EXPORT, value[INDEX], "", value[TYPE])
}
})
}},
}, ExportHashAction(SHORT, INDEX, FIELD, "time,index,type,enable")), Hand: func(m *ice.Message, arg ...string) {
if len(arg) < 2 {
HashSelect(m, arg...).PushAction(REMOVE)
return
}
m.OptionDefault(CACHE_LIMIT, "-1") m.OptionDefault(CACHE_LIMIT, "-1")
file := _mdb_export_file(m, arg...) file := _mdb_export_file(m, arg...)
kit.Switch(arg[2], kit.Switch(arg[2],
HASH, func() { _hash_export(m, arg[0], arg[1], file) }, HASH, func() { _hash_export(m, arg[0], arg[1], file) },
ZONE, func() { _zone_export(m, arg[0], arg[1], file) }, ZONE, func() { _zone_export(m, arg[0], arg[1], file); _hash_export(m, arg[0], arg[1], file) },
LIST, func() { _list_export(m, arg[0], arg[1], file) }, LIST, func() { _list_export(m, arg[0], arg[1], file) },
) )
}}, }},
@ -220,7 +256,7 @@ var Index = &ice.Context{Name: MDB, Help: "数据模块", Commands: ice.Commands
file := _mdb_export_file(m, arg...) file := _mdb_export_file(m, arg...)
kit.Switch(arg[2], kit.Switch(arg[2],
HASH, func() { _hash_import(m, arg[0], arg[1], file) }, HASH, func() { _hash_import(m, arg[0], arg[1], file) },
ZONE, func() { _zone_import(m, arg[0], arg[1], file) }, ZONE, func() { _hash_import(m, arg[0], arg[1], file); _zone_import(m, arg[0], arg[1], file) },
LIST, func() { _list_import(m, arg[0], arg[1], file) }, LIST, func() { _list_import(m, arg[0], arg[1], file) },
) )
}}, }},
@ -254,12 +290,14 @@ func AutoConfig(arg ...Any) *ice.Action {
} }
add := func(list []string) (inputs []Any) { add := func(list []string) (inputs []Any) {
kit.For(list, func(k string) { kit.For(list, func(k string) {
kit.If(!kit.IsIn(k, TIME, HASH, COUNT, ID), func() { kit.If(!kit.IsIn(k, TIME, HASH, COUNT, ID, ENABLE, DISABLE), func() {
inputs = append(inputs, k+kit.Select("", "*", strings.Contains(s, k))) inputs = append(inputs, k+kit.Select("", FOREACH, strings.Contains(s, k)))
}) })
}) })
return return
} }
kit.If(cmd.Meta[CREATE] == nil, func() { m.Design(CREATE, "", add(kit.Split(HashField(m)))...) })
return
if cmd.Actions[INSERT] != nil { if cmd.Actions[INSERT] != nil {
kit.If(cmd.Meta[INSERT] == nil, func() { m.Design(INSERT, "", add(kit.Simple(Config(m, SHORT), kit.Split(ListField(m))))...) }) kit.If(cmd.Meta[INSERT] == nil, func() { m.Design(INSERT, "", add(kit.Simple(Config(m, SHORT), kit.Split(ListField(m))))...) })
kit.If(cmd.Meta[CREATE] == nil, func() { m.Design(CREATE, "", add(kit.Split(Config(m, SHORT)))...) }) kit.If(cmd.Meta[CREATE] == nil, func() { m.Design(CREATE, "", add(kit.Split(Config(m, SHORT)))...) })
@ -285,8 +323,3 @@ func saveImportant(m *ice.Message, key, sub string, arg ...string) {
} }
kit.If(m.Conf(key, kit.Keys(META, IMPORTANT)) == ice.TRUE, func() { ice.SaveImportant(m, arg...) }) kit.If(m.Conf(key, kit.Keys(META, IMPORTANT)) == ice.TRUE, func() { ice.SaveImportant(m, arg...) })
} }
func ToMaps(value Map) Maps {
res := Maps{}
kit.For(value, func(k, v string) { res[k] = v })
return res
}

View File

@ -55,10 +55,17 @@ func _zone_select(m *ice.Message, prefix, chain, zone string, id string) {
Grows(m, prefix, chain, ID, id, func(value ice.Map) { Grows(m, prefix, chain, ID, id, func(value ice.Map) {
_mdb_select(m, m.OptionCB(""), key, value, fields, val) _mdb_select(m, m.OptionCB(""), key, value, fields, val)
}) })
m.StatusTimeCountTotal(kit.Value(val, "meta.count"), "step", "0")
}) })
} }
func _zone_export(m *ice.Message, prefix, chain, file string) { func _zone_export(m *ice.Message, prefix, chain, file string) {
if !ice.HasUsr() {
return
}
defer Lock(m, prefix)() defer Lock(m, prefix)()
if len(Confm(m, prefix, kit.Keys(chain, HASH))) == 0 {
return
}
f, p, e := miss.CreateFile(kit.Keys(file, CSV)) f, p, e := miss.CreateFile(kit.Keys(file, CSV))
m.Assert(e) m.Assert(e)
defer f.Close() defer f.Close()
@ -66,7 +73,6 @@ func _zone_export(m *ice.Message, prefix, chain, file string) {
w := csv.NewWriter(f) w := csv.NewWriter(f)
defer w.Flush() defer w.Flush()
head := kit.AddUniq(_zone_fields(m), EXTRA) head := kit.AddUniq(_zone_fields(m), EXTRA)
m.Debug("export %v", head)
w.Write(head) w.Write(head)
count := 0 count := 0
for _, key := range kit.SortedKey(m.Confv(prefix, kit.Keys(chain, HASH))) { for _, key := range kit.SortedKey(m.Confv(prefix, kit.Keys(chain, HASH))) {
@ -81,21 +87,21 @@ func _zone_export(m *ice.Message, prefix, chain, file string) {
count++ count++
}) })
}) })
m.Conf(prefix, kit.Keys(chain, HASH, key, LIST), "")
m.Conf(prefix, kit.Keys(chain, HASH, key, META, COUNT), "")
} }
if count == 0 { kit.If(count == 0, func() { os.Remove(p) })
os.Remove(p)
return
}
m.Logs(EXPORT, KEY, path.Join(prefix, chain), FILE, p, COUNT, count) m.Logs(EXPORT, KEY, path.Join(prefix, chain), FILE, p, COUNT, count)
m.Conf(prefix, kit.Keys(chain, HASH), "")
} }
func _zone_import(m *ice.Message, prefix, chain, file string) { func _zone_import(m *ice.Message, prefix, chain, file string) {
defer Lock(m, prefix)() if !ice.HasUsr() {
f, e := ice.Info.Open(m, kit.Keys(file, CSV))
if os.IsNotExist(e) {
return return
} }
if m.Warn(e) { defer Lock(m, prefix)()
f, e := miss.OpenFile(kit.Keys(file, CSV))
if e != nil && !ice.Info.Important {
return
} else if m.WarnNotFound(e) {
return return
} }
defer f.Close() defer f.Close()
@ -103,6 +109,10 @@ func _zone_import(m *ice.Message, prefix, chain, file string) {
head, _ := r.Read() head, _ := r.Read()
zkey := kit.Select(head[0], m.OptionFields()) zkey := kit.Select(head[0], m.OptionFields())
list := ice.Maps{} list := ice.Maps{}
times := ice.Maps{}
kit.For(m.Confv(prefix, kit.Keys(chain, HASH)), func(key string, value ice.Any) {
times[key] = kit.Format(kit.Value(value, kit.Keys(META, TIME)))
})
count := 0 count := 0
for { for {
line, e := r.Read() line, e := r.Read()
@ -126,11 +136,9 @@ func _zone_import(m *ice.Message, prefix, chain, file string) {
} }
if list[zone] == "" { if list[zone] == "" {
list[zone] = Rich(m, prefix, chain, kit.Data(zkey, zone)) list[zone] = Rich(m, prefix, chain, kit.Data(zkey, zone))
kit.If(times[list[zone]], func(t string) { m.Confv(prefix, kit.Keys(chain, HASH, list[zone], META, TIME), t) })
} }
func() { func() { chain := kit.Keys(chain, HASH, list[zone]); Grow(m, prefix, chain, data) }()
chain := kit.Keys(chain, HASH, list[zone])
Grow(m, prefix, chain, data)
}()
count++ count++
} }
m.Logs(IMPORT, KEY, path.Join(prefix, chain), FILE, kit.Keys(file, CSV), COUNT, count) m.Logs(IMPORT, KEY, path.Join(prefix, chain), FILE, kit.Keys(file, CSV), COUNT, count)
@ -161,7 +169,7 @@ func ZoneConfig(arg ...Any) *ice.Action {
add := func(list []string) (inputs []Any) { add := func(list []string) (inputs []Any) {
kit.For(list, func(k string) { kit.For(list, func(k string) {
kit.If(!kit.IsIn(k, TIME, HASH, COUNT, ID), func() { kit.If(!kit.IsIn(k, TIME, HASH, COUNT, ID), func() {
inputs = append(inputs, k+kit.Select("", "*", strings.Contains(s, k))) inputs = append(inputs, k+kit.Select("", FOREACH, strings.Contains(s, k)))
}) })
}) })
return return
@ -184,10 +192,10 @@ func ZoneAction(arg ...ice.Any) ice.Actions {
} }
} }
func ExportZoneAction(arg ...ice.Any) ice.Actions { func ExportZoneAction(arg ...ice.Any) ice.Actions {
return ice.MergeActions(ZoneAction(arg...), ice.Actions{ return ice.MergeActions(ice.Actions{
ice.CTX_INIT: {Hand: func(m *ice.Message, arg ...string) { Config(m, IMPORTANT, ice.TRUE); ZoneImport(m, arg) }}, ice.CTX_INIT: {Hand: func(m *ice.Message, arg ...string) { Config(m, IMPORTANT, ice.TRUE); ZoneImport(m, arg) }},
ice.CTX_EXIT: {Hand: func(m *ice.Message, arg ...string) { m.OptionFields(""); ZoneExport(m, arg) }}, ice.CTX_EXIT: {Hand: func(m *ice.Message, arg ...string) { m.OptionFields(""); ZoneExport(m, arg) }},
}) }, ZoneAction(arg...))
} }
func PageZoneAction(arg ...ice.Any) ice.Actions { func PageZoneAction(arg ...ice.Any) ice.Actions {
return ice.MergeActions(ice.Actions{ return ice.MergeActions(ice.Actions{
@ -228,19 +236,24 @@ func ZoneInsert(m *ice.Message, arg ...Any) {
} }
} }
func ZoneModify(m *ice.Message, arg ...Any) { func ZoneModify(m *ice.Message, arg ...Any) {
if args := kit.Simple(arg...); args[0] == HASH || args[0] == ZoneShort(m) { if args := kit.Simple(arg...); m.Option(ID) == "" {
m.Cmdy(MODIFY, m.PrefixKey(), "", ZONE, args[1], args[3], arg[4:]) HashModify(m, arg...)
} else if args[0] == HASH || args[0] == ZoneShort(m) {
m.Cmdy(MODIFY, m.PrefixKey(), "", ZONE, args[1], args[3], args[4:])
} else { } else {
m.Cmdy(MODIFY, m.PrefixKey(), "", ZONE, m.Option(ZoneKey(m)), m.Option(ID), arg) m.Cmdy(MODIFY, m.PrefixKey(), "", ZONE, m.Option(ZoneKey(m)), m.Option(ID), arg)
} }
} }
func ZoneSelect(m *ice.Message, arg ...string) *ice.Message { func ZoneSelect(m *ice.Message, arg ...string) *ice.Message {
arg = kit.Slice(arg, 0, 2) arg = kit.Slice(arg, 0, 2)
m.Fields(len(arg), kit.Select(kit.Fields(TIME, Config(m, SHORT), COUNT), Config(m, FIELD)), ZoneField(m)) short, field, fields := Config(m, SHORT), Config(m, FIELD), ZoneField(m)
m.Fields(len(arg), kit.Select(kit.Fields(TIME, short, COUNT), field), fields)
if m.Cmdy(SELECT, m.PrefixKey(), "", ZONE, arg, logs.FileLineMeta(-1)); len(arg) == 0 { if m.Cmdy(SELECT, m.PrefixKey(), "", ZONE, arg, logs.FileLineMeta(-1)); len(arg) == 0 {
m.Sort(ZoneShort(m)).PushAction(Config(m, ACTION), REMOVE).Action(CREATE) m.Sort(short).PushAction(REMOVE).Action(CREATE)
} else if len(arg) == 1 { } else if len(arg) == 1 {
m.Action(INSERT).StatusTimeCountTotal(_zone_meta(m, m.PrefixKey(), kit.Keys(HASH, HashSelectField(m, arg[0], HASH)), COUNT)) m.Action(INSERT)
} else {
sortByField(m, fields)
} }
return m return m
} }
@ -270,7 +283,7 @@ func PageZoneSelect(m *ice.Message, arg ...string) *ice.Message {
if ZoneSelect(m, arg...); len(arg) == 0 { if ZoneSelect(m, arg...); len(arg) == 0 {
m.Action(CREATE) m.Action(CREATE)
} else if len(arg) == 1 { } else if len(arg) == 1 {
m.Action(INSERT, "page") m.Action(INSERT, PAGE)
} }
return m return m
} }

View File

@ -2,6 +2,7 @@ package nfs
import ( import (
"bytes" "bytes"
"encoding/csv"
"encoding/json" "encoding/json"
"io" "io"
"io/ioutil" "io/ioutil"
@ -30,11 +31,11 @@ func _cat_line(m *ice.Message, p string) (n int) {
return return
} }
func _cat_list(m *ice.Message, p string) { func _cat_list(m *ice.Message, p string) {
if m.Option(CAT_CONTENT) == "" && !aaa.Right(m, path.Join(m.Option(DIR_ROOT), p)) { if m.Option(CAT_CONTENT) == "" && !kit.IsIn(kit.Ext(p), "css", "js") && !aaa.Right(m, path.Join(m.Option(DIR_ROOT), p)) {
return return
} }
f, e := _cat_find(m, p) f, e := _cat_find(m, p)
if m.Warn(e, ice.ErrNotFound, p) { if m.WarnNotFound(e, FILE, p) {
return return
} }
defer f.Close() defer f.Close()
@ -43,6 +44,10 @@ func _cat_list(m *ice.Message, p string) {
list := []string{} list := []string{}
kit.For(f, func(s string, i int) { list = append(list, cb(s, i)) }) kit.For(f, func(s string, i int) { list = append(list, cb(s, i)) })
m.Echo(strings.Join(list, ice.NL) + ice.NL) m.Echo(strings.Join(list, ice.NL) + ice.NL)
case func([]string, string) string:
list := []string{}
kit.For(f, func(s string, i int) { list = append(list, cb(kit.Split(s), s)) })
m.Echo(strings.Join(list, ice.NL) + ice.NL)
case func(string, int): case func(string, int):
kit.For(f, cb) kit.For(f, cb)
case func(string): case func(string):
@ -52,7 +57,7 @@ func _cat_list(m *ice.Message, p string) {
case func([]string): case func([]string):
kit.For(f, cb) kit.For(f, cb)
case nil: case nil:
if b, e := ioutil.ReadAll(f); !m.Warn(e) { if b, e := ioutil.ReadAll(f); !m.WarnNotFound(e) {
m.Echo(string(b)).StatusTime(FILE, p, SIZE, len(b)) m.Echo(string(b)).StatusTime(FILE, p, SIZE, len(b))
} }
default: default:
@ -71,13 +76,18 @@ const (
TARGET = "target" TARGET = "target"
BINARY = "binary" BINARY = "binary"
SCRIPT = "script" SCRIPT = "script"
FORMAT = "format"
TRANS = "trans"
CLONE = "clone"
REPOS = "repos" REPOS = "repos"
REMOTE = "remote" REMOTE = "remote"
ORIGIN = "origin" ORIGIN = "origin"
COMMIT = "commit"
BRANCH = "branch" BRANCH = "branch"
MASTER = "master" MASTER = "master"
VERSION = "version" VERSION = "version"
COMPILE = "compile"
) )
const ( const (
HTML = ice.HTML HTML = ice.HTML
@ -89,6 +99,7 @@ const (
SHY = ice.SHY SHY = ice.SHY
CSV = ice.CSV CSV = ice.CSV
JSON = ice.JSON JSON = ice.JSON
MOD = "mod"
PROTO = "proto" PROTO = "proto"
YAML = "yaml" YAML = "yaml"
@ -100,13 +111,12 @@ const (
PY = "py" PY = "py"
IMAGE = "image" IMAGE = "image"
JPEG = "jpeg"
PNG = "png" JPG = "jpg"
JPEG = "jpeg" PNG = "png"
JPG = "jpg" MP4 = "mp4"
MP4 = "mp4" MOV = "mov"
MOV = "mov" PDF = "pdf"
PDF = "pdf"
DF = ice.DF DF = ice.DF
PS = ice.PS PS = ice.PS
@ -136,8 +146,9 @@ func DirList(m *ice.Message, arg ...string) bool {
if len(arg) == 0 || strings.HasSuffix(arg[0], PS) { if len(arg) == 0 || strings.HasSuffix(arg[0], PS) {
m.Cmdy(DIR, kit.Slice(arg, 0, 1)) m.Cmdy(DIR, kit.Slice(arg, 0, 1))
return true return true
} else {
return false
} }
return false
} }
func IsSourceFile(m *ice.Message, ext string) bool { func IsSourceFile(m *ice.Message, ext string) bool {
@ -156,7 +167,7 @@ func Open(m *ice.Message, p string, cb ice.Any) {
return return
} else if strings.HasSuffix(p, PS) { } else if strings.HasSuffix(p, PS) {
kit.If(p == PS, func() { p = "" }) kit.If(p == PS, func() { p = "" })
if ls, e := ReadDir(m, p); !m.Warn(e) { if ls, e := ReadDir(m, p); !m.WarnNotFound(e) {
switch cb := cb.(type) { switch cb := cb.(type) {
case func([]os.FileInfo): case func([]os.FileInfo):
cb(ls) cb(ls)
@ -168,7 +179,7 @@ func Open(m *ice.Message, p string, cb ice.Any) {
m.ErrorNotImplement(cb) m.ErrorNotImplement(cb)
} }
} }
} else if f, e := OpenFile(m, p); !m.Warn(e, ice.ErrNotFound, p) { } else if f, e := OpenFile(m, p); !m.WarnNotFound(e, p) {
defer f.Close() defer f.Close()
switch cb := cb.(type) { switch cb := cb.(type) {
case func(io.Reader, os.FileInfo): case func(io.Reader, os.FileInfo):
@ -179,7 +190,7 @@ func Open(m *ice.Message, p string, cb ice.Any) {
case func(io.Reader): case func(io.Reader):
cb(f) cb(f)
case func(string): case func(string):
if b, e := ioutil.ReadAll(f); !m.Warn(e) { if b, e := ioutil.ReadAll(f); !m.WarnNotFound(e) {
cb(string(b)) cb(string(b))
} }
default: default:
@ -188,7 +199,7 @@ func Open(m *ice.Message, p string, cb ice.Any) {
} }
} }
func ReadAll(m *ice.Message, r io.Reader) []byte { func ReadAll(m *ice.Message, r io.Reader) []byte {
if b, e := ioutil.ReadAll(r); !m.Warn(e) { if b, e := ioutil.ReadAll(r); !m.WarnNotFound(e) {
return b return b
} }
return nil return nil
@ -200,3 +211,26 @@ func ReadFile(m *ice.Message, p string) (b []byte, e error) {
func Rewrite(m *ice.Message, p string, cb func(string) string) { func Rewrite(m *ice.Message, p string, cb func(string) string) {
m.Cmd(SAVE, p, m.Cmdx(CAT, p, func(s string, i int) string { return cb(s) })) m.Cmd(SAVE, p, m.Cmdx(CAT, p, func(s string, i int) string { return cb(s) }))
} }
func ScanCSV(m *ice.Message, file string, cb func([]string), arg ...string) {
f, e := OpenFile(m, file)
if m.Warn(e) {
return
}
r := csv.NewReader(f)
head, err := r.Read()
if err != nil {
return
}
index := []int{}
kit.If(len(arg) == 0, func() { arg = append(arg, head...) })
kit.For(arg, func(h string) { index = append(index, kit.IndexOf(head, h)) })
for {
data, err := r.Read()
if err != nil {
break
}
res := []string{}
kit.For(index, func(i int) { res = append(res, data[i]) })
cb(res)
}
}

View File

@ -4,6 +4,7 @@ import (
"os" "os"
"path" "path"
"regexp" "regexp"
"runtime"
"strings" "strings"
"time" "time"
@ -50,9 +51,7 @@ func _dir_list(m *ice.Message, root string, dir string, level int, deep bool, di
default: default:
m.ErrorNotImplement(cb) m.ErrorNotImplement(cb)
} }
if s.ModTime().After(last) { kit.If(s.ModTime().After(last), func() { last = s.ModTime() })
last = s.ModTime()
}
for _, field := range fields { for _, field := range fields {
switch field { switch field {
case mdb.TIME: case mdb.TIME:
@ -97,13 +96,15 @@ func _dir_list(m *ice.Message, root string, dir string, level int, deep bool, di
case mdb.LINK: case mdb.LINK:
if isDir { if isDir {
m.Push(mdb.LINK, "") m.Push(mdb.LINK, "")
} else if strings.Contains(p, "ice.windows.") {
m.PushDownload(mdb.LINK, "ice.exe", p)
} else { } else {
m.PushDownload(mdb.LINK, p) if strings.Contains(p, "ice.windows") {
m.PushDownload(mdb.LINK, "ice.exe", p)
} else {
m.PushDownload(mdb.LINK, p)
}
} }
case mdb.SHOW: case mdb.SHOW:
switch p := kit.MergeURL(ice.SHARE_LOCAL+p, ice.POD, m.Option(ice.MSG_USERPOD)); kit.Ext(s.Name()) { switch p := m.MergeLink(SHARE_LOCAL+p, ice.POD, m.Option(ice.MSG_USERPOD)); kit.Ext(s.Name()) {
case PNG, JPG: case PNG, JPG:
m.PushImages(field, p) m.PushImages(field, p)
case MP4: case MP4:
@ -115,7 +116,7 @@ func _dir_list(m *ice.Message, root string, dir string, level int, deep bool, di
if m.IsCliUA() || m.Option(ice.MSG_USERROLE) == aaa.VOID { if m.IsCliUA() || m.Option(ice.MSG_USERROLE) == aaa.VOID {
break break
} }
m.PushButton(mdb.SHOW, TRASH) m.PushButton(mdb.SHOW, "rename", TRASH)
default: default:
m.Push(field, "") m.Push(field, "")
} }
@ -136,26 +137,64 @@ func _dir_list(m *ice.Message, root string, dir string, level int, deep bool, di
} }
const ( const (
PWD = "./" PWD = "./"
SRC = "src/" SRC = "src/"
ETC = "etc/" ETC = "etc/"
BIN = "bin/" BIN = "bin/"
VAR = "var/" VAR = "var/"
USR = "usr/" USR = "usr/"
USR_PORTAL = ice.USR_PORTAL
USR_PUBLISH = ice.USR_PUBLISH
USR_ICEBERGS = ice.USR_ICEBERGS
USR_LOCAL_WORK = ice.USR_LOCAL_WORK
USR_LOCAL = ice.USR_LOCAL
SRC_DOCUMENT = ice.SRC_DOCUMENT
SRC_TEMPLATE = ice.SRC_TEMPLATE
REQUIRE = "/require/"
VOLCANOS = "/volcanos/"
INTSHELL = "/intshell/"
PATHNAME = "pathname"
FILENAME = "filename"
USR_ICONS_ICEBERGS = "usr/icons/icebergs.jpg" SCAN = "scan"
GOWORK = "gowork"
PORTAL_GO = "portal.go"
PORTAL_JSON = "portal.json"
ETC_LOCAL_SH = "etc/local.sh"
ETC_CERT_KEY = "etc/cert/cert.key"
ETC_CERT_PEM = "etc/cert/cert.pem"
SRC_DOCUMENT = "src/document/"
SRC_PRIVATE = "src/private/"
SRC_MAIN_PNG = "src/main.png"
SRC_OPTION_GO = "src/option.go"
SRC_TEMPLATE = ice.SRC_TEMPLATE
USR_TOOLKITS = ice.USR_TOOLKITS
USR_ICEBERGS = ice.USR_ICEBERGS
USR_RELEASE = ice.USR_RELEASE
USR_PUBLISH = ice.USR_PUBLISH
USR_LOCAL = ice.USR_LOCAL
USR_LOCAL_WORK = ice.USR_LOCAL_WORK
USR_IMAGE = "usr/image/"
USR_MATERIAL = "usr/material/"
USR_LOCAL_IMAGE = "usr/local/image/"
USR_LEARNING_PORTAL = "usr/learning/portal/"
USR_MODULES = "usr/node_modules/"
USR_PACKAGE = "usr/package.json"
VAR_LOG_BENCH_LOG = "var/log/bench.log"
USR_ICONS_AVATAR = "usr/icons/avatar.jpg"
USR_ICONS_CONTEXTS = "usr/icons/contexts.jpg"
USR_ICONS_ICEBERGS = "usr/icons/icebergs.png"
USR_ICONS_VOLCANOS = "usr/icons/volcanos.png"
USR_ICONS = "usr/icons/"
V = "/v/"
M = "/m/"
P = "/p/"
X = "/x/"
S = "/s/"
C = "/c/"
INTSHELL = "/intshell/"
VOLCANOS = "/volcanos/"
VOLCANOS_PLUGIN = "/volcanos/plugin/"
REQUIRE_MODULES = "/require/modules/"
REQUIRE_USR = "/require/usr/"
REQUIRE_SRC = "/require/src/"
REQUIRE = "/require/"
PLUGIN = "/plugin/"
SHARE_LOCAL = "/share/local/"
PATHNAME = "pathname"
FILENAME = "filename"
CONTEXTS = "contexts"
TYPE_ALL = "all" TYPE_ALL = "all"
TYPE_BIN = "bin" TYPE_BIN = "bin"
@ -164,8 +203,8 @@ const (
TYPE_BOTH = "both" TYPE_BOTH = "both"
DIR_ROOT = "dir_root" DIR_ROOT = "dir_root"
DIR_TYPE = "dir_type"
DIR_DEEP = "dir_deep" DIR_DEEP = "dir_deep"
DIR_TYPE = "dir_type"
DIR_REG = "dir_reg" DIR_REG = "dir_reg"
DIR_DEF_FIELDS = "time,path,size,action" DIR_DEF_FIELDS = "time,path,size,action"
@ -185,21 +224,31 @@ const DIR = "dir"
func init() { func init() {
Index.MergeCommands(ice.Commands{ Index.MergeCommands(ice.Commands{
DIR: {Name: "dir path auto upload app", Icon: "dir.png", Help: "目录", Actions: ice.Actions{ DIR: {Name: "dir path auto upload app", Icon: "dir.png", Help: "文件夹", Actions: ice.Actions{
ice.CTX_INIT: {Hand: func(m *ice.Message, arg ...string) { ice.CTX_INIT: {Hand: func(m *ice.Message, arg ...string) {
aaa.White(m, ice.MAKEFILE, ice.README_MD, ice.LICENSE)
aaa.White(m, ice.SRC, ice.BIN, ice.USR) aaa.White(m, ice.SRC, ice.BIN, ice.USR)
aaa.Black(m, ice.SRC_PRIVATE)
aaa.Black(m, ice.USR_LOCAL) aaa.Black(m, ice.USR_LOCAL)
}}, }},
ice.APP: {Help: "本机", Hand: func(m *ice.Message, arg ...string) { ice.APP: {Help: "本机", Hand: func(m *ice.Message, arg ...string) {
m.Cmd("cli.system", "opens", "Finder.app") switch runtime.GOOS {
case "darwin":
m.System("open", kit.Path(m.Option(PATH)))
}
}}, }},
mdb.SHOW: {Help: "预览", Hand: func(m *ice.Message, arg ...string) { mdb.SHOW: {Help: "预览", Hand: func(m *ice.Message, arg ...string) {
Show(m.ProcessInner(), path.Join(m.Option(DIR_ROOT), m.Option(PATH))) Show(m.ProcessInner(), path.Join(m.Option(DIR_ROOT), m.Option(PATH)))
}}, mdb.UPLOAD: {}, }}, mdb.UPLOAD: {},
SIZE: {Hand: func(m *ice.Message, arg ...string) { SIZE: {Hand: func(m *ice.Message, arg ...string) {
m.Echo(kit.Select("", kit.Split(m.Cmdx("cli.system", "du", "-sh")), 0)) m.Echo(kit.Select("", kit.Split(m.System("du", "-sh").Result()), 0))
}},
"rename": {Name: "rename to", Hand: func(m *ice.Message, arg ...string) {
m.Cmd(MOVE, path.Join(path.Dir(m.Option(PATH)), m.Option(TO)), m.Option(PATH))
}},
TRASH: {Hand: func(m *ice.Message, arg ...string) {
m.Cmd(TRASH, mdb.CREATE, m.Option(PATH))
}}, }},
TRASH: {Hand: func(m *ice.Message, arg ...string) { m.Cmd(TRASH, mdb.CREATE, m.Option(PATH)) }},
}, Hand: func(m *ice.Message, arg ...string) { }, Hand: func(m *ice.Message, arg ...string) {
root, dir := kit.Select(PWD, m.Option(DIR_ROOT)), kit.Select(PWD, arg, 0) root, dir := kit.Select(PWD, m.Option(DIR_ROOT)), kit.Select(PWD, arg, 0)
kit.If(strings.HasPrefix(dir, PS), func() { root = "" }) kit.If(strings.HasPrefix(dir, PS), func() { root = "" })
@ -218,22 +267,24 @@ func init() {
func Relative(m *ice.Message, p string) string { func Relative(m *ice.Message, p string) string {
if _p := kit.ExtChange(p, JS); Exists(m, _p) { if _p := kit.ExtChange(p, JS); Exists(m, _p) {
return _p return _p
} else if _p := kit.ExtChange(path.Join(ice.USR_VOLCANOS, ice.PLUGIN_LOCAL, path.Join(kit.Slice(kit.Split(p, PS), -2)...)), JS); Exists(m, _p) { } else if _p := kit.ExtChange(path.Join(ice.USR_VOLCANOS, ice.PLUGIN_LOCAL, path.Join(kit.Slice(kit.Split(p, PS), -2)...)), JS); Exists(m, kit.Split(_p, "?")[0]) {
return _p return _p
} else { } else {
return p return p
} }
} }
func SplitPath(m *ice.Message, p string) []string { func SplitPath(m *ice.Message, p string) []string {
if kit.HasPrefix(p, ice.REQUIRE_SRC, ice.REQUIRE_USR) { if kit.HasPrefix(p, REQUIRE_SRC, REQUIRE_USR) {
p = strings.TrimPrefix(p, REQUIRE) p = strings.TrimPrefix(p, REQUIRE)
} else if kit.HasPrefix(p, REQUIRE) { } else if kit.HasPrefix(p, REQUIRE) {
ls := kit.Split(p, PS) ls := kit.Split(p, PS)
return []string{ice.USR_REQUIRE + path.Join(ls[1:4]...) + PS, path.Join(ls[4:]...)} return []string{ice.USR_REQUIRE + path.Join(ls[1:4]...) + PS, path.Join(ls[4:]...)}
} else if kit.HasPrefix(p, P) {
p = strings.TrimPrefix(p, P)
} }
line := kit.Select("1", strings.Split(p, DF), 1) line := kit.Select("1", strings.Split(p, DF), 1)
p = strings.TrimPrefix(p, kit.Path("")+PS)
p = strings.Split(p, DF)[0] p = strings.Split(p, DF)[0]
p = strings.Split(p, "?")[0]
if ls := kit.Split(kit.Select(ice.SRC_MAIN_GO, p), PS); len(ls) == 1 { if ls := kit.Split(kit.Select(ice.SRC_MAIN_GO, p), PS); len(ls) == 1 {
return []string{PWD, ls[0], line} return []string{PWD, ls[0], line}
} else if ls[0] == ice.USR { } else if ls[0] == ice.USR {
@ -257,12 +308,10 @@ func DirDeepAll(m *ice.Message, root, dir string, cb func(ice.Maps), arg ...stri
} }
} }
func Show(m *ice.Message, file string) bool { func Show(m *ice.Message, file string) bool {
p := ice.SHARE_LOCAL + file p := SHARE_LOCAL + file
kit.If(m.Option(ice.MSG_USERPOD), func(pod string) { kit.If(m.Option(ice.MSG_USERPOD), func(pod string) { p = kit.MergeURL(p, ice.POD, pod) })
p += "?" + kit.JoinKV("=", "&", ice.POD, pod)
})
switch strings.ToLower(kit.Ext(file)) { switch strings.ToLower(kit.Ext(file)) {
case PNG, JPG, JPEG: case PNG, JPG, JPEG, "gif":
m.EchoImages(p) m.EchoImages(p)
case MP4, MOV: case MP4, MOV:
m.EchoVideos(p) m.EchoVideos(p)
@ -270,6 +319,7 @@ func Show(m *ice.Message, file string) bool {
if IsSourceFile(m, kit.Ext(file)) { if IsSourceFile(m, kit.Ext(file)) {
m.Cmdy(CAT, file) m.Cmdy(CAT, file)
} else { } else {
m.ProcessOpen(p)
return false return false
} }
} }

View File

@ -11,9 +11,9 @@ const DOCUMENT = "document"
func init() { func init() {
Index.MergeCommands(ice.Commands{ Index.MergeCommands(ice.Commands{
DOCUMENT: {Name: "document index path auto", Help: "文档", Actions: ice.MergeActions(ice.Actions{}), Hand: func(m *ice.Message, arg ...string) { DOCUMENT: {Name: "document index path auto", Help: "文档", Hand: func(m *ice.Message, arg ...string) {
if len(arg) == 0 { if len(arg) == 0 {
m.Cmdy(ice.COMMAND).Action("filter:text").Option(ice.MSG_DISPLAY, "") m.Cmdy(ice.COMMAND).Option(ice.MSG_DISPLAY, "")
return return
} }
m.Search(arg[0], func(p *ice.Context, c *ice.Context, key string, cmd *ice.Command) { m.Search(arg[0], func(p *ice.Context, c *ice.Context, key string, cmd *ice.Command) {
@ -36,9 +36,5 @@ var DocumentText = func(m *ice.Message, p string) string {
return m.Cmdx(CAT, DocumentPath(m, path.Base(p))) return m.Cmdx(CAT, DocumentPath(m, path.Base(p)))
} }
var DocumentPath = func(m *ice.Message, arg ...string) string { var DocumentPath = func(m *ice.Message, arg ...string) string {
if p := path.Join(ice.SRC_DOCUMENT, m.PrefixKey(), path.Join(arg...)); Exists(m, p) { return path.Join(USR_LEARNING_PORTAL, m.PrefixKey(), path.Join(arg...))
return p
} else {
return p
}
} }

View File

@ -16,7 +16,7 @@ func init() {
FIND: {Name: "find word file auto", Help: "搜索", Hand: func(m *ice.Message, arg ...string) { FIND: {Name: "find word file auto", Help: "搜索", Hand: func(m *ice.Message, arg ...string) {
kit.If(len(arg) == 0, func() { arg = append(arg, "main.go") }) kit.If(len(arg) == 0, func() { arg = append(arg, "main.go") })
m.Options(mdb.VALUE, arg[0], CMD_DIR, kit.Select("", arg, 2)) m.Options(mdb.VALUE, arg[0], CMD_DIR, kit.Select("", arg, 2))
msg := m.Cmd("cli.system", FIND, kit.Select(SRC, arg, 1), "-name", arg[0]) msg := m.System(FIND, kit.Select(SRC, arg, 1), "-name", arg[0])
m.Echo(msg.FormatsMeta(nil)) m.Echo(msg.FormatsMeta(nil))
kit.For(strings.Split(msg.Result(), ice.NL), func(s string) { m.Push(FILE, s) }) kit.For(strings.Split(msg.Result(), ice.NL), func(s string) { m.Push(FILE, s) })
m.StatusTimeCount(kit.Dict(PATH, m.Option(CMD_DIR))) m.StatusTimeCount(kit.Dict(PATH, m.Option(CMD_DIR)))

View File

@ -1,7 +1,6 @@
package nfs package nfs
import ( import (
"path"
"strings" "strings"
ice "shylinux.com/x/icebergs" ice "shylinux.com/x/icebergs"
@ -20,13 +19,15 @@ func init() {
Index.MergeCommands(ice.Commands{ Index.MergeCommands(ice.Commands{
GREP: {Name: "grep word file auto", Help: "搜索", Hand: func(m *ice.Message, arg ...string) { GREP: {Name: "grep word file auto", Help: "搜索", Hand: func(m *ice.Message, arg ...string) {
kit.If(len(arg) == 0, func() { arg = append(arg, ice.MAIN) }) kit.If(len(arg) == 0, func() { arg = append(arg, ice.MAIN) })
m.Options(mdb.VALUE, arg[0], CMD_DIR, kit.Select("", arg, 2)) kit.If(len(arg) == 1, func() { arg = append(arg, ice.SRC) })
kit.For(strings.Split(m.Cmdx("cli.system", GREP, "--exclude=.[a-z]*", "--exclude-dir=.[a-z]*", "-rni", arg[0], path.Join(kit.Select(SRC, arg, 1))), ice.NL), func(s string) { m.Options(mdb.VALUE, arg[0])
kit.For(kit.SplitLine(m.System(GREP, "--exclude=.[a-z]*", "--exclude-dir=.[a-z]*", "-rni", arg[0], kit.AddUniq([]string{}, arg[1:]...)).Result()), func(s string) {
if ls := strings.SplitN(s, DF, 3); len(ls) > 2 { if ls := strings.SplitN(s, DF, 3); len(ls) > 2 {
m.Push(FILE, strings.TrimPrefix(ls[0], PWD)).Push(LINE, ls[1]).Push(mdb.TEXT, ls[2]) _ls := SplitPath(m, ls[0])
m.Push(PATH, _ls[0]).Push(FILE, _ls[1]).Push(LINE, ls[1]).Push(mdb.TEXT, ls[2])
} }
}) })
m.StatusTimeCount(kit.Dict(PATH, m.Option(CMD_DIR))) m.Sort("path,file,line")
}}, }},
}) })
} }

View File

@ -22,11 +22,11 @@ func init() {
Open(m, arg[0], func(r io.Reader, s os.FileInfo) { Open(m, arg[0], func(r io.Reader, s os.FileInfo) {
switch arg[1] { switch arg[1] {
case "gzip": case "gzip":
if g, e := gzip.NewReader(r); !m.Warn(e) { if g, e := gzip.NewReader(r); !m.WarnNotFound(e) {
r = g r = g
} }
case "zlib": case "zlib":
if z, e := zlib.NewReader(r); !m.Warn(e) { if z, e := zlib.NewReader(r); !m.WarnNotFound(e) {
r = z r = z
} }
} }

View File

@ -10,6 +10,6 @@ const NFS = "nfs"
var Index = &ice.Context{Name: NFS, Help: "存储模块"} var Index = &ice.Context{Name: NFS, Help: "存储模块"}
func init() { func init() {
ice.Index.Register(Index, nil, ZIP, TAR, CAT, DIR, PACK, DEFS, SAVE, PUSH, COPY, LINK, GREP, FIND, MOVE, TRASH) ice.Index.Register(Index, nil, ZIP, TAR, CAT, DIR, PACK, DEFS, SAVE, PUSH, COPY, LINK, GREP, FIND, MOVE, MOVETO, TRASH)
} }
func Prefix(arg ...string) string { return kit.Keys(NFS, arg) } func Prefix(arg ...string) string { return kit.Keys(NFS, arg) }

View File

@ -17,20 +17,6 @@ const PACK = "pack"
func init() { func init() {
Index.MergeCommands(ice.Commands{ Index.MergeCommands(ice.Commands{
PACK: {Name: "pack path auto create upload", Help: "文件系统", Actions: ice.Actions{ PACK: {Name: "pack path auto create upload", Help: "文件系统", Actions: ice.Actions{
mdb.SEARCH: {Hand: func(m *ice.Message, arg ...string) {
if arg[0] == mdb.FOREACH && arg[1] != "" {
m.Cmd(DIR, SRC, PATH, kit.Dict(DIR_REG, arg[1], DIR_DEEP, ice.TRUE, DIR_TYPE, CAT), func(value ice.Maps) {
if strings.HasPrefix(value[PATH], ice.SRC_TEMPLATE) {
return
}
m.PushSearch(mdb.TYPE, kit.Ext(value[PATH]), mdb.NAME, path.Base(value[PATH]), mdb.TEXT, value[PATH])
})
OptionFiles(m, PackFile)
m.Cmd(DIR, USR, PATH, kit.Dict(DIR_REG, arg[1], DIR_DEEP, ice.TRUE, DIR_TYPE, CAT), func(value ice.Maps) {
m.PushSearch(mdb.TYPE, kit.Ext(value[PATH]), mdb.NAME, path.Base(value[PATH]), mdb.TEXT, value[PATH])
})
}
}},
mdb.CREATE: {Name: "create path*=src/hi/hi.txt text*=hello", Hand: func(m *ice.Message, arg ...string) { mdb.CREATE: {Name: "create path*=src/hi/hi.txt text*=hello", Hand: func(m *ice.Message, arg ...string) {
OptionFiles(m, PackFile) OptionFiles(m, PackFile)
Create(m, m.Option(PATH), func(w io.Writer, p string) { Create(m, m.Option(PATH), func(w io.Writer, p string) {
@ -72,13 +58,8 @@ var DiskFile = file.NewDiskFile()
var PackFile = file.NewPackFile() var PackFile = file.NewPackFile()
func init() { file.Init(OptionFiles(ice.Pulse, DiskFile, PackFile)) } func init() { file.Init(OptionFiles(ice.Pulse, DiskFile, PackFile)) }
func init() { ice.Info.Open = OpenFile }
type optionMessage interface { func OptionFiles(m *ice.Message, f ...file.File) file.File {
Optionv(key string, arg ...ice.Any) ice.Any
}
func OptionFiles(m optionMessage, f ...file.File) file.File {
if len(f) > 1 { if len(f) > 1 {
m.Optionv(ice.MSG_FILES, file.NewMultiFile(f...)) m.Optionv(ice.MSG_FILES, file.NewMultiFile(f...))
} else if len(f) > 0 { } else if len(f) > 0 {
@ -86,18 +67,18 @@ func OptionFiles(m optionMessage, f ...file.File) file.File {
} }
return m.Optionv(ice.MSG_FILES).(file.File) return m.Optionv(ice.MSG_FILES).(file.File)
} }
func StatFile(m optionMessage, p string) (os.FileInfo, error) { return OptionFiles(m).StatFile(p) } func StatFile(m *ice.Message, p string) (os.FileInfo, error) { return OptionFiles(m).StatFile(p) }
func OpenFile(m *ice.Message, p string) (io.ReadCloser, error) { return OptionFiles(m).OpenFile(p) } func OpenFile(m *ice.Message, p string) (io.ReadCloser, error) { return OptionFiles(m).OpenFile(p) }
func CreateFile(m optionMessage, p string) (io.WriteCloser, string, error) { func CreateFile(m *ice.Message, p string) (io.WriteCloser, string, error) {
return OptionFiles(m).CreateFile(p) return OptionFiles(m).CreateFile(p)
} }
func AppendFile(m optionMessage, p string) (io.ReadWriteCloser, string, error) { func AppendFile(m *ice.Message, p string) (io.ReadWriteCloser, string, error) {
w, e := OptionFiles(m).AppendFile(p) w, e := OptionFiles(m).AppendFile(p)
return w, p, e return w, p, e
} }
func WriteFile(m optionMessage, p string, b []byte) error { return OptionFiles(m).WriteFile(p, b) } func WriteFile(m *ice.Message, p string, b []byte) error { return OptionFiles(m).WriteFile(p, b) }
func ReadDir(m optionMessage, p string) ([]os.FileInfo, error) { func ReadDir(m *ice.Message, p string) ([]os.FileInfo, error) {
list, e := OptionFiles(m).ReadDir(p) list, e := OptionFiles(m).ReadDir(p)
for i := 0; i < len(list)-1; i++ { for i := 0; i < len(list)-1; i++ {
for j := i + 1; j < len(list); j++ { for j := i + 1; j < len(list); j++ {
@ -110,24 +91,24 @@ func ReadDir(m optionMessage, p string) ([]os.FileInfo, error) {
} }
return list, e return list, e
} }
func MkdirAll(m optionMessage, p string) string { func MkdirAll(m *ice.Message, p string) string {
OptionFiles(m).MkdirAll(p, ice.MOD_DIR) OptionFiles(m).MkdirAll(p, ice.MOD_DIR)
return p return p
} }
func RemoveAll(m optionMessage, p string) error { return OptionFiles(m).RemoveAll(p) } func RemoveAll(m *ice.Message, p string) error { return OptionFiles(m).RemoveAll(p) }
func Remove(m optionMessage, p string) error { return OptionFiles(m).Remove(p) } func Remove(m *ice.Message, p string) error { return OptionFiles(m).Remove(p) }
func Rename(m optionMessage, oldname string, newname string) error { func Rename(m *ice.Message, oldname string, newname string) error {
MkdirAll(m, path.Dir(newname)) MkdirAll(m, path.Dir(newname))
return OptionFiles(m).Rename(oldname, newname) return OptionFiles(m).Rename(oldname, newname)
} }
func Symlink(m optionMessage, oldname string, newname string) error { func Symlink(m *ice.Message, oldname string, newname string) error {
return OptionFiles(m).Symlink(oldname, newname) return OptionFiles(m).Symlink(oldname, newname)
} }
func Link(m optionMessage, oldname string, newname string) error { func Link(m *ice.Message, oldname string, newname string) error {
return OptionFiles(m).Link(oldname, newname) return OptionFiles(m).Link(oldname, newname)
} }
func Exists(m optionMessage, p string, cb ...func(string)) bool { func Exists(m *ice.Message, p string, cb ...func(string)) bool {
if _, e := OptionFiles(m).StatFile(p); e == nil { if _, e := OptionFiles(m).StatFile(p); e == nil {
for _, cb := range cb { for _, cb := range cb {
cb(p) cb(p)
@ -136,7 +117,7 @@ func Exists(m optionMessage, p string, cb ...func(string)) bool {
} }
return false return false
} }
func ExistsFile(m optionMessage, p string) bool { func ExistsFile(m *ice.Message, p string) bool {
if s, e := OptionFiles(m).StatFile(p); e == nil && !s.IsDir() { if s, e := OptionFiles(m).StatFile(p); e == nil && !s.IsDir() {
return true return true
} }
@ -146,7 +127,7 @@ func NewReadCloser(r io.Reader) io.ReadCloser { return file.NewReadCloser(r) }
func NewWriteCloser(w func([]byte) (int, error), c func() error) io.WriteCloser { func NewWriteCloser(w func([]byte) (int, error), c func() error) io.WriteCloser {
return file.NewWriteCloser(w, c) return file.NewWriteCloser(w, c)
} }
func Close(m optionMessage, p ice.Any) { func Close(m *ice.Message, p ice.Any) {
if w, ok := p.(io.Closer); ok { if w, ok := p.(io.Closer); ok {
w.Close() w.Close()
} }

View File

@ -7,6 +7,7 @@ import (
"path" "path"
ice "shylinux.com/x/icebergs" ice "shylinux.com/x/icebergs"
"shylinux.com/x/icebergs/base/mdb"
kit "shylinux.com/x/toolkits" kit "shylinux.com/x/toolkits"
) )
@ -15,7 +16,7 @@ func _defs_file(m *ice.Message, name string, text ...string) {
return return
} }
for i, v := range text { for i, v := range text {
if b, e := kit.Render(v, m); !m.Warn(e) { if b, e := kit.Render(v, m); !m.WarnNotValid(e) {
text[i] = string(b) text[i] = string(b)
} }
} }
@ -44,16 +45,16 @@ func _copy_file(m *ice.Message, name string, from ...string) {
}) })
} }
func _link_file(m *ice.Message, name string, from string) { func _link_file(m *ice.Message, name string, from string) {
if m.Warn(from == "", ice.ErrNotValid, FROM) { if m.WarnNotValid(from == "", FROM) {
return return
} }
name = path.Join(m.Option(DIR_ROOT), name) name = path.Join(m.Option(DIR_ROOT), name)
from = path.Join(m.Option(DIR_ROOT), from) from = path.Join(m.Option(DIR_ROOT), from)
if m.Warn(!Exists(m, from), ice.ErrNotFound, from) { if m.WarnNotFound(!Exists(m, from), from) {
return return
} }
Remove(m, name) Remove(m, name)
if MkdirAll(m, path.Dir(name)); m.Warn(Link(m, from, name)) && m.Warn(Symlink(m, from, name), ice.ErrWarn, from) { if MkdirAll(m, path.Dir(name)); m.WarnNotValid(Link(m, from, name)) && m.WarnNotValid(Symlink(m, from, name), from) {
return return
} }
m.Logs(SAVE, FILE, name, FROM, from).Echo(name) m.Logs(SAVE, FILE, name, FROM, from).Echo(name)
@ -73,6 +74,7 @@ const COPY = "copy"
const LINK = "link" const LINK = "link"
const LOAD = "load" const LOAD = "load"
const MOVE = "move" const MOVE = "move"
const MOVETO = "moveto"
func init() { func init() {
Index.MergeCommands(ice.Commands{ Index.MergeCommands(ice.Commands{
@ -99,10 +101,13 @@ func init() {
arg[0] = path.Join(m.Option(DIR_ROOT), arg[0]) arg[0] = path.Join(m.Option(DIR_ROOT), arg[0])
Rename(m, arg[1], arg[0]) Rename(m, arg[1], arg[0])
}}, }},
MOVETO: {Name: "moveto path from run", Help: "移动到", Hand: func(m *ice.Message, arg ...string) {
kit.For(arg[1:], func(from string) { m.Cmd(MOVE, path.Join(arg[0], path.Base(from)), from) })
}},
}) })
} }
func Create(m *ice.Message, p string, cb ice.Any) { func Create(m *ice.Message, p string, cb ice.Any) string {
if f, p, e := CreateFile(m, p); !m.Warn(e) { if f, p, e := CreateFile(m, p); !m.WarnNotValid(e) {
defer f.Close() defer f.Close()
switch cb := cb.(type) { switch cb := cb.(type) {
case func(io.Writer, string): case func(io.Writer, string):
@ -113,9 +118,10 @@ func Create(m *ice.Message, p string, cb ice.Any) {
m.ErrorNotImplement(cb) m.ErrorNotImplement(cb)
} }
} }
return p
} }
func Append(m *ice.Message, p string, cb ice.Any) { func Append(m *ice.Message, p string, cb ice.Any) {
if f, p, e := AppendFile(m, p); !m.Warn(e) { if f, p, e := AppendFile(m, p); !m.WarnNotValid(e) {
defer f.Close() defer f.Close()
switch cb := cb.(type) { switch cb := cb.(type) {
case func(io.Writer, string): case func(io.Writer, string):
@ -133,7 +139,7 @@ func Save(m *ice.Message, w io.Writer, s string, cb ice.Any) {
io.Copy(w, content) io.Copy(w, content)
return return
} }
if n, e := fmt.Fprint(w, s); !m.Warn(e) { if n, e := fmt.Fprint(w, s); !m.WarnNotValid(e) {
switch cb := cb.(type) { switch cb := cb.(type) {
case func(int): case func(int):
cb(n) cb(n)
@ -143,7 +149,7 @@ func Save(m *ice.Message, w io.Writer, s string, cb ice.Any) {
} }
} }
func Copy(m *ice.Message, w io.Writer, r io.Reader, cb ice.Any) { func Copy(m *ice.Message, w io.Writer, r io.Reader, cb ice.Any) {
if n, e := io.Copy(w, r); !m.Warn(e) { if n, e := io.Copy(w, r); !m.WarnNotValid(e) {
switch cb := cb.(type) { switch cb := cb.(type) {
case func(int): case func(int):
cb(int(n)) cb(int(n))
@ -152,7 +158,7 @@ func Copy(m *ice.Message, w io.Writer, r io.Reader, cb ice.Any) {
} }
} }
} }
func CopyStream(m *ice.Message, to io.WriteCloser, from io.ReadCloser, cache, total int, cb ice.Any) { func CopyStream(m *ice.Message, to io.Writer, from io.Reader, cache, total int, cb ice.Any) {
kit.If(total == 0, func() { total = 1 }) kit.If(total == 0, func() { total = 1 })
count, buf := 0, make([]byte, cache) count, buf := 0, make([]byte, cache)
for { for {
@ -170,7 +176,7 @@ func CopyStream(m *ice.Message, to io.WriteCloser, from io.ReadCloser, cache, to
default: default:
m.ErrorNotImplement(cb) m.ErrorNotImplement(cb)
} }
if e == io.EOF || m.Warn(e) { if e == io.EOF || m.WarnNotValid(e) {
break break
} }
} }
@ -209,3 +215,14 @@ func Pipe(m *ice.Message, cb ice.Any) io.WriteCloser {
} }
return w return w
} }
func TempName(m *ice.Message) string {
return m.Cmdx(SAVE, path.Join(ice.VAR_TMP, kit.Hashs(mdb.UNIQ)), "")
}
func Temp(m *ice.Message, cb func(p string)) {
p := TempName(m)
defer os.Remove(p)
cb(p)
}
var ImageResize = func(m *ice.Message, p string, height, width uint) bool { return false }

View File

@ -20,7 +20,7 @@ func _tar_list(m *ice.Message, p string, cb func(*tar.Header, io.Reader, int)) {
case TGZ: case TGZ:
p = kit.Keys(kit.TrimExt(p, kit.Ext(p)), TAR, GZ) p = kit.Keys(kit.TrimExt(p, kit.Ext(p)), TAR, GZ)
case GZ: case GZ:
if f, e := gzip.NewReader(r); m.Warn(e, ice.ErrNotValid, p) { if f, e := gzip.NewReader(r); m.WarnNotValid(e, p) {
return return
} else { } else {
defer f.Close() defer f.Close()
@ -30,7 +30,7 @@ func _tar_list(m *ice.Message, p string, cb func(*tar.Header, io.Reader, int)) {
i := 0 i := 0
for r := tar.NewReader(r); ; i++ { for r := tar.NewReader(r); ; i++ {
h, e := r.Next() h, e := r.Next()
if m.Warn(e) || e == io.EOF { if m.WarnNotValid(e) || e == io.EOF {
break break
} }
if h.Size == 0 { if h.Size == 0 {

View File

@ -11,9 +11,15 @@ const TEMPLATE = "template"
func init() { func init() {
Index.MergeCommands(ice.Commands{ Index.MergeCommands(ice.Commands{
TEMPLATE: {Name: "template index path auto", Help: "模板", Actions: ice.MergeActions(ice.Actions{}), Hand: func(m *ice.Message, arg ...string) { TEMPLATE: {Name: "template index path auto", Help: "模板", Actions: ice.MergeActions(ice.Actions{
ice.CTX_INIT: {Hand: func(m *ice.Message, arg ...string) {
ice.AddRender(ice.RENDER_TEMPLATE, func(m *ice.Message, args ...ice.Any) string {
return Template(m, kit.Format(args[0]), args[1:]...)
})
}},
}), Hand: func(m *ice.Message, arg ...string) {
if len(arg) == 0 { if len(arg) == 0 {
m.Cmdy(ice.COMMAND).Action("filter:text").Option(ice.MSG_DISPLAY, "") m.Cmdy(ice.COMMAND).Option(ice.MSG_DISPLAY, "")
return return
} }
m.Search(arg[0], func(p *ice.Context, c *ice.Context, key string, cmd *ice.Command) { m.Search(arg[0], func(p *ice.Context, c *ice.Context, key string, cmd *ice.Command) {
@ -29,20 +35,21 @@ func init() {
}) })
} }
func init() { ice.Info.Template = Template }
func Template(m *ice.Message, p string, data ...ice.Any) string { func Template(m *ice.Message, p string, data ...ice.Any) string {
if len(data) == 0 { if text := TemplateText(m, p); text == "" {
return kit.Renders(TemplateText(m, p), m) return ""
} else if len(data) == 0 {
return kit.Renders(text, m)
} else {
return kit.Renders(text, data[0])
} }
return kit.Renders(TemplateText(m, p), data[0])
} }
var TemplateText = func(m *ice.Message, p string) string { var TemplateText = func(m *ice.Message, p string) string {
return m.Cmdx(CAT, TemplatePath(m, path.Base(p))) return m.Cmdx(CAT, kit.Select(TemplatePath(m, path.Base(p)), m.Option("_template")))
} }
var TemplatePath = func(m *ice.Message, arg ...string) string { var TemplatePath = func(m *ice.Message, arg ...string) string {
if p := path.Join(ice.SRC_TEMPLATE, m.PrefixKey(), path.Join(arg...)); Exists(m, p) { return path.Join(ice.SRC_TEMPLATE, m.PrefixKey(), path.Join(arg...))
return p
} else {
return p
}
} }

View File

@ -2,7 +2,6 @@ package nfs
import ( import (
"io" "io"
"os"
"path" "path"
ice "shylinux.com/x/icebergs" ice "shylinux.com/x/icebergs"
@ -11,25 +10,25 @@ import (
) )
func _trash_create(m *ice.Message, from string) { func _trash_create(m *ice.Message, from string) {
if m.Warn(from == "", ice.ErrNotValid, FROM) { if m.WarnNotValid(from == "", FROM) {
return return
} }
s, e := StatFile(m, from) s, e := StatFile(m, from)
defer os.Remove(from) if m.WarnNotFound(e, from) {
if m.Warn(e, ice.ErrNotFound, from) {
return return
} }
defer Remove(m, from)
p := path.Join(ice.VAR_TRASH, path.Base(from)) p := path.Join(ice.VAR_TRASH, path.Base(from))
kit.If(!s.IsDir(), func() { Open(m, from, func(r io.Reader) { p = path.Join(ice.VAR_TRASH, kit.HashsPath(r)) }) }) kit.If(!s.IsDir(), func() { Open(m, from, func(r io.Reader) { p = path.Join(ice.VAR_TRASH, kit.HashsPath(r)) }) })
RemoveAll(m, p) RemoveAll(m, p)
kit.If(!m.Warn(Rename(m, from, p)), func() { mdb.HashCreate(m, FROM, kit.Paths(from), FILE, p) }) kit.If(!m.WarnNotValid(Rename(m, from, p)), func() { mdb.HashCreate(m, FROM, kit.Paths(from), FILE, p) })
} }
const TRASH = "trash" const TRASH = "trash"
func init() { func init() {
Index.MergeCommands(ice.Commands{ Index.MergeCommands(ice.Commands{
TRASH: {Name: "trash hash auto prunes", Help: "回收站", Actions: ice.MergeActions(ice.Actions{ TRASH: {Name: "trash hash auto", Help: "回收站", Actions: ice.MergeActions(ice.Actions{
mdb.CREATE: {Hand: func(m *ice.Message, arg ...string) { mdb.CREATE: {Hand: func(m *ice.Message, arg ...string) {
_trash_create(m, kit.Paths(m.Option(FROM))) _trash_create(m, kit.Paths(m.Option(FROM)))
}}, }},
@ -37,7 +36,7 @@ func init() {
Remove(m, m.Option(FILE)) Remove(m, m.Option(FILE))
mdb.HashRemove(m, m.OptionSimple(mdb.HASH)) mdb.HashRemove(m, m.OptionSimple(mdb.HASH))
}}, }},
mdb.REVERT: {Hand: func(m *ice.Message, arg ...string) { mdb.REVERT: {Help: "恢复", Icon: "bi bi-folder-symlink", Hand: func(m *ice.Message, arg ...string) {
msg := mdb.HashSelect(m.Spawn(), m.Option(mdb.HASH)) msg := mdb.HashSelect(m.Spawn(), m.Option(mdb.HASH))
Rename(m, msg.Append(FILE), msg.Append(FROM)) Rename(m, msg.Append(FILE), msg.Append(FROM))
mdb.HashRemove(m, m.OptionSimple(mdb.HASH)) mdb.HashRemove(m, m.OptionSimple(mdb.HASH))

View File

@ -13,7 +13,7 @@ import (
) )
func _zip_list(m *ice.Message, p string, cb func(zip.FileHeader, io.Reader, int)) { func _zip_list(m *ice.Message, p string, cb func(zip.FileHeader, io.Reader, int)) {
if f, e := zip.OpenReader(p); m.Warn(e, ice.ErrNotValid, p) { if f, e := zip.OpenReader(p); m.WarnNotFound(e, p) {
return return
} else { } else {
defer f.Close() defer f.Close()

View File

@ -96,8 +96,8 @@ func (f *Frame) parse(m *ice.Message, h, line string) string {
return "" return ""
} }
msg := m.Spawn(f.target) msg := m.Spawn(f.target)
kit.If(h == STDIO, func() { msg.Option(ice.LOG_TRACEID, log.Traceid()) }) kit.If(h == STDIO, func() { msg.Option(ice.LOG_TRACEID, log.Traceid(m)) })
if msg.Cmdy(ls); h == STDIO && msg.IsErrNotFound() { if msg.Cmdy(ls); h == STDIO && msg.IsErrNotFoundIndex() {
msg.SetResult().Cmdy(cli.SYSTEM, ls) msg.SetResult().Cmdy(cli.SYSTEM, ls)
} }
kit.If(m.Option(ice.MSG_STATUS) == "", func() { m.StatusTimeCount() }) kit.If(m.Option(ice.MSG_STATUS) == "", func() { m.StatusTimeCount() })
@ -105,7 +105,7 @@ func (f *Frame) parse(m *ice.Message, h, line string) string {
return "" return ""
} }
func (f *Frame) scan(m *ice.Message, h, line string) *Frame { func (f *Frame) scan(m *ice.Message, h, line string) *Frame {
// kit.If(f.source == STDIO, func() { m.Option(ice.LOG_DISABLE, ice.TRUE) }) kit.If(f.source == STDIO, func() { m.Option(ice.LOG_DISABLE, ice.TRUE) })
f.ps1 = kit.Simple(mdb.Confv(m, PROMPT, kit.Keym(PS1))) f.ps1 = kit.Simple(mdb.Confv(m, PROMPT, kit.Keym(PS1)))
f.ps2 = kit.Simple(mdb.Confv(m, PROMPT, kit.Keym(PS2))) f.ps2 = kit.Simple(mdb.Confv(m, PROMPT, kit.Keym(PS2)))
ps, bio := f.ps1, bufio.NewScanner(f.stdin) ps, bio := f.ps1, bufio.NewScanner(f.stdin)
@ -148,6 +148,7 @@ func (f *Frame) Start(m *ice.Message, arg ...string) {
f.pipe, f.stdin, f.stdout = w, r, os.Stdout f.pipe, f.stdin, f.stdout = w, r, os.Stdout
kit.If(f.target == nil, func() { f.target = m.Target() }) kit.If(f.target == nil, func() { f.target = m.Target() })
m.Optionv(ice.MSG_OPTS, ice.MSG_USERNAME, ice.MSG_USERROLE) m.Optionv(ice.MSG_OPTS, ice.MSG_USERNAME, ice.MSG_USERROLE)
m.Option(ice.MSG_USERWEB, "http://localhost:9020")
f.scan(m, STDIO, "") f.scan(m, STDIO, "")
default: default:
if m.Option(ice.MSG_SCRIPT) != "" { if m.Option(ice.MSG_SCRIPT) != "" {
@ -183,7 +184,6 @@ func (f *Frame) Spawn(m *ice.Message, c *ice.Context, arg ...string) ice.Server
const ( const (
FRAME = "frame" FRAME = "frame"
SHELL = "shell" SHELL = "shell"
WEBIO = "webio"
STDIO = "stdio" STDIO = "stdio"
PS1 = "PS1" PS1 = "PS1"
PS2 = "PS2" PS2 = "PS2"
@ -194,7 +194,6 @@ const (
TARGET = "target" TARGET = "target"
PROMPT = "prompt" PROMPT = "prompt"
PRINTF = "printf" PRINTF = "printf"
SCREEN = "screen"
) )
func init() { func init() {
@ -228,16 +227,6 @@ func init() {
f.printf(m, kit.Select(m.Option(nfs.CONTENT), arg, 0)) f.printf(m, kit.Select(m.Option(nfs.CONTENT), arg, 0))
} }
}}, }},
SCREEN: {Name: "screen run text", Help: "输出命令", Hand: func(m *ice.Message, arg ...string) {
if f, ok := m.Target().Server().(*Frame); ok {
for _, line := range kit.Split(arg[0], lex.NL, lex.NL) {
fmt.Fprintf(f.pipe, line+lex.NL)
f.printf(m, line+lex.NL)
m.Sleep300ms()
}
m.Echo(f.res)
}
}},
}) })
} }

View File

@ -6,4 +6,4 @@ const SSH = "ssh"
var Index = &ice.Context{Name: SSH, Help: "终端模块"} var Index = &ice.Context{Name: SSH, Help: "终端模块"}
func init() { ice.Index.Register(Index, &Frame{}, SOURCE, RETURN, TARGET, PROMPT, PRINTF, SCREEN) } func init() { ice.Index.Register(Index, &Frame{}, SOURCE, RETURN, TARGET, PROMPT, PRINTF) }

View File

@ -19,7 +19,7 @@ func _server_udp(m *ice.Message, arg ...string) {
m.Assert(e) m.Assert(e)
buf := make([]byte, 2*ice.MOD_BUFS) buf := make([]byte, 2*ice.MOD_BUFS)
for { for {
if n, from, e := l.ReadFromUDP(buf[:]); !m.Warn(e) { if n, from, e := l.ReadFromUDP(buf[:]); !m.WarnNotValid(e) {
cb(from, buf[:n]) cb(from, buf[:n])
} else { } else {
break break
@ -34,20 +34,23 @@ func _client_dial_udp4(m *ice.Message, arg ...string) {
defer kit.If(e == nil, func() { c.Close() }) defer kit.If(e == nil, func() { c.Close() })
switch cb := m.OptionCB("").(type) { switch cb := m.OptionCB("").(type) {
case func(*net.UDPConn): case func(*net.UDPConn):
kit.If(!m.Warn(e), func() { cb(c) }) kit.If(!m.WarnNotValid(e), func() { cb(c) })
default: default:
m.ErrorNotImplement(cb) m.ErrorNotImplement(cb)
} }
} }
const ( const (
UDP4 = "udp4" UDP4 = "udp4"
SEND = "send" SEND = "send"
RECV = "recv" RECV = "recv"
ECHO = "echo"
DONE = "done"
DIRECT = "direct"
) )
func UDPAddr(m *ice.Message, host, port string) *net.UDPAddr { func UDPAddr(m *ice.Message, host, port string) *net.UDPAddr {
if addr, e := net.ResolveUDPAddr(UDP4, host+nfs.DF+port); !m.Warn(e, ice.ErrNotValid, host, port, logs.FileLineMeta(2)) { if addr, e := net.ResolveUDPAddr(UDP4, host+nfs.DF+port); !m.WarnNotValid(e, host, port, logs.FileLineMeta(2)) {
return addr return addr
} }
return nil return nil

View File

@ -2,6 +2,7 @@ package tcp
import ( import (
"net" "net"
"time"
ice "shylinux.com/x/icebergs" ice "shylinux.com/x/icebergs"
"shylinux.com/x/icebergs/base/mdb" "shylinux.com/x/icebergs/base/mdb"
@ -29,12 +30,12 @@ func (c *Conn) Write(b []byte) (int, error) {
func (c *Conn) Close() error { return c.Conn.Close() } func (c *Conn) Close() error { return c.Conn.Close() }
func _client_dial(m *ice.Message, arg ...string) { func _client_dial(m *ice.Message, arg ...string) {
c, e := net.Dial(TCP, m.Option(HOST)+nfs.DF+m.Option(PORT)) c, e := net.DialTimeout(TCP, m.Option(HOST)+nfs.DF+m.Option(PORT), 3*time.Second)
c = &Conn{Conn: c, m: m, s: &Stat{}} c = &Conn{Conn: c, m: m, s: &Stat{}}
defer kit.If(e == nil, func() { c.Close() }) defer kit.If(e == nil, func() { c.Close() })
switch cb := m.OptionCB("").(type) { switch cb := m.OptionCB("").(type) {
case func(net.Conn): case func(net.Conn):
kit.If(!m.Warn(e), func() { cb(c) }) kit.If(!m.WarnNotValid(e), func() { cb(c) })
default: default:
m.ErrorNotImplement(cb) m.ErrorNotImplement(cb)
} }

View File

@ -1,18 +1,35 @@
package tcp package tcp
import ( import (
"fmt"
"net" "net"
"os"
"strings" "strings"
ice "shylinux.com/x/icebergs" ice "shylinux.com/x/icebergs"
"shylinux.com/x/icebergs/base/aaa" "shylinux.com/x/icebergs/base/aaa"
"shylinux.com/x/icebergs/base/mdb" "shylinux.com/x/icebergs/base/mdb"
"shylinux.com/x/icebergs/base/nfs" "shylinux.com/x/icebergs/base/nfs"
"shylinux.com/x/icebergs/base/web/html"
kit "shylinux.com/x/toolkits" kit "shylinux.com/x/toolkits"
) )
func _host_list(m *ice.Message, name string) { func _host_domain(m *ice.Message) string {
return kit.GetValid(
func() string { return m.Option(ice.TCP_DOMAIN) },
func() string { return mdb.Config(m, DOMAIN) },
func() string { return os.Getenv(ice.TCP_DOMAIN) },
func() string {
if !kit.IsIn(m.ActionKey(), "", ice.LIST) {
return m.Cmdv(HOST, mdb.Config(m, ice.MAIN), aaa.IP)
}
return ""
},
func() string {
return LOCALHOST
},
)
}
func _host_list(m *ice.Message, name string) *ice.Message {
if ifs, e := net.Interfaces(); m.Assert(e) { if ifs, e := net.Interfaces(); m.Assert(e) {
for _, v := range ifs { for _, v := range ifs {
if !strings.Contains(v.Name, name) || len(v.HardwareAddr.String()) == 0 { if !strings.Contains(v.Name, name) || len(v.HardwareAddr.String()) == 0 {
@ -24,34 +41,40 @@ func _host_list(m *ice.Message, name string) {
if strings.Contains(ip[0], nfs.DF) || len(ip) == 0 { if strings.Contains(ip[0], nfs.DF) || len(ip) == 0 {
continue continue
} }
m.Push(mdb.INDEX, v.Index).Push(mdb.NAME, v.Name).Push(aaa.IP, ip[0]).Push("mask", ip[1]).Push("hard", v.HardwareAddr.String()) m.Push(mdb.INDEX, v.Index).Push(mdb.NAME, v.Name).Push(aaa.IP, ip[0]).Push(MASK, ip[1]).Push(MAC_ADDRESS, v.HardwareAddr.String())
} }
} }
} }
} }
if len(m.Appendv(aaa.IP)) == 0 { return m.SortInt(mdb.INDEX).StatusTimeCount(DOMAIN, _host_domain(m))
m.Push(mdb.INDEX, -1).Push(mdb.NAME, LOCALHOST).Push(aaa.IP, "127.0.0.1").Push("mask", "255.0.0.0").Push("hard", "")
}
m.SortInt(mdb.INDEX)
} }
const ( const (
LOCALHOST = "localhost" LOCALHOST = "localhost"
MAC_ADDRESS = "mac-address"
MASK = "mask"
DOMAIN = "domain"
GATEWAY = "gateway"
MACHINE = "machine"
ISLOCAL = "islocal" ISLOCAL = "islocal"
PUBLISH = "publish" PUBLISH = "publish"
GATEWAY = "gateway"
) )
const HOST = "host" const HOST = "host"
func init() { func init() {
Index.MergeCommands(ice.Commands{ Index.MergeCommands(ice.Commands{
HOST: {Name: "host name auto", Help: "主机", Actions: ice.MergeActions(ice.Actions{ HOST: {Name: "host name auto domain", Help: "主机", Meta: kit.Dict(
ice.CTX_TRANS, kit.Dict(html.INPUT, kit.Dict(
aaa.IP, "网络地址", MASK, "子网掩码", MAC_ADDRESS, "物理地址",
)),
), Actions: ice.MergeActions(ice.Actions{
ice.CTX_INIT: {Hand: func(m *ice.Message, arg ...string) { ice.CTX_INIT: {Hand: func(m *ice.Message, arg ...string) {
m.Cmd("", func(value ice.Maps) { m.Cmd("", aaa.WHITE, LOCALHOST, value[aaa.IP]) }) m.Cmd("", func(value ice.Maps) { m.Cmd("", aaa.WHITE, LOCALHOST, value[aaa.IP]) })
ice.Info.Host = mdb.Config(m, DOMAIN)
}}, }},
mdb.SEARCH: {Hand: func(m *ice.Message, arg ...string) { mdb.SEARCH: {Hand: func(m *ice.Message, arg ...string) {
if mdb.IsSearchPreview(m, arg) { if mdb.IsSearchPreview(m, arg) && m.Cmd(HOST).Length() > 0 {
ip := m.Cmdv(HOST, GATEWAY, aaa.IP) ip := m.Cmdv(HOST, GATEWAY, aaa.IP)
m.PushSearch(mdb.TYPE, GATEWAY, mdb.NAME, ip, mdb.TEXT, "http://"+ip) m.PushSearch(mdb.TYPE, GATEWAY, mdb.NAME, ip, mdb.TEXT, "http://"+ip)
} }
@ -70,22 +93,32 @@ func init() {
} }
}}, }},
PUBLISH: {Hand: func(m *ice.Message, arg ...string) { PUBLISH: {Hand: func(m *ice.Message, arg ...string) {
if strings.Contains(arg[0], LOCALHOST) { for _, p := range []string{LOCALHOST, "127.0.0.1", m.Option("tcp_localhost")} {
arg[0] = strings.Replace(arg[0], LOCALHOST, m.Cmdv(HOST, mdb.Config(m, "publish"), aaa.IP), 1) if p != "" && strings.Contains(arg[0], p) {
} else if strings.Contains(arg[0], "127.0.0.1") { arg[0] = strings.Replace(arg[0], p, _host_domain(m), 1)
arg[0] = strings.Replace(arg[0], "127.0.0.1", m.Cmdv(HOST, mdb.Config(m, "publish"), aaa.IP), 1) break
}
} }
m.Echo(arg[0]) m.Echo(arg[0])
}}, }},
GATEWAY: {Hand: func(m *ice.Message, arg ...string) { GATEWAY: {Hand: func(m *ice.Message, arg ...string) {
m.Push(aaa.IP, kit.Keys(kit.Slice(strings.Split(m.Cmdv(HOST, aaa.IP), nfs.PT), 0, 3), "1")) m.Push(aaa.IP, kit.Keys(kit.Slice(strings.Split(m.Cmdv(HOST, aaa.IP), nfs.PT), 0, 3), "1"))
}}, }},
}, mdb.HashAction(mdb.SHORT, mdb.TEXT), mdb.ClearOnExitHashAction()), Hand: func(m *ice.Message, arg ...string) { DOMAIN: {Name: "domain ip", Help: "主机", Icon: "bi bi-house-check", Hand: func(m *ice.Message, arg ...string) {
_host_list(m, kit.Select("", arg, 0)) kit.If(m.Option(aaa.IP), func(p string) { ice.Info.Host = p; mdb.Config(m, DOMAIN, p) })
m.Echo(mdb.Config(m, DOMAIN))
}},
}, mdb.HashAction(mdb.SHORT, mdb.TEXT)), Hand: func(m *ice.Message, arg ...string) {
_host_list(m, kit.Select("", arg, 0)).Table(func(value ice.Maps) {
if value[aaa.IP] == mdb.Config(m, DOMAIN) {
m.Push(mdb.STATUS, "current").PushButton("")
} else {
m.Push(mdb.STATUS, "").PushButton(DOMAIN)
}
})
}}, }},
}) })
} }
func Address(host, port string) string { return fmt.Sprintf("%s:%s", host, port) }
func IsLocalHost(m *ice.Message, ip string) bool { return m.Cmdx(HOST, ISLOCAL, ip) == ice.OK } func IsLocalHost(m *ice.Message, ip string) bool { return m.Cmdx(HOST, ISLOCAL, ip) == ice.OK }
func PublishLocalhost(m *ice.Message, url string) string { return m.Cmdx(HOST, PUBLISH, url) } func PublishLocalhost(m *ice.Message, url string) string { return m.Cmdx(HOST, PUBLISH, url) }

View File

@ -3,6 +3,7 @@ package tcp
import ( import (
"net" "net"
"path" "path"
"runtime"
"strconv" "strconv"
"strings" "strings"
@ -14,9 +15,8 @@ import (
kit "shylinux.com/x/toolkits" kit "shylinux.com/x/toolkits"
) )
func _port_right(m *ice.Message, arg ...string) string { func _port_right(m *ice.Message, current, begin, end int) string {
current, end := kit.Int(kit.Select(mdb.Config(m, CURRENT), arg, 0)), kit.Int(mdb.Config(m, END)) kit.If(current >= end, func() { current = begin })
kit.If(current >= end, func() { current = kit.Int(mdb.Config(m, BEGIN)) })
for i := current; i < end; i++ { for i := current; i < end; i++ {
if p := path.Join(ice.USR_LOCAL_DAEMON, kit.Format(i)); nfs.Exists(m, p) { if p := path.Join(ice.USR_LOCAL_DAEMON, kit.Format(i)); nfs.Exists(m, p) {
@ -33,11 +33,19 @@ func _port_right(m *ice.Message, arg ...string) string {
} }
const ( const (
PORT_22 = "22"
PORT_80 = "80"
PORT_443 = "443"
PORT_9020 = "9020"
PORT_9022 = "9022"
SOCKET = "socket" SOCKET = "socket"
BEGIN = "begin" BEGIN = "begin"
CURRENT = "current" CURRENT = "current"
RANDOM = "random" RANDOM = "random"
END = "end" END = "end"
PID = "pid"
SPACE = "space"
) )
const PORT = "port" const PORT = "port"
@ -46,7 +54,7 @@ func init() {
PORT: {Name: "port port path auto socket", Help: "端口", Actions: ice.MergeActions(ice.Actions{ PORT: {Name: "port port path auto socket", Help: "端口", Actions: ice.MergeActions(ice.Actions{
mdb.INPUTS: {Hand: func(m *ice.Message, arg ...string) { mdb.INPUTS: {Hand: func(m *ice.Message, arg ...string) {
switch arg[0] { switch arg[0] {
case SERVER: case HOST, SERVER:
m.Cmd(PORT, SOCKET, func(value ice.Maps) { m.Cmd(PORT, SOCKET, func(value ice.Maps) {
switch value[mdb.STATUS] { switch value[mdb.STATUS] {
case "LISTEN": case "LISTEN":
@ -54,6 +62,15 @@ func init() {
} }
}) })
case PORT: case PORT:
if runtime.GOOS == "darwin" {
ls := kit.SplitLine(m.Cmd("system", "sh", "-c", `lsof -nP -i4TCP | grep LISTEN | awk '{print $1 " " $9 }'`).Result())
kit.For(ls, func(p string) {
ls := kit.SplitWord(p)
m.Push(arg[0], kit.Split(ls[1], ":")[1]).Push(SERVER, ls[0])
})
m.Sort(arg[0], ice.INT)
return
}
m.Cmd(PORT, SOCKET, func(value ice.Maps) { m.Cmd(PORT, SOCKET, func(value ice.Maps) {
switch value[mdb.STATUS] { switch value[mdb.STATUS] {
case "LISTEN": case "LISTEN":
@ -63,19 +80,28 @@ func init() {
}) })
} }
}}, }},
SOCKET: {Hand: func(m *ice.Message, arg ...string) { SOCKET: {Help: "端口", Hand: func(m *ice.Message, arg ...string) {
parse := func(str string) int64 { parse := func(str string) int64 { port, _ := strconv.ParseInt(str, 16, 32); return port }
port, _ := strconv.ParseInt(str, 16, 32)
return port
}
trans := func(str string) string { trans := func(str string) string {
switch str { switch str {
case "0A":
return "LISTEN"
case "01": case "01":
return "ESTABLISHED" return "ESTABLISHED"
case "02":
return "TCP_SYNC_SEND"
case "03":
return "TCP_SYNC_RECV"
case "04":
return "TCP_FIN_WAIT1"
case "05":
return "TCP_FIN_WAIT2"
case "06": case "06":
return "TIME_WAIT" return "TIME_WAIT"
case "07":
return "TCP_CLOSE"
case "08":
return "TCP_CLOSE_WAIT"
case "0A":
return "LISTEN"
default: default:
return str return str
} }
@ -97,29 +123,48 @@ func init() {
ls = kit.Split(value["remote_address"], ":") ls = kit.Split(value["remote_address"], ":")
m.Push("remote", kit.Format("%d.%d.%d.%d:%d", parse(ls[0][30:32]), parse(ls[0][28:30]), parse(ls[0][26:28]), parse(ls[0][24:26]), parse(ls[1]))) m.Push("remote", kit.Format("%d.%d.%d.%d:%d", parse(ls[0][30:32]), parse(ls[0][28:30]), parse(ls[0][26:28]), parse(ls[0][24:26]), parse(ls[1])))
}) })
m.Sort("status,local").StatusTimeCount(stats) m.Sort("status,local", []string{"LISTEN", "ESTABLISHED", "TIME_WAIT"}).StatusTimeCount(stats)
}}, }},
nfs.TRASH: {Hand: func(m *ice.Message, arg ...string) { nfs.TRASH: {Hand: func(m *ice.Message, arg ...string) {
m.Assert(m.Option(PORT) != "") m.Assert(m.Option(PORT) != "")
nfs.Trash(m, path.Join(ice.USR_LOCAL_DAEMON, m.Option(PORT))) nfs.Trash(m, path.Join(ice.USR_LOCAL_DAEMON, m.Option(PORT)))
mdb.HashRemove(m)
}}, }},
aaa.RIGHT: {Hand: func(m *ice.Message, arg ...string) { m.Echo(_port_right(m, arg...)) }}, aaa.RIGHT: {Hand: func(m *ice.Message, arg ...string) { m.Echo(PortRight(m, arg...)) }},
CURRENT: {Hand: func(m *ice.Message, arg ...string) { m.Echo(mdb.Config(m, CURRENT)) }}, CURRENT: {Hand: func(m *ice.Message, arg ...string) { m.Echo(mdb.Config(m, CURRENT)) }},
}, mdb.HashAction(BEGIN, 10000, CURRENT, 10000, END, 20000)), Hand: func(m *ice.Message, arg ...string) { STOP: {Hand: func(m *ice.Message, arg ...string) { PortCmds(m, arg...); mdb.HashModify(m, PID, "") }},
START: {Hand: func(m *ice.Message, arg ...string) { PortCmds(m, arg...); mdb.HashModify(m, PID, m.Append(PID)) }},
}, mdb.HashAction(BEGIN, 10000, END, 20000,
mdb.SHORT, PORT, mdb.FIELD, "time,port,pid,cmd,name,text,icon,space,index",
)), Hand: func(m *ice.Message, arg ...string) {
if len(arg) > 0 { if len(arg) > 0 {
m.Cmdy(nfs.DIR, arg[1:], kit.Dict(nfs.DIR_ROOT, path.Join(ice.USR_LOCAL_DAEMON, arg[0]))) m.Cmdy(nfs.DIR, arg[1:], kit.Dict(nfs.DIR_ROOT, path.Join(ice.USR_LOCAL_DAEMON, arg[0])))
return return
} }
current := kit.Int(mdb.Config(m, BEGIN)) current := kit.Int(mdb.Config(m, BEGIN))
m.Options(nfs.DIR_ROOT, ice.USR_LOCAL_DAEMON).Cmd(nfs.DIR, nfs.PWD, func(value ice.Maps) { mdb.HashSelect(m, arg...).Table(func(value ice.Maps) {
bin := m.Cmdv(nfs.DIR, path.Join(value[nfs.PATH], ice.BIN), nfs.PATH) current = kit.Max(current, kit.Int(value[PORT]))
kit.If(bin == "", func() { bin = m.Cmdv(nfs.DIR, path.Join(value[nfs.PATH], "sbin"), nfs.PATH) }) if value[PID] == "" {
port := kit.Int(path.Base(value[nfs.PATH])) m.PushButton(START, nfs.TRASH)
m.Push(mdb.TIME, value[mdb.TIME]).Push(PORT, port).Push(nfs.SIZE, value[nfs.SIZE]).Push(ice.BIN, strings.TrimPrefix(bin, value[nfs.PATH])) } else {
current = kit.Max(current, port) m.PushButton(STOP)
}
}) })
m.PushAction(nfs.TRASH).StatusTimeCount(ctx.ConfigSimple(m, BEGIN, CURRENT, END)).SortInt(PORT)
mdb.Config(m, CURRENT, current) mdb.Config(m, CURRENT, current)
m.StatusTimeCount(mdb.ConfigSimple(m, BEGIN, CURRENT, END)).SortInt(PORT)
}}, }},
}) })
ice.Info.Inputs = append(ice.Info.Inputs, func(m *ice.Message, arg ...string) {
switch arg[0] {
case PORT:
m.SetAppend().Cmdy(PORT, mdb.INPUTS, arg)
}
})
}
func PortRight(m *ice.Message, arg ...string) string {
current, begin, end := kit.Select("20000", mdb.Config(m, CURRENT)), kit.Select("20000", mdb.Config(m, BEGIN)), kit.Select("30000", mdb.Config(m, END))
return _port_right(m, kit.Int(kit.Select(kit.Select(begin, current), arg, 0)), kit.Int(kit.Select(begin, arg, 1)), kit.Int(kit.Select(end, arg, 2)))
}
func PortCmds(m *ice.Message, arg ...string) {
m.Cmdy(SPACE, m.Option(SPACE), m.Option(ctx.INDEX), m.ActionKey())
} }

View File

@ -30,7 +30,7 @@ func (l Listener) Close() error {
func _server_listen(m *ice.Message, arg ...string) { func _server_listen(m *ice.Message, arg ...string) {
l, e := net.Listen(TCP, m.Option(HOST)+nfs.DF+m.Option(PORT)) l, e := net.Listen(TCP, m.Option(HOST)+nfs.DF+m.Option(PORT))
if m.Warn(e) { if m.WarnNotValid(e) {
return return
} }
l = &Listener{Listener: l, m: m, h: mdb.HashCreate(m, arg, kit.Dict(mdb.TARGET, l), STATUS, kit.Select(ERROR, OPEN, e == nil), ERROR, kit.Format(e)), s: &Stat{}} l = &Listener{Listener: l, m: m, h: mdb.HashCreate(m, arg, kit.Dict(mdb.TARGET, l), STATUS, kit.Select(ERROR, OPEN, e == nil), ERROR, kit.Format(e)), s: &Stat{}}
@ -40,7 +40,7 @@ func _server_listen(m *ice.Message, arg ...string) {
cb(l) cb(l)
case func(net.Conn): case func(net.Conn):
for { for {
if c, e := l.Accept(); !m.Warn(e) { if c, e := l.Accept(); !m.WarnNotValid(e) {
cb(c) cb(c)
} else { } else {
break break
@ -52,10 +52,13 @@ func _server_listen(m *ice.Message, arg ...string) {
} }
const ( const (
PROTOCOL = "protocol" PROTOCOL = "protocol"
HOSTPORT = "hostport" HOSTPORT = "hostport"
HOSTNAME = "hostname" HOSTNAME = "hostname"
NODENAME = "nodename" NODENAME = "nodename"
NODETYPE = "nodetype"
BANDWIDTH = "bandwidth"
ADDRESS = "address"
) )
const ( const (
PROTO = "proto" PROTO = "proto"

View File

@ -9,6 +9,6 @@ const TCP = "tcp"
var Index = &ice.Context{Name: TCP, Help: "通信模块"} var Index = &ice.Context{Name: TCP, Help: "通信模块"}
func init() { ice.Index.Register(Index, nil, HOST, PORT, CLIENT, SERVER) } func init() { ice.Index.Register(Index, nil, WIFI, HOST, PORT, CLIENT, SERVER) }
func Prefix(arg ...ice.Any) string { return kit.Keys(TCP, kit.Keys(arg...)) } func Prefix(arg ...ice.Any) string { return kit.Keys(TCP, kit.Keys(arg...)) }

47
base/tcp/wifi.go Normal file
View File

@ -0,0 +1,47 @@
package tcp
import (
"strings"
ice "shylinux.com/x/icebergs"
"shylinux.com/x/icebergs/base/aaa"
"shylinux.com/x/icebergs/base/mdb"
kit "shylinux.com/x/toolkits"
)
const (
SSID = "ssid"
)
const WIFI = "wifi"
func init() {
const (
NETWORKSETUP = "networksetup"
CONNECT = "connect"
)
Index.MergeCommands(ice.Commands{
WIFI: {Help: "无线", Icon: "AirPort Utility.png", Actions: ice.MergeActions(ice.Actions{
mdb.INPUTS: {Hand: func(m *ice.Message, arg ...string) {
switch arg[0] {
case SSID:
kit.For(kit.Slice(kit.SplitLine(m.System(NETWORKSETUP, "-listpreferredwirelessnetworks", "en0").Result()), 1), func(name string) {
m.Push(arg[0], strings.TrimSpace(name))
})
}
}},
CONNECT: {Help: "连接", Hand: func(m *ice.Message, arg ...string) {
m.ToastProcess()
msg := mdb.HashSelect(m.Spawn(), m.Option(SSID, strings.TrimSpace(m.Option(SSID))))
if res := m.System(NETWORKSETUP, "-setairportnetwork", "en0", kit.Select(m.Option(SSID), msg.Append(SSID)), msg.Append(aaa.PASSWORD)); res.Result() != "" {
m.Echo(res.Result()).ToastFailure(res.Result())
} else {
m.ProcessHold()
}
}},
}, mdb.ExportHashAction(mdb.SHORT, SSID, mdb.FIELD, "time,ssid,password")), Hand: func(m *ice.Message, arg ...string) {
if mdb.HashSelect(m, arg...).PushAction(CONNECT, mdb.REMOVE); len(arg) > 0 {
m.EchoQRCode(kit.Format("WIFI:T:WPA;S:%s;P:%s;H:false;;", m.Append(SSID), m.Append(aaa.PASSWORD)))
}
}},
})
}

View File

@ -2,9 +2,15 @@ package web
import ( import (
"net/http" "net/http"
"path" "os"
ice "shylinux.com/x/icebergs" ice "shylinux.com/x/icebergs"
"shylinux.com/x/icebergs/base/aaa"
"shylinux.com/x/icebergs/base/cli"
"shylinux.com/x/icebergs/base/mdb"
"shylinux.com/x/icebergs/base/nfs"
"shylinux.com/x/icebergs/base/tcp"
"shylinux.com/x/icebergs/base/web/html"
kit "shylinux.com/x/toolkits" kit "shylinux.com/x/toolkits"
) )
@ -12,9 +18,50 @@ const ADMIN = "admin"
func init() { func init() {
Index.MergeCommands(ice.Commands{ Index.MergeCommands(ice.Commands{
ADMIN: {Name: "admin index list", Help: "管理", Hand: func(m *ice.Message, arg ...string) { ADMIN: {Name: "admin index list", Help: "后台", Role: aaa.VOID, Actions: ice.MergeActions(ice.Actions{
kit.If(len(arg) == 0, func() { arg = append(arg, SPACE, DOMAIN) }) DREAM_ACTION: {Hand: func(m *ice.Message, arg ...string) { DreamProcessIframe(m, arg...) }},
m.Cmdy(SPIDE, ice.OPS, SPIDE_RAW, http.MethodGet, CHAT_CMD+path.Join(arg...)) }, DreamTablesAction()), Hand: func(m *ice.Message, arg ...string) {
if m.Option(ice.MSG_SOURCE) != "" {
RenderMain(m)
} else {
kit.If(len(arg) == 0, func() { arg = append(arg, SPACE, DOMAIN) })
m.Cmd(SPIDE, mdb.CREATE, HostPort(m, tcp.LOCALHOST, kit.GetValid(
func() string { return m.Cmdx(nfs.CAT, ice.VAR_LOG_ICE_PORT) },
func() string { return m.Cmdx(nfs.CAT, kit.Path(os.Args[0], "../", ice.VAR_LOG_ICE_PORT)) },
func() string { return m.Cmdx(nfs.CAT, kit.Path(os.Args[0], "../../", ice.VAR_LOG_ICE_PORT)) },
func() string { return tcp.PORT_9020 },
)), ice.OPS)
args := []string{}
for i := range arg {
if arg[i] == "--" {
arg, args = arg[:i], arg[i+1:]
break
}
}
kit.If(os.Getenv(cli.CTX_OPS), func(p string) { m.Optionv(SPIDE_HEADER, html.XHost, p) })
m.Cmdy(SPIDE, ice.OPS, SPIDE_RAW, http.MethodPost, C(arg...), cli.PWD, kit.Path(""), args)
}
}}, }},
}) })
} }
func AdminCmd(m *ice.Message, cmd string, arg ...ice.Any) *ice.Message {
if ice.Info.NodeType == WORKER {
return m.Cmd(append([]ice.Any{SPACE, ice.OPS, cmd}, arg...)...)
} else {
return m.Cmd(append([]ice.Any{cmd}, arg...)...)
}
}
func OpsCmd(m *ice.Message, cmd string, arg ...ice.Any) *ice.Message {
if ice.Info.NodeType == WORKER {
return m.Cmd(append([]ice.Any{SPACE, ice.OPS, cmd}, arg...)...)
} else {
return m.Cmd(append([]ice.Any{cmd}, arg...)...)
}
}
func DevCmd(m *ice.Message, cmd string, arg ...ice.Any) *ice.Message {
if ice.Info.NodeType == WORKER {
return m.Cmd(append([]ice.Any{SPACE, ice.OPS, SPACE, ice.DEV, cmd}, arg...)...)
} else {
return m.Cmd(append([]ice.Any{SPACE, ice.DEV, cmd}, arg...)...)
}
}

View File

@ -8,6 +8,7 @@ import (
"shylinux.com/x/icebergs/base/aaa" "shylinux.com/x/icebergs/base/aaa"
"shylinux.com/x/icebergs/base/mdb" "shylinux.com/x/icebergs/base/mdb"
"shylinux.com/x/icebergs/base/nfs" "shylinux.com/x/icebergs/base/nfs"
"shylinux.com/x/icebergs/base/web/html"
kit "shylinux.com/x/toolkits" kit "shylinux.com/x/toolkits"
) )
@ -32,13 +33,15 @@ func BasicSess(m *ice.Message) {
m.Options(ice.MSG_SESSID, kit.Select(m.Option(ice.MSG_SESSID), m.Option(CookieName(m.Option(ice.MSG_USERWEB))))) m.Options(ice.MSG_SESSID, kit.Select(m.Option(ice.MSG_SESSID), m.Option(CookieName(m.Option(ice.MSG_USERWEB)))))
aaa.SessCheck(m, m.Option(ice.MSG_SESSID)) aaa.SessCheck(m, m.Option(ice.MSG_SESSID))
} }
func BasicCheck(m *ice.Message, realm string) bool { func BasicCheck(m *ice.Message, realm string, check ...func(*ice.Message) bool) bool {
switch ls := kit.Split(m.R.Header.Get(Authorization)); kit.Select("", ls, 0) { switch ls := kit.Split(m.R.Header.Get(html.Authorization)); kit.Select("", ls, 0) {
case Basic: case html.Basic:
if buf, err := base64.StdEncoding.DecodeString(kit.Select("", ls, 1)); !m.Warn(err) { if buf, err := base64.StdEncoding.DecodeString(kit.Select("", ls, 1)); !m.WarnNotValid(err) {
if ls := strings.SplitN(string(buf), ":", 2); !m.Warn(len(ls) < 2) { if ls := strings.SplitN(string(buf), ":", 2); !m.WarnNotValid(len(ls) < 2 || ls[1] == "", html.Basic) {
if msg := m.Cmd(TOKEN, ls[1]); !m.Warn(msg.Time() > msg.Append(mdb.TIME)) { if msg := m.Cmd(TOKEN, ls[1]); !m.WarnNotValid(msg.Time() > msg.Append(mdb.TIME)) {
return true if len(check) == 0 || check[0](msg) {
return true
}
} }
} }
} }

View File

@ -2,9 +2,11 @@ package web
import ( import (
"net" "net"
"strings"
ice "shylinux.com/x/icebergs" ice "shylinux.com/x/icebergs"
"shylinux.com/x/icebergs/base/aaa" "shylinux.com/x/icebergs/base/aaa"
"shylinux.com/x/icebergs/base/cli"
"shylinux.com/x/icebergs/base/gdb" "shylinux.com/x/icebergs/base/gdb"
"shylinux.com/x/icebergs/base/mdb" "shylinux.com/x/icebergs/base/mdb"
"shylinux.com/x/icebergs/base/nfs" "shylinux.com/x/icebergs/base/nfs"
@ -14,20 +16,31 @@ import (
) )
func _broad_send(m *ice.Message, to_host, to_port string, host, port string, arg ...string) { func _broad_send(m *ice.Message, to_host, to_port string, host, port string, arg ...string) {
m.Cmd(tcp.CLIENT, tcp.DIAL, mdb.TYPE, tcp.UDP4, tcp.HOST, to_host, tcp.PORT, kit.Select("9020", to_port), func(s *net.UDPConn) { m.Cmd(tcp.CLIENT, tcp.DIAL, mdb.TYPE, tcp.UDP4, tcp.HOST, to_host, tcp.PORT, kit.Select(tcp.PORT_9020, to_port), func(s *net.UDPConn) {
msg := m.Spawn(kit.Dict(tcp.HOST, host, tcp.PORT, port, arg)) msg := m.Spawn(kit.Dict(tcp.HOST, host, tcp.PORT, port, arg))
msg.Logs(tcp.SEND, BROAD, msg.FormatsMeta(nil), nfs.TO, tcp.HostPort(to_host, to_port)).FormatsMeta(s) msg.Logs(tcp.SEND, BROAD, msg.FormatsMeta(nil), nfs.TO, tcp.HostPort(to_host, to_port)).FormatsMeta(s)
}) })
} }
func _broad_serve(m *ice.Message) { func _broad_serve(m *ice.Message) {
m.GoSleep("30ms", tcp.HOST, func(value ice.Maps) { if m.Cmd(tcp.HOST).Length() == 0 {
_broad_send(m, "", "", value[aaa.IP], m.Option(tcp.PORT), gdb.EVENT, tcp.LISTEN, mdb.NAME, ice.Info.NodeName, mdb.TYPE, ice.Info.NodeType) return
}
m.GoSleep300ms(func() {
m.Cmd(tcp.HOST, func(value ice.Maps) {
_broad_send(m, "", "", value[aaa.IP], m.Option(tcp.PORT), kit.Simple(gdb.EVENT, tcp.LISTEN, mdb.NAME, ice.Info.NodeName, mdb.TYPE, ice.Info.NodeType, mdb.TIME, m.Time(), cli.SimpleMake())...)
})
}) })
m.Cmd(tcp.SERVER, tcp.LISTEN, mdb.TYPE, tcp.UDP4, mdb.NAME, logs.FileLine(1), m.OptionSimple(tcp.HOST, tcp.PORT), func(from *net.UDPAddr, buf []byte) { m.Cmd(tcp.SERVER, tcp.LISTEN, mdb.TYPE, tcp.UDP4, mdb.NAME, logs.FileLine(1), m.OptionSimple(tcp.HOST, tcp.PORT), func(from *net.UDPAddr, buf []byte) {
if m.WarnNotValid(len(buf) > 1024, "broad recv buf size too large") {
return
}
msg := m.Spawn(buf).Logs(tcp.RECV, BROAD, string(buf), nfs.FROM, from) msg := m.Spawn(buf).Logs(tcp.RECV, BROAD, string(buf), nfs.FROM, from)
if strings.HasPrefix(msg.Option(tcp.HOST), "169.254") {
return
}
if m.Cmd(BROAD, mdb.CREATE, msg.OptionSimple(kit.Simple(msg.Optionv(ice.MSG_OPTION))...)); msg.Option(gdb.EVENT) == tcp.LISTEN { if m.Cmd(BROAD, mdb.CREATE, msg.OptionSimple(kit.Simple(msg.Optionv(ice.MSG_OPTION))...)); msg.Option(gdb.EVENT) == tcp.LISTEN {
m.Cmds(BROAD, func(value ice.Maps) { m.Cmds(BROAD, func(value ice.Maps) {
_broad_send(m, msg.Option(tcp.HOST), msg.Option(tcp.PORT), value[tcp.HOST], value[tcp.PORT], mdb.TYPE, value[mdb.TYPE], mdb.NAME, value[mdb.NAME]) _broad_send(m, msg.Option(tcp.HOST), msg.Option(tcp.PORT), value[tcp.HOST], value[tcp.PORT], kit.Simple(value)...)
}) })
} }
}) })
@ -37,24 +50,40 @@ const BROAD = "broad"
func init() { func init() {
Index.MergeCommands(ice.Commands{ Index.MergeCommands(ice.Commands{
BROAD: {Help: "广播", Actions: ice.MergeActions(ice.Actions{ BROAD: {Help: "广播台", Icon: "Podcasts.png", Actions: ice.MergeActions(ice.Actions{
SERVE_START: {Hand: func(m *ice.Message, arg ...string) { gdb.Go(m, _broad_serve) }},
mdb.SEARCH: {Hand: func(m *ice.Message, arg ...string) { mdb.SEARCH: {Hand: func(m *ice.Message, arg ...string) {
if mdb.IsSearchPreview(m, arg) { if mdb.IsSearchPreview(m, arg) {
host, domain := m.Cmdv(tcp.HOST, aaa.IP), UserWeb(m).Hostname() host, domain := m.Cmdv(tcp.HOST, aaa.IP), UserWeb(m).Hostname()
m.Cmds("", func(value ice.Maps) { m.Cmds("", func(value ice.Maps) {
switch kit.If(value[tcp.HOST] == host, func() { value[tcp.HOST] = domain }); value[mdb.TYPE] { switch kit.If(value[tcp.HOST] == host, func() { value[tcp.HOST] = domain }); value[mdb.TYPE] {
case "sshd": case "sshd":
m.PushSearch(mdb.NAME, Script(m, "ssh -p %s %s@%s", value[tcp.PORT], m.Option(ice.MSG_USERNAME), value[tcp.HOST]), mdb.TEXT, Domain(value[tcp.HOST], value[tcp.PORT]), value) m.PushSearch(mdb.NAME, Script(m, "ssh -p %s %s@%s", value[tcp.PORT], m.Option(ice.MSG_USERNAME), value[tcp.HOST]), mdb.TEXT, HostPort(m, value[tcp.HOST], value[tcp.PORT]), value)
default: default:
m.PushSearch(mdb.TEXT, Domain(value[tcp.HOST], value[tcp.PORT]), value) m.PushSearch(mdb.TEXT, HostPort(m, value[tcp.HOST], value[tcp.PORT]), value)
} }
}) })
} }
}}, }},
SERVE_START: {Hand: func(m *ice.Message, arg ...string) { gdb.Go(m, _broad_serve) }}, SERVE: {Name: "serve port=9020 host", Hand: func(m *ice.Message, arg ...string) { gdb.Go(m, _broad_serve) }},
SERVE: {Name: "serve port=9020 host", Hand: func(m *ice.Message, arg ...string) { gdb.Go(m, _broad_serve) }}, ADMIN: {Hand: func(m *ice.Message, arg ...string) { broadOpen(m) }},
OPEN: {Hand: func(m *ice.Message, arg ...string) { m.ProcessOpen(Domain(m.Option(tcp.HOST), m.Option(tcp.PORT))) }}, DREAM: {Hand: func(m *ice.Message, arg ...string) { broadOpen(m) }},
tcp.SEND: {Hand: func(m *ice.Message, arg ...string) { _broad_send(m, "", "", "", "", arg...) }}, VIMER: {Hand: func(m *ice.Message, arg ...string) { broadOpen(m) }},
}, mdb.HashAction(mdb.SHORT, "host,port", mdb.FIELD, "time,hash,type,name,host,port", mdb.ACTION, OPEN), mdb.ClearOnExitHashAction())}, SPIDE: {Name: "spide name type=repos", Icon: "bi bi-house-add", Hand: func(m *ice.Message, arg ...string) {
m.Cmd(SPIDE, mdb.CREATE, HostPort(m, m.Option(tcp.HOST), m.Option(tcp.PORT)), m.Option(mdb.NAME))
}},
OPEN: {Hand: func(m *ice.Message, arg ...string) {
m.ProcessOpen(HostPort(m, m.Option(tcp.HOST), m.Option(tcp.PORT)))
}},
tcp.SEND: {Hand: func(m *ice.Message, arg ...string) { _broad_send(m, "", "", "", "", arg...) }},
}, gdb.EventsAction(SERVE_START), mdb.HashAction(mdb.SHORT, "host,port",
mdb.FIELD, "time,hash,type,name,host,port,module,version,commitTime,compileTime,bootTime,kernel,arch",
mdb.ACTION, "admin,dream,vimer,spide,open", mdb.SORT, "type,name,host,port"), mdb.ClearOnExitHashAction()), Hand: func(m *ice.Message, arg ...string) {
mdb.HashSelect(m, arg...)
m.StatusTimeCount("nodename", ice.Info.NodeName)
}},
}) })
} }
func broadOpen(m *ice.Message) {
m.ProcessOpen(HostPort(m, m.Option(mdb.NAME), m.Option(tcp.PORT)) + C(m.ActionKey()))
}

View File

@ -5,9 +5,10 @@ import (
"net/http" "net/http"
"os" "os"
"path" "path"
"strings"
ice "shylinux.com/x/icebergs" ice "shylinux.com/x/icebergs"
"shylinux.com/x/icebergs/base/ctx" "shylinux.com/x/icebergs/base/aaa"
"shylinux.com/x/icebergs/base/mdb" "shylinux.com/x/icebergs/base/mdb"
"shylinux.com/x/icebergs/base/nfs" "shylinux.com/x/icebergs/base/nfs"
"shylinux.com/x/icebergs/base/tcp" "shylinux.com/x/icebergs/base/tcp"
@ -18,7 +19,7 @@ import (
func _cache_name(m *ice.Message, h string) string { return path.Join(ice.VAR_FILE, h[:2], h) } func _cache_name(m *ice.Message, h string) string { return path.Join(ice.VAR_FILE, h[:2], h) }
func _cache_mime(m *ice.Message, mime, name string) string { func _cache_mime(m *ice.Message, mime, name string) string {
if mime == ApplicationOctet { if mime == html.ApplicationOctet {
if kit.ExtIsImage(name) { if kit.ExtIsImage(name) {
mime = IMAGE + nfs.PS + kit.Ext(name) mime = IMAGE + nfs.PS + kit.Ext(name)
} else if kit.ExtIsVideo(name) { } else if kit.ExtIsVideo(name) {
@ -30,10 +31,10 @@ func _cache_mime(m *ice.Message, mime, name string) string {
return mime return mime
} }
func _cache_save(m *ice.Message, mime, name, text string, arg ...string) { func _cache_save(m *ice.Message, mime, name, text string, arg ...string) {
if m.Warn(name == "", ice.ErrNotValid, mdb.NAME) { if m.WarnNotValid(name == "", mdb.NAME) {
return return
} else if len(text) > 512 { } else if len(text) > 512 {
p := m.Cmdx(nfs.SAVE, _cache_name(m, kit.Hashs(text)), text) p := m.Cmdx(nfs.SAVE, _cache_name(m, kit.Hashs(text)), kit.Dict(nfs.CONTENT, text))
text, arg = p, kit.Simple(p, len(text)) text, arg = p, kit.Simple(p, len(text))
} }
file, size := kit.Select("", arg, 0), kit.Int(kit.Select(kit.Format(len(text)), arg, 1)) file, size := kit.Select("", arg, 0), kit.Int(kit.Select(kit.Format(len(text)), arg, 1))
@ -57,21 +58,22 @@ func _cache_catch(m *ice.Message, path string) (file string, size string) {
return "", "0" return "", "0"
} }
func _cache_upload(m *ice.Message, r *http.Request) (mime, name, file, size string) { func _cache_upload(m *ice.Message, r *http.Request) (mime, name, file, size string) {
if b, h, e := r.FormFile(UPLOAD); !m.Warn(e, ice.ErrNotValid, UPLOAD) { if b, h, e := r.FormFile(UPLOAD); !m.WarnNotValid(e, UPLOAD) {
defer b.Close() defer b.Close()
if f, p, e := miss.CreateFile(_cache_name(m, kit.Hashs(b))); !m.Warn(e, ice.ErrNotValid, UPLOAD) { if f, p, e := miss.CreateFile(_cache_name(m, kit.Hashs(b))); !m.WarnNotValid(e, UPLOAD) {
defer f.Close() defer f.Close()
b.Seek(0, os.SEEK_SET) b.Seek(0, os.SEEK_SET)
if n, e := io.Copy(f, b); !m.Warn(e, ice.ErrNotValid, UPLOAD) { if n, e := io.Copy(f, b); !m.WarnNotValid(e, UPLOAD) {
m.Logs(nfs.SAVE, nfs.FILE, p, nfs.SIZE, kit.FmtSize(int64(n))) m.Logs(nfs.SAVE, nfs.FILE, p, nfs.SIZE, kit.FmtSize(int64(n)))
return h.Header.Get(ContentType), h.Filename, p, kit.Format(n) return h.Header.Get(html.ContentType), h.Filename, p, kit.Format(n)
} }
} }
} }
return "", "", "", "0" return "", "", "", "0"
} }
func _cache_download(m *ice.Message, r *http.Response, file string, cb ice.Any) string { func _cache_download(m *ice.Message, r *http.Response, file string, cb ice.Any) string {
if f, p, e := miss.CreateFile(file); !m.Warn(e, ice.ErrNotValid, DOWNLOAD) { m.Option(ice.MSG_USERROLE, aaa.TECH)
if f, p, e := miss.CreateFile(file); !m.WarnNotValid(e, DOWNLOAD) {
defer func() { defer func() {
if s, e := os.Stat(file); e == nil && s.Size() == 0 { if s, e := os.Stat(file); e == nil && s.Size() == 0 {
nfs.Remove(m, file) nfs.Remove(m, file)
@ -79,7 +81,7 @@ func _cache_download(m *ice.Message, r *http.Response, file string, cb ice.Any)
}() }()
defer f.Close() defer f.Close()
last, base := 0, 10 last, base := 0, 10
nfs.CopyStream(m, f, r.Body, base*ice.MOD_BUFS, kit.Int(kit.Select("100", r.Header.Get(ContentLength))), func(count, total, value int) { nfs.CopyStream(m, f, r.Body, base*ice.MOD_BUFS, kit.Int(kit.Select("100", r.Header.Get(html.ContentLength))), func(count, total, value int) {
if value/base == last { if value/base == last {
return return
} }
@ -103,6 +105,8 @@ const (
WRITE = "write" WRITE = "write"
UPLOAD = "upload" UPLOAD = "upload"
DOWNLOAD = "download" DOWNLOAD = "download"
PREVIEW = "preview"
PAGES = "pages"
IMAGE = "image" IMAGE = "image"
VIDEO = "video" VIDEO = "video"
@ -111,13 +115,10 @@ const CACHE = "cache"
func init() { func init() {
Index.MergeCommands(ice.Commands{ Index.MergeCommands(ice.Commands{
CACHE: {Name: "cache hash auto write catch upload", Help: "缓存池", Actions: ice.MergeActions(ice.Actions{ CACHE: {Name: "cache hash auto upload", Help: "缓存池", Actions: ice.MergeActions(ice.Actions{
ice.RENDER_DOWNLOAD: {Hand: func(m *ice.Message, arg ...string) { ice.RENDER_DOWNLOAD: {Hand: func(m *ice.Message, arg ...string) {
m.Echo(_share_link(m, kit.Select(arg[0], arg, 1), ice.POD, m.Option(ice.MSG_USERPOD), nfs.FILENAME, kit.Select("", arg[0], len(arg) > 1))) m.Echo(_share_link(m, kit.Select(arg[0], arg, 1), ice.POD, m.Option(ice.MSG_USERPOD), nfs.FILENAME, kit.Select("", arg[0], len(arg) > 1)))
}}, }},
WATCH: {Name: "watch hash* path*", Help: "导出", Hand: func(m *ice.Message, arg ...string) {
_cache_watch(m, m.Option(mdb.HASH), m.Option(nfs.PATH))
}},
WRITE: {Name: "write type name* text*", Help: "添加", Hand: func(m *ice.Message, arg ...string) { WRITE: {Name: "write type name* text*", Help: "添加", Hand: func(m *ice.Message, arg ...string) {
_cache_save(m, m.Option(mdb.TYPE), m.Option(mdb.NAME), m.Option(mdb.TEXT)) _cache_save(m, m.Option(mdb.TYPE), m.Option(mdb.NAME), m.Option(mdb.TEXT))
}}, }},
@ -125,16 +126,19 @@ func init() {
file, size := _cache_catch(m, m.Option(nfs.PATH)) file, size := _cache_catch(m, m.Option(nfs.PATH))
_cache_save(m, m.Option(mdb.TYPE), m.Option(nfs.PATH), "", file, size) _cache_save(m, m.Option(mdb.TYPE), m.Option(nfs.PATH), "", file, size)
}}, }},
WATCH: {Name: "watch hash* path*", Help: "导出", Hand: func(m *ice.Message, arg ...string) {
_cache_watch(m, m.Option(mdb.HASH), m.Option(nfs.PATH))
}},
UPLOAD: {Hand: func(m *ice.Message, arg ...string) { UPLOAD: {Hand: func(m *ice.Message, arg ...string) {
mime, name, file, size := _cache_upload(m, m.R) mime, name, file, size := _cache_upload(m, m.R)
_cache_save(m, mime, name, "", file, size) _cache_save(m, mime, name, "", file, size)
}}, }},
DOWNLOAD: {Name: "download type name*", Hand: func(m *ice.Message, arg ...string) { DOWNLOAD: {Name: "download type name*", Hand: func(m *ice.Message, arg ...string) {
if res, ok := m.Optionv(RESPONSE).(*http.Response); !m.Warn(!ok, ice.ErrNotValid, RESPONSE) { if res, ok := m.Optionv(RESPONSE).(*http.Response); !m.WarnNotValid(!ok, RESPONSE) {
p := path.Join(ice.VAR_TMP, kit.Hashs(mdb.UNIQ)) nfs.Temp(m, func(p string) {
defer os.Remove(p) file, size := _cache_catch(m, _cache_download(m, res, p, m.OptionCB("")))
file, size := _cache_catch(m, _cache_download(m, res, p, m.OptionCB(""))) _cache_save(m, m.Option(mdb.TYPE), m.Option(mdb.NAME), "", file, size)
_cache_save(m, m.Option(mdb.TYPE), m.Option(mdb.NAME), "", file, size) })
} }
}}, }},
nfs.PS: {Hand: func(m *ice.Message, arg ...string) { nfs.PS: {Hand: func(m *ice.Message, arg ...string) {
@ -150,13 +154,16 @@ func init() {
}, func() { m.RenderResult(msg.Append(mdb.TEXT)) }) }, func() { m.RenderResult(msg.Append(mdb.TEXT)) })
} }
}}, }},
}, mdb.HashAction(mdb.SHORT, mdb.TEXT, mdb.FIELD, "time,hash,size,type,name,text,file", ctx.ACTION, WATCH), ice.RenderAction(ice.RENDER_DOWNLOAD)), Hand: func(m *ice.Message, arg ...string) { }, mdb.HashAction(mdb.SHORT, mdb.TEXT, mdb.FIELD, "time,hash,size,type,name,text,file"), ice.RenderAction(ice.RENDER_DOWNLOAD)), Hand: func(m *ice.Message, arg ...string) {
if mdb.HashSelect(m, arg...); len(arg) == 0 || m.R != nil && m.R.Method == http.MethodGet { if mdb.HashSelect(m, arg...); len(arg) == 0 {
m.Option(ice.MSG_ACTION, "") return
}
if m.Length() == 0 {
return
} else if m.Append(nfs.FILE) == "" { } else if m.Append(nfs.FILE) == "" {
m.PushScript(mdb.TEXT, m.Append(mdb.TEXT)) m.PushScript(mdb.TEXT, m.Append(mdb.TEXT))
} else { } else {
PushDisplay(m, m.Append(mdb.TYPE), m.Append(mdb.NAME), MergeURL2(m, P(SHARE, CACHE, arg[0]))) PushDisplay(m, m.Append(mdb.TYPE), m.Append(mdb.NAME), m.MergeLink(P(SHARE, CACHE, arg[0])))
} }
}}, }},
}) })
@ -170,18 +177,35 @@ func init() {
action.Hand = ice.MergeHand(func(m *ice.Message, arg ...string) { action.Hand = ice.MergeHand(func(m *ice.Message, arg ...string) {
up := Upload(m) up := Upload(m)
m.Assert(len(up) > 1) m.Assert(len(up) > 1)
m.Cmd(CACHE, m.Option(ice.MSG_UPLOAD)).Table(func(value ice.Maps) { m.Options(value) }) msg := m.Cmd(CACHE, m.Option(ice.MSG_UPLOAD))
if m.Options(mdb.HASH, up[0], mdb.NAME, up[1]); watch { // if m.Cmd(CACHE, m.Option(ice.MSG_UPLOAD)).Table(func(value ice.Maps) { m.Options(value) }).Length() == 0 {
m.Cmdy(CACHE, WATCH, m.Option(mdb.HASH), path.Join(m.Option(nfs.PATH), up[1])) if msg.Length() == 0 {
SpideCache(m.Spawn(), m.MergeLink(SHARE_CACHE+up[0]))
}
// if m.Options(mdb.HASH, up[0], mdb.NAME, up[1]); watch {
if watch {
m.Cmdy(CACHE, WATCH, up[0], path.Join(msg.Append(nfs.PATH), up[1]))
} }
}, action.Hand) }, action.Hand)
} }
}) })
} }
func UploadSave(m *ice.Message, p string) string {
up := kit.Simple(m.Optionv(ice.MSG_UPLOAD))
kit.If(strings.HasSuffix(p, nfs.PS), func() { p = path.Join(p, up[1]) })
m.Cmd(CACHE, WATCH, up[0], p)
return p
}
func Upload(m *ice.Message) []string { func Upload(m *ice.Message) []string {
if up := kit.Simple(m.Optionv(ice.MSG_UPLOAD)); len(up) == 1 { if up := kit.Simple(m.Optionv(ice.MSG_UPLOAD)); len(up) == 1 {
if m.Cmdy(CACHE, UPLOAD).Optionv(ice.MSG_UPLOAD, kit.Simple(m.Append(mdb.HASH), m.Append(mdb.NAME), m.Append(nfs.SIZE))); m.Option(ice.MSG_USERPOD) != "" { msg := m.Cmd(CACHE, UPLOAD)
m.Cmd(SPACE, m.Option(ice.MSG_USERPOD), SPIDE, ice.DEV, SPIDE_CACHE, http.MethodGet, tcp.PublishLocalhost(m, MergeURL2(m, PP(SHARE, CACHE, m.Append(mdb.HASH))))) if m.Optionv(ice.MSG_UPLOAD, kit.Simple(msg.Append(mdb.HASH), msg.Append(mdb.NAME), msg.Append(nfs.SIZE))); m.Option(ice.MSG_USERPOD) != "" {
if nfs.Exists(m, nfs.USR_LOCAL_WORK+m.Option(ice.MSG_USERPOD)) {
m.Cmd(nfs.LINK, path.Join(nfs.USR_LOCAL_WORK+m.Option(ice.MSG_USERPOD), msg.Append(nfs.FILE)), msg.Append(nfs.FILE))
m.Cmd(SPACE, m.Option(ice.MSG_USERPOD), CACHE, mdb.CREATE, msg.AppendSimple(mdb.NAME, mdb.TEXT, nfs.FILE, nfs.SIZE))
} else {
m.Cmd(SPACE, m.Option(ice.MSG_USERPOD), SPIDE, ice.DEV, SPIDE_CACHE, http.MethodGet, tcp.PublishLocalhost(m, m.MergeLink(PP(SHARE, CACHE, msg.Append(mdb.HASH)))))
}
} }
return kit.Simple(m.Optionv(ice.MSG_UPLOAD)) return kit.Simple(m.Optionv(ice.MSG_UPLOAD))
} else { } else {
@ -228,5 +252,13 @@ func ExportCacheAction(field string) ice.Actions {
value[field] = kit.Join(kit.Simple(kit.For(kit.Split(kit.Format(value[field])), func(p string) string { return kit.Select(p, list[p]) }))) value[field] = kit.Join(kit.Simple(kit.For(kit.Split(kit.Format(value[field])), func(p string) string { return kit.Select(p, list[p]) })))
}) })
}}, }},
UPLOAD: {Hand: func(m *ice.Message, arg ...string) {
nfs.Temp(m, func(p string) {
msg := m.Cmd(CACHE, Upload(m)[0])
if os.Link(msg.Append(nfs.FILE), p); nfs.ImageResize(m, p, 390, 390) {
m.Echo(m.Cmd(CACHE, CATCH, p, msg.Append(mdb.TYPE)).Append(mdb.HASH))
}
})
}},
} }
} }

View File

@ -1,19 +1,114 @@
package web package web
import ( import (
"strings"
ice "shylinux.com/x/icebergs" ice "shylinux.com/x/icebergs"
"shylinux.com/x/icebergs/base/aaa"
"shylinux.com/x/icebergs/base/mdb" "shylinux.com/x/icebergs/base/mdb"
"shylinux.com/x/icebergs/base/web/html"
kit "shylinux.com/x/toolkits" kit "shylinux.com/x/toolkits"
) )
func _count_stat(m *ice.Message, arg ...string) map[string]int {
stat := map[string]int{}
m.Table(func(value ice.Maps) {
count := kit.Int(value[mdb.COUNT])
stat[mdb.TOTAL] += count
for _, agent := range []string{"美国", "电信", "联通", "移动", "阿里云", "腾讯云"} {
if strings.Contains(value[aaa.LOCATION], agent) {
stat[agent] += count
break
}
}
for _, agent := range []string{"GoModuleMirror", "Go-http-client", "git", "compatible"} {
if strings.Contains(value[mdb.TEXT], agent) {
stat[agent] += count
return
}
}
for _, agent := range html.AgentList {
if strings.Contains(value[mdb.TEXT], agent) {
stat[agent] += count
break
}
}
for _, agent := range html.SystemList {
if strings.Contains(value[mdb.TEXT], agent) {
stat[agent] += count
break
}
}
})
return stat
}
const COUNT = "count" const COUNT = "count"
func init() { func init() {
Index.MergeCommands(ice.Commands{ Index.MergeCommands(ice.Commands{
COUNT: &ice.Command{Help: "计数", Actions: ice.MergeActions(ice.Actions{ COUNT: &ice.Command{Name: "count hash auto group valid location", Help: "计数器", Meta: kit.Dict(
ice.CTX_TRANS, kit.Dict(html.INPUT, kit.Dict(aaa.LOCATION, "地理位置")),
), Actions: ice.MergeActions(ice.Actions{
mdb.CREATE: {Name: "create type name text", Hand: func(m *ice.Message, arg ...string) { mdb.CREATE: {Name: "create type name text", Hand: func(m *ice.Message, arg ...string) {
mdb.HashSelectUpdate(m, mdb.HashCreate(m), func(value ice.Map) { value[mdb.COUNT] = kit.Int(value[mdb.COUNT]) + 1 }) mdb.HashSelectUpdate(m, mdb.HashCreate(m), func(value ice.Map) { value[mdb.COUNT] = kit.Int(value[mdb.COUNT]) + 1 })
// m.Cmd("count", mdb.CREATE, OFFER, m.Option(FROM), kit.Dict(ice.LOG_DISABLE, ice.TRUE))
}}, }},
}, mdb.HashAction(mdb.LIMIT, 1000, mdb.LEAST, 500, mdb.SHORT, "type,name", mdb.FIELD, "time,hash,count,type,name,text", mdb.SORT, "type,name,text"))}, mdb.VALID: {Hand: func(m *ice.Message, arg ...string) {
mdb.HashSelect(m.Spawn(), arg...).Table(func(value ice.Maps) {
if !strings.HasPrefix(value[mdb.TEXT], html.Mozilla) {
return
} else if count := kit.Int(value[mdb.COUNT]); count < 1 {
return
} else {
m.Push("", value, kit.Split(mdb.Config(m, mdb.FIELD)))
}
})
m.StatusTimeCount(_count_stat(m))
}},
mdb.GROUP: {Hand: func(m *ice.Message, arg ...string) {
count := map[string]int{}
list := map[string]map[string]string{}
m.Cmd("", mdb.VALID).Table(func(value ice.Maps) {
count[value[aaa.LOCATION]] += kit.Int(value[mdb.COUNT])
list[value[aaa.LOCATION]] = value
})
stat := map[string]int{}
for _, v := range list {
func() {
for _, agent := range []string{"美国", "电信", "联通", "移动", "阿里云", "腾讯云", "北京市", "香港"} {
if strings.Contains(v[aaa.LOCATION], agent) {
stat[agent] += kit.Int(v[mdb.COUNT])
return
}
}
m.Push("", v, kit.Split(mdb.Config(m, mdb.FIELD)))
}()
}
m.StatusTimeCount(stat)
}},
aaa.LOCATION: {Hand: func(m *ice.Message, arg ...string) {
GoToast(mdb.HashSelects(m).Sort(mdb.COUNT, ice.INT_R), func(toast func(string, int, int)) []string {
m.Table(func(value ice.Maps, index, total int) {
if value[aaa.LOCATION] == "" {
location := kit.Format(kit.Value(SpideGet(m, "http://opendata.baidu.com/api.php?co=&resource_id=6006&oe=utf8", "query", value[mdb.NAME]), "data.0.location"))
mdb.HashModify(m, mdb.HASH, value[mdb.HASH], aaa.LOCATION, location)
toast(kit.Select(value[mdb.NAME], location), index, total)
m.Sleep300ms()
}
})
return nil
})
}},
}, mdb.HashAction(mdb.LIMIT, 1000, mdb.LEAST, 500, mdb.SHORT, "type,name", mdb.FIELD, "time,hash,count,location,type,name,text")), Hand: func(m *ice.Message, arg ...string) {
mdb.HashSelect(m, arg...).Sort(mdb.TIME, ice.STR_R).StatusTimeCount(_count_stat(m))
}},
}) })
} }
func Count(m *ice.Message, arg ...string) *ice.Message {
kit.If(len(arg) > 0 && arg[0] == "", func() { arg[0] = m.ShortKey() })
kit.If(len(arg) > 1 && arg[1] == "", func() { arg[1] = m.ActionKey() })
m.Cmd(COUNT, mdb.CREATE, arg, kit.Dict(ice.LOG_DISABLE, ice.TRUE))
return m
}

View File

@ -17,91 +17,173 @@ import (
"shylinux.com/x/icebergs/base/mdb" "shylinux.com/x/icebergs/base/mdb"
"shylinux.com/x/icebergs/base/nfs" "shylinux.com/x/icebergs/base/nfs"
"shylinux.com/x/icebergs/base/tcp" "shylinux.com/x/icebergs/base/tcp"
"shylinux.com/x/icebergs/base/web/html"
kit "shylinux.com/x/toolkits" kit "shylinux.com/x/toolkits"
) )
func _dream_list(m *ice.Message) *ice.Message { func _dream_list(m *ice.Message) *ice.Message {
stats := map[string]int{}
list := m.CmdMap(SPACE, mdb.NAME) list := m.CmdMap(SPACE, mdb.NAME)
mdb.HashSelect(m).Table(func(value ice.Maps) { mdb.HashSelects(m.Spawn()).Table(func(value ice.Maps, index int, head []string) {
if value[aaa.ACCESS] == aaa.PRIVATE && (m.Option(ice.FROM_SPACE) != "" || !aaa.IsTechOrRoot(m)) {
return
}
if space, ok := list[value[mdb.NAME]]; ok { if space, ok := list[value[mdb.NAME]]; ok {
msg := gdb.Event(m.Spawn(value, space), DREAM_TABLES).Copy(m.Spawn().PushButton(cli.STOP)) value[ice.MAIN] = space[ice.MAIN]
m.Push(nfs.VERSION, space[nfs.VERSION]) value[mdb.ICONS] = space[mdb.ICONS]
m.Push(mdb.TYPE, space[mdb.TYPE]) m.Push("", value, kit.Slice(head, 0, -1))
m.Push(cli.STATUS, cli.START) m.Push(mdb.TYPE, space[mdb.TYPE]).Push(cli.STATUS, cli.START)
m.Push(mdb.TEXT, msg.Append(mdb.TEXT)) m.Push(nfs.MODULE, space[nfs.MODULE]).Push(nfs.VERSION, space[nfs.VERSION])
m.PushButton(strings.Join(msg.Appendv(ctx.ACTION), "")) button := []ice.Any{PORTAL, DESKTOP, ADMIN, WORD}
stats[cli.START]++ text := space[nfs.MODULE]
} else { kit.If(m.Option(ice.DREAM_SIMPLE) != ice.TRUE && aaa.IsTechOrRoot(m), func() {
m.Push(nfs.VERSION, "") kit.If(m.IsDebug(), func() {
m.Push(mdb.TYPE, WORKER) button = append(button, VIMER, STATUS, COMPILE, cli.RUNTIME, XTERM)
m.Push(cli.STATUS, cli.STOP) text += "\n" + DreamStat(m, value[mdb.NAME])
m.Push(mdb.TEXT, "") })
if nfs.Exists(m, path.Join(ice.USR_LOCAL_WORK, value[mdb.NAME])) { button = append(button, "settings", cli.STOP)
m.PushButton(cli.START, nfs.TRASH) })
stats[cli.STOP]++ m.Push(mdb.TEXT, text)
m.PushButton(append(button, OPEN)...)
} else if aaa.IsTechOrRoot(m) {
m.Push("", value, kit.Slice(head, 0, -1))
m.Push(nfs.MODULE, "").Push(nfs.VERSION, "").Push(mdb.TEXT, "")
if m.Push(mdb.TYPE, WORKER); nfs.Exists(m, path.Join(ice.USR_LOCAL_WORK, value[mdb.NAME])) {
m.Push(cli.STATUS, cli.STOP).PushButton(cli.START, nfs.TRASH)
} else { } else {
m.PushButton(cli.START, mdb.REMOVE) m.Push(cli.STATUS, cli.BEGIN).PushButton(cli.START, mdb.REMOVE)
stats[ice.INIT]++
} }
} }
}) })
return m.Sort("status,type,name", ice.STR, ice.STR, ice.STR_R).StatusTimeCount(stats) m.RewriteAppend(func(value, key string, index int) string {
if key == mdb.TIME {
} if space, ok := list[m.Appendv(mdb.NAME)[index]]; ok {
func _dream_start(m *ice.Message, name string) { return space[mdb.TIME]
if m.Warn(name == "", ice.ErrNotValid, mdb.NAME) { }
return } else if key == mdb.ICONS {
} if kit.HasPrefix(value, HTTP, nfs.PS) {
defer m.ProcessOpen(m.MergePod(m.Option(mdb.NAME, name))) return value
p := path.Join(ice.USR_LOCAL_WORK, name) } else if nfs.ExistsFile(m, path.Join(ice.USR_LOCAL_WORK, m.Appendv(mdb.NAME)[index], value)) {
if pid := m.Cmdx(nfs.CAT, path.Join(p, ice.Info.PidPath), kit.Dict(ice.MSG_USERROLE, aaa.TECH)); pid != "" { return m.Spawn(kit.Dict(ice.MSG_USERPOD, m.Appendv(mdb.NAME)[index])).FileURI(value)
if nfs.Exists(m, "/proc/"+pid) { } else if nfs.ExistsFile(m, value) {
m.Info("already exists %v", pid) return m.FileURI(value)
return }
} }
for i := 0; i < 3; i++ { return value
if msg := m.Cmd(SPACE, name); msg.Length() > 0 { })
m.Info("already exists %v", name) return m
}
func _dream_list_more(m *ice.Message) *ice.Message {
field := kit.Split(mdb.Config(m, mdb.FIELD) + ",type,status,module,version,text")
m.Cmds(SPACE).Table(func(value ice.Maps) {
value[nfs.REPOS] = "https://" + value[nfs.MODULE]
value[aaa.ACCESS] = kit.Select("", value[aaa.USERROLE], value[aaa.USERROLE] != aaa.VOID)
value[mdb.STATUS] = cli.START
button := []ice.Any{PORTAL, DESKTOP, ADMIN, WORD}
kit.If(m.IsDebug(), func() { button = append(button, VIMER, STATUS, COMPILE, cli.RUNTIME, XTERM) })
switch value[mdb.TYPE] {
case ORIGIN:
if m.IsCliUA() {
return return
} }
m.Sleep300ms() value[mdb.TEXT] = kit.JoinLine(value[nfs.MODULE], value[mdb.TEXT])
button = append(button, GETTOKEN, OPEN)
kit.If(value[aaa.ACCESS] == "", func() { button = []ice.Any{PORTAL, OPEN} })
case SERVER:
if !m.IsCliUA() {
value[mdb.TEXT] = kit.JoinLine(value[nfs.MODULE], value[mdb.TEXT])
} else if !strings.HasPrefix(value[mdb.TEXT], ice.HTTP) {
return
}
button = append(button, SETTOKEN, OPEN)
case aaa.LOGIN:
if m.IsCliUA() {
return
}
value[mdb.TEXT] = kit.JoinWord(value[AGENT], value[cli.SYSTEM], value[aaa.IP], kit.Format(PublicIP(m, value[aaa.IP])))
button = []ice.Any{GRANT}
default:
return
} }
m.Push("", value, field)
m.PushButton(button...)
})
return m
}
func _dream_start(m *ice.Message, name string) {
if m.WarnNotValid(name == "", mdb.NAME) {
return
}
if !m.IsCliUA() {
defer m.ProcessRefresh()
}
defer mdb.Lock(m, m.PrefixKey(), cli.START, name)()
p := _dream_check(m, name)
if p == "" {
return
}
if !nfs.Exists(m, p) {
gdb.Event(m, DREAM_CREATE, m.OptionSimple(mdb.NAME))
} }
defer ToastProcess(m)()
defer m.Sleep3s()
m.Options(cli.CMD_DIR, kit.Path(p), cli.CMD_ENV, kit.EnvList(kit.Simple(
cli.CTX_OPS, Domain(tcp.LOCALHOST, m.Cmdv(SERVE, tcp.PORT)), cli.CTX_LOG, ice.VAR_LOG_BOOT_LOG, cli.CTX_PID, ice.VAR_LOG_ICE_PID,
cli.PATH, cli.BinPath(p, ""), cli.USER, ice.Info.Username,
)...), cli.CMD_OUTPUT, path.Join(p, ice.VAR_LOG_BOOT_LOG), mdb.CACHE_CLEAR_ONEXIT, ice.TRUE)
defer m.Options(cli.CMD_DIR, "", cli.CMD_ENV, "", cli.CMD_OUTPUT, "") defer m.Options(cli.CMD_DIR, "", cli.CMD_ENV, "", cli.CMD_OUTPUT, "")
gdb.Event(m, DREAM_CREATE, m.OptionSimple(mdb.NAME, mdb.TYPE)) m.Options(cli.CMD_DIR, kit.Path(p), cli.CMD_ENV, kit.EnvList(kit.Simple(m.OptionSimple(ice.TCP_DOMAIN),
cli.CTX_OPS, HostPort(m, tcp.LOCALHOST, m.Cmdv(SERVE, tcp.PORT)), cli.CTX_LOG, ice.VAR_LOG_BOOT_LOG,
cli.CTX_ROOT, kit.Path(""), cli.PATH, cli.BinPath(p, ""), cli.USER, ice.Info.Username,
)...), cli.CMD_OUTPUT, path.Join(p, ice.VAR_LOG_BOOT_LOG), mdb.CACHE_CLEAR_ONEXIT, ice.TRUE)
kit.If(m.Option(nfs.BINARY) == "" && !cli.SystemFindGo(m), func(p string) { m.Option(nfs.BINARY, S(name)) })
kit.If(m.Option(nfs.BINARY), func(p string) { _dream_binary(m, p) }) kit.If(m.Option(nfs.BINARY), func(p string) { _dream_binary(m, p) })
kit.If(m.Option(nfs.TEMPLATE), func(p string) { _dream_template(m, p) }) kit.If(m.Option(nfs.TEMPLATE), func(p string) { _dream_template(m, p) })
m.Cmd(cli.DAEMON, kit.Select(kit.Path(os.Args[0]), cli.SystemFind(m, ice.ICE_BIN, nfs.PWD+path.Join(p, ice.BIN), nfs.PWD+ice.BIN)), bin := kit.Select(kit.Path(os.Args[0]), cli.SystemFind(m, ice.ICE_BIN, nfs.PWD+path.Join(p, ice.BIN), nfs.PWD+ice.BIN))
SPACE, tcp.DIAL, ice.DEV, ice.OPS, mdb.TYPE, WORKER, m.OptionSimple(mdb.NAME), cli.DAEMON, ice.OPS) if cli.IsSuccess(m.Cmd(cli.DAEMON, bin, SPACE, tcp.DIAL, ice.DEV, ice.OPS, cli.DAEMON, ice.OPS)) {
gdb.WaitEvent(m, DREAM_OPEN, func(m *ice.Message, arg ...string) bool { return m.Option(mdb.NAME) == name })
m.Sleep300ms()
}
}
func _dream_check(m *ice.Message, name string) string {
p := path.Join(ice.USR_LOCAL_WORK, name)
msg := m.Spawn(kit.Dict(ice.MSG_USERROLE, aaa.ROOT))
if pp := path.Join(p, ice.VAR_LOG_ICE_PID); nfs.Exists(m, pp) {
for i := 0; i < 5; i++ {
pid := msg.Cmdx(nfs.CAT, pp)
if pid == "" {
return p
}
m.Sleep("1s")
if m.Cmd(SPACE, name).Length() > 0 {
m.Info("already exists %v", name)
return ""
}
if runtime.GOOS == cli.LINUX && !nfs.Exists(m, "/proc/"+pid) {
return p
}
if nfs.Exists(m, "/proc/"+pid) && runtime.GOOS == cli.LINUX {
if !kit.HasPrefix(msg.Cmdx(nfs.CAT, "/proc/"+pid+"/cmdline"), kit.Path(ice.BIN_ICE_BIN), kit.Path(p, ice.BIN_ICE_BIN)) {
return p
} else {
return ""
}
}
if gdb.SignalProcess(m, pid) {
m.Info("already exists %v", pid)
return ""
}
}
}
return p
} }
func _dream_binary(m *ice.Message, p string) { func _dream_binary(m *ice.Message, p string) {
if bin := path.Join(m.Option(cli.CMD_DIR), ice.BIN_ICE_BIN); nfs.Exists(m, bin) { if bin := path.Join(m.Option(cli.CMD_DIR), ice.BIN_ICE_BIN); nfs.Exists(m, bin) {
return return
} else if kit.IsUrl(p) { } else if kit.IsUrl(p) || strings.HasPrefix(p, S()) {
GoToast(m, DOWNLOAD, func(toast func(string, int, int)) (list []string) { // m.Cmd(DREAM, DOWNLOAD, bin, kit.MergeURL2(p, kit.Format("/publish/ice.%s.%s", runtime.GOOS, runtime.GOARCH), ice.POD, m.Option(mdb.NAME)))
begin := time.Now() m.Cmd(DREAM, DOWNLOAD, bin, kit.MergeURL(p, cli.GOOS, runtime.GOOS, cli.GOARCH, runtime.GOARCH))
SpideSave(m, bin, kit.MergeURL(p, cli.GOOS, runtime.GOOS, cli.GOARCH, runtime.GOARCH), func(count, total, value int) {
cost := time.Now().Sub(begin)
toast(kit.FormatShow(nfs.FROM, begin.Format("15:04:05"), cli.COST, kit.FmtDuration(cost), cli.REST, kit.FmtDuration(cost*time.Duration(101)/time.Duration(value+1)-cost)), count, total)
})
return nil
})
os.Chmod(bin, ice.MOD_DIR)
} else { } else {
m.Cmd(nfs.LINK, bin, kit.Path(p)) m.Cmd(nfs.LINK, bin, kit.Path(p))
} }
} }
func _dream_template(m *ice.Message, p string) { func _dream_template(m *ice.Message, p string) {
kit.For([]string{ kit.For([]string{
ice.README_MD, ice.MAKEFILE, ice.LICENSE, ice.GO_MOD, ice.GO_SUM, ice.LICENSE, ice.README_MD, ice.MAKEFILE, ice.GO_MOD, ice.GO_SUM,
ice.SRC_MAIN_SHY, ice.SRC_MAIN_SH, ice.SRC_MAIN_GO, ice.SRC_MAIN_JS, ice.SRC_MAIN_SH, ice.SRC_MAIN_SHY, ice.SRC_MAIN_GO, ice.SRC_MAIN_JS,
ice.ETC_MISS_SH, ice.ETC_INIT_SHY, ice.ETC_EXIT_SHY, ice.ETC_MISS_SH, ice.ETC_INIT_SHY, ice.ETC_EXIT_SHY,
}, func(file string) { }, func(file string) {
if nfs.Exists(m, kit.Path(m.Option(cli.CMD_DIR), file)) { if nfs.Exists(m, kit.Path(m.Option(cli.CMD_DIR), file)) {
@ -117,193 +199,403 @@ func _dream_template(m *ice.Message, p string) {
} }
const ( const (
ALWAYS = "always"
STARTALL = "startall"
STOPALL = "stopall"
FOR_EACH = "forEach"
FOR_FLOW = "forFlow"
GETTOKEN = "gettoken"
SETTOKEN = "settoken"
DREAM_INPUTS = "dream.inputs"
DREAM_CREATE = "dream.create" DREAM_CREATE = "dream.create"
DREAM_REMOVE = "dream.remove" DREAM_REMOVE = "dream.remove"
DREAM_TRASH = "dream.trash"
DREAM_START = "dream.start" DREAM_START = "dream.start"
DREAM_STOP = "dream.stop" DREAM_STOP = "dream.stop"
DREAM_OPEN = "dream.open" DREAM_OPEN = "dream.open"
DREAM_CLOSE = "dream.close" DREAM_CLOSE = "dream.close"
DREAM_TRASH = "dream.trash"
DREAM_INPUTS = "dream.inputs"
DREAM_TABLES = "dream.tables" DREAM_TABLES = "dream.tables"
DREAM_ACTION = "dream.action" DREAM_ACTION = "dream.action"
OPS_DREAM_CREATE = "ops.dream.create"
OPS_DREAM_REMOVE = "ops.dream.remove"
) )
const DREAM = "dream" const DREAM = "dream"
func init() { func init() {
Index.MergeCommands(ice.Commands{ Index.MergeCommands(ice.Commands{
DREAM: {Name: "dream name@key auto create repos startall stopall publish cmd cat", Help: "梦想家", Icon: "Launchpad.png", Actions: ice.MergeActions(ice.Actions{ DREAM: {Name: "dream refresh", Help: "梦想家", Icon: "Launchpad.png", Role: aaa.VOID, Meta: kit.Dict(
ctx.CONFIG: {Hand: func(m *ice.Message, arg ...string) { ice.CTX_TRANS, kit.Dict(html.INPUT, kit.Dict(WORKER, "空间", SERVER, "门户", ORIGIN, "主机")),
for _, cmd := range kit.Reverse(arg) { ), Actions: ice.MergeActions(ice.Actions{
m.Cmd(gdb.EVENT, gdb.LISTEN, gdb.EVENT, DREAM_TABLES, ice.CMD, cmd) ice.AFTER_INIT: {Hand: func(m *ice.Message, arg ...string) {
m.Cmd(gdb.EVENT, gdb.LISTEN, gdb.EVENT, DREAM_ACTION, ice.CMD, cmd) AddPortalProduct(m, "云空间", `
} 比虚拟机和容器更加轻量每个空间都是一个完整的系统拥有各种软件与独立的环境
空间内所有的软件配置数据以源码库形式保存每个空间都可以随时启动停止上传下载分享
每个空间都自带软件开发工具也可以随时编程添加新的功能
`, 200.0)
}}, }},
mdb.SEARCH: {Hand: func(m *ice.Message, arg ...string) { mdb.SEARCH: {Hand: func(m *ice.Message, arg ...string) {
if mdb.IsSearchPreview(m, arg) { if mdb.IsSearchPreview(m, arg) {
m.Cmds("", func(value ice.Maps) { m.PushSearch(mdb.TEXT, m.MergePod(value[mdb.NAME]), value) }) mdb.HashSelects(m.Spawn()).Table(func(value ice.Maps) { m.PushSearch(mdb.TYPE, WORKER, mdb.TEXT, m.MergePod(value[mdb.NAME]), value) })
} }
}}, }},
mdb.INPUTS: {Hand: func(m *ice.Message, arg ...string) { mdb.INPUTS: {Hand: func(m *ice.Message, arg ...string) {
switch m.Option(ctx.ACTION) {
case mdb.CREATE:
switch arg[0] {
case mdb.NAME, nfs.TEMPLATE:
_dream_list(m).Cut("name,status,time")
return
}
case "startall":
DreamEach(m, "", cli.STOP, func(name string) { m.Push(arg[0], name) })
return
case ice.MAIN:
m.Cmdy(SPACE, m.Option(mdb.NAME), SPACE, mdb.INPUTS, arg)
return
}
switch arg[0] { switch arg[0] {
case mdb.NAME: case mdb.NAME:
DreamEach(m, "", cli.START, func(name string) { m.Push(arg[0], name) }) DreamEach(m, "", kit.Select(cli.START, cli.STOP, m.Option(ctx.ACTION) == STARTALL), func(name string) { m.Push(arg[0], name) })
case tcp.NODENAME:
m.Cmdy(SPACE, m.Option(mdb.NAME), SPACE, ice.INFO).CutTo(mdb.NAME, arg[0])
case aaa.USERNAME:
if aaa.IsTechOrRoot(m) && m.Option(ctx.ACTION) == GRANT {
m.Cmdy(aaa.USER).Cut(aaa.USERNAME, aaa.USERNICK).Option(ice.TABLE_CHECKBOX, ice.FALSE)
} else {
m.Push(arg[0], m.Option(tcp.NODENAME))
m.Push(arg[0], m.Option(ice.MSG_USERNAME))
}
case nfs.REPOS:
case nfs.BINARY: case nfs.BINARY:
m.Cmdy(nfs.DIR, ice.BIN, "path,size,time", kit.Dict(nfs.DIR_TYPE, nfs.TYPE_BIN))
m.Cmd(nfs.DIR, ice.USR_LOCAL_WORK, kit.Dict(nfs.DIR_TYPE, nfs.TYPE_BOTH), func(value ice.Maps) {
m.Cmdy(nfs.DIR, path.Join(value[nfs.PATH], ice.BIN), "path,size,time", kit.Dict(nfs.DIR_TYPE, nfs.TYPE_BIN))
})
m.RenameAppend(nfs.PATH, arg[0])
mdb.HashInputs(m, arg)
case ice.CMD:
m.Cmdy(ctx.COMMAND)
case nfs.FILE:
m.Options(nfs.DIR_TYPE, nfs.TYPE_CAT, ice.MSG_FIELDS, nfs.PATH)
m.Cmdy(nfs.DIR, nfs.SRC).Cmdy(nfs.DIR, nfs.ETC).Cmdy(nfs.DIR, "")
default: default:
gdb.Event(m, DREAM_INPUTS, arg) gdb.Event(m, DREAM_INPUTS, arg)
} }
}}, }},
mdb.CREATE: {Name: "create name*=hi icon@icon repos binary template", Hand: func(m *ice.Message, arg ...string) { nfs.SCAN: {Hand: func(m *ice.Message, arg ...string) {
list := m.CmdMap(CODE_GIT_REPOS, nfs.REPOS)
GoToastTable(m.Cmd(nfs.DIR, nfs.USR_LOCAL_WORK, mdb.NAME), mdb.NAME, func(value ice.Maps) {
if repos, ok := list[value[mdb.NAME]]; ok {
m.Cmd("", mdb.CREATE, value[mdb.NAME], repos[ORIGIN])
}
})
}},
mdb.CREATE: {Name: "create name*=hi repos binary", Hand: func(m *ice.Message, arg ...string) {
kit.If(!strings.Contains(m.Option(mdb.NAME), "-") || !strings.HasPrefix(m.Option(mdb.NAME), "20"), func() { m.Option(mdb.NAME, m.Time("20060102-")+m.Option(mdb.NAME)) }) kit.If(!strings.Contains(m.Option(mdb.NAME), "-") || !strings.HasPrefix(m.Option(mdb.NAME), "20"), func() { m.Option(mdb.NAME, m.Time("20060102-")+m.Option(mdb.NAME)) })
m.OptionDefault(mdb.ICON, nfs.USR_ICONS_ICEBERGS) m.Option(nfs.REPOS, kit.Select("", kit.Split(m.Option(nfs.REPOS)), -1))
kit.If(mdb.Config(m, nfs.REPOS), func(p string) { m.OptionDefault(nfs.REPOS, p+m.Option(mdb.NAME)) }) if mdb.HashCreate(m); ice.Info.Important == true {
kit.If(mdb.Config(m, nfs.BINARY), func(p string) { m.OptionDefault(nfs.BINARY, p+m.Option(mdb.NAME)) })
m.Option(nfs.REPOS, kit.Select("", kit.Slice(kit.Split(m.Option(nfs.REPOS)), -1), 0))
if mdb.HashCreate(m); !m.IsCliUA() {
_dream_start(m, m.Option(mdb.NAME)) _dream_start(m, m.Option(mdb.NAME))
SpaceEvent(m, OPS_DREAM_CREATE, m.Option(mdb.NAME), m.OptionSimple(mdb.NAME, nfs.REPOS, nfs.BINARY)...)
} }
}}, }},
nfs.REPOS: {Help: "仓库", Hand: func(m *ice.Message, arg ...string) { mdb.REMOVE: {Hand: func(m *ice.Message, arg ...string) {
m.ProcessOpen(m.MergePodCmd("", CODE_GIT_SEARCH, nfs.REPOS, nfs.REPOS)) gdb.Event(m, DREAM_REMOVE, m.OptionSimple(mdb.NAME))
mdb.HashRemove(m)
}}, }},
"startall": {Name: "startall name", Help: "启动", Hand: func(m *ice.Message, arg ...string) { STARTALL: {Name: "startall name", Help: "启动", Icon: "bi bi-play-circle", Hand: func(m *ice.Message, arg ...string) {
DreamEach(m, m.Option(mdb.NAME), cli.STOP, func(name string) { DreamEach(m, m.Option(mdb.NAME), cli.STOP, func(name string) {
m.Cmd("", cli.START, ice.Maps{mdb.NAME: name, ice.MSG_DAEMON: ""}) m.Cmd("", cli.START, ice.Maps{mdb.NAME: name, ice.MSG_DAEMON: ""})
}) })
}}, }},
"stopall": {Name: "stopall name", Help: "停止", Hand: func(m *ice.Message, arg ...string) { STOPALL: {Name: "stopall name", Help: "停止", Icon: "bi bi-stop-circle", Hand: func(m *ice.Message, arg ...string) {
DreamEach(m, m.Option(mdb.NAME), "", func(name string) { DreamEach(m, m.Option(mdb.NAME), cli.START, func(name string) {
m.Cmd("", cli.STOP, ice.Maps{mdb.NAME: name, ice.MSG_DAEMON: ""}) m.Cmd("", cli.STOP, ice.Maps{mdb.NAME: name, ice.MSG_DAEMON: ""})
}) })
}}, }},
"publish": {Name: "publish name", Help: "发布", Hand: func(m *ice.Message, arg ...string) { cli.BUILD: {Name: "build name", Hand: func(m *ice.Message, arg ...string) {
compile := cli.SystemFindGo(m)
m.Option(ice.MSG_TITLE, kit.Keys(m.Option(ice.MSG_USERPOD0), m.Option(ice.MSG_USERPOD), m.CommandKey(), m.ActionKey()))
m.Cmd("", FOR_FLOW, m.Option(mdb.NAME), kit.JoinWord(cli.SH, ice.ETC_MISS_SH), func(p string) bool {
if compile && nfs.Exists(m, path.Join(p, ice.SRC_MAIN_GO)) {
return false
} else {
m.Cmd(SPACE, path.Base(p), cli.RUNTIME, UPGRADE)
return true
}
}).Sleep3s()
m.ProcessHold()
}},
PUBLISH: {Name: "publish name", Hand: func(m *ice.Message, arg ...string) {
m.Option(ice.MSG_TITLE, kit.Keys(m.Option(ice.MSG_USERPOD0), m.Option(ice.MSG_USERPOD), m.CommandKey(), m.ActionKey()))
list := []string{cli.LINUX, cli.DARWIN, cli.WINDOWS}
msg := m.Spawn(ice.Maps{ice.MSG_DAEMON: ""})
func() {
if m.Option(mdb.NAME) != "" {
return
}
defer ToastProcess(m, PUBLISH, ice.Info.Pathname)()
m.Cmd(AUTOGEN, BINPACK)
kit.For(list, func(goos string) {
list := []string{cli.AMD64}
kit.If(goos == cli.DARWIN, func() { list = append(list, cli.ARM64) })
kit.For(list, func(arch string) {
PushNoticeRich(m, mdb.NAME, ice.Info.NodeName, msg.Cmd(COMPILE, goos, arch).AppendSimple())
})
})
}()
DreamEach(m, m.Option(mdb.NAME), "", func(name string) { DreamEach(m, m.Option(mdb.NAME), "", func(name string) {
m.Push(mdb.NAME, name).Push(mdb.TEXT, m.Cmdx(SPACE, name, "compile", cli.LINUX)) m.Cmd(SPACE, name, AUTOGEN, BINPACK)
m.Push(mdb.NAME, name).Push(mdb.TEXT, m.Cmdx(SPACE, name, "compile", cli.DARWIN)) kit.For(list, func(goos string) {
m.Push(mdb.NAME, name).Push(mdb.TEXT, m.Cmdx(SPACE, name, "compile", cli.WINDOWS)) list := []string{cli.AMD64}
kit.If(goos == cli.DARWIN, func() { list = append(list, cli.ARM64) })
kit.For(list, func(arch string) {
PushNoticeRich(m.Options(ice.MSG_COUNT, "0", ice.LOG_DISABLE, ice.TRUE), mdb.NAME, name, msg.Cmd(SPACE, name, COMPILE, goos, arch, kit.Dict(ice.MSG_USERPOD, name)).AppendSimple())
})
})
})
m.ProcessHold()
}},
FOR_FLOW: {Name: "forFlow name cmd*='sh etc/miss.sh'", Help: "流程", Icon: "bi bi-terminal", Hand: func(m *ice.Message, arg ...string) {
m.Options(ctx.DISPLAY, html.PLUGIN_XTERM, cli.CMD_OUTPUT, nfs.NewWriteCloser(func(buf []byte) (int, error) {
PushNoticeGrow(m.Options(ice.MSG_COUNT, "0", ice.LOG_DEBUG, ice.FALSE, ice.LOG_DISABLE, ice.TRUE), strings.ReplaceAll(string(buf), lex.NL, "\r\n"))
return len(buf), nil
}, nil))
msg := m.Spawn(ice.Maps{ice.MSG_DEBUG: ice.FALSE})
DreamEach(m, m.Option(mdb.NAME), "", func(name string) {
p := path.Join(ice.USR_LOCAL_WORK, name)
if cb, ok := m.OptionCB("").(func(string) bool); ok && cb(p) {
return
}
defer PushNoticeGrow(msg, "\r\n\r\n")
PushNoticeGrow(msg, kit.Format("\033[33m[%s]%s$\033[0m %s\r\n", time.Now().Format(ice.MOD_TIME_ONLY), name, m.Option(ice.CMD)))
m.Cmd(cli.SYSTEM, kit.Split(m.Option(ice.CMD)), kit.Dict(cli.CMD_DIR, p)).Sleep300ms()
}) })
}}, }},
ice.CMD: {Name: "cmd name cmd*", Help: "命令", Hand: func(m *ice.Message, arg ...string) {
DreamEach(m, m.Option(mdb.NAME), "", func(name string) {
m.Push(mdb.NAME, name).Push(mdb.TEXT, m.Cmdx(SPACE, name, kit.Split(m.Option(ice.CMD))))
}).StatusTimeCount(ice.CMD, m.Option(ice.CMD))
}},
nfs.CAT: {Name: "cat name file*", Help: "文件", Hand: func(m *ice.Message, arg ...string) {
DreamEach(m, m.Option(mdb.NAME), "", func(name string) {
m.Push(mdb.NAME, name).Push(mdb.TEXT, m.Cmdx(SPACE, name, nfs.CAT, m.Option(nfs.FILE)))
}).StatusTimeCount(nfs.FILE, m.Option(nfs.FILE))
}},
cli.START: {Hand: func(m *ice.Message, arg ...string) { cli.START: {Hand: func(m *ice.Message, arg ...string) {
gdb.Event(m, DREAM_START, arg)
_dream_start(m, m.Option(mdb.NAME)) _dream_start(m, m.Option(mdb.NAME))
gdb.Event(m, DREAM_START, arg)
}}, }},
cli.STOP: {Hand: func(m *ice.Message, arg ...string) { cli.STOP: {Hand: func(m *ice.Message, arg ...string) {
defer ToastProcess(m)()
gdb.Event(m, DREAM_STOP, arg) gdb.Event(m, DREAM_STOP, arg)
m.Cmd(SPACE, mdb.MODIFY, m.OptionSimple(mdb.NAME), mdb.STATUS, cli.STOP) m.Cmd(SPACE, mdb.MODIFY, m.OptionSimple(mdb.NAME), mdb.STATUS, cli.STOP)
m.Cmd(SPACE, m.Option(mdb.NAME), ice.EXIT) m.Cmd(SPACE, m.Option(mdb.NAME), ice.EXIT).Sleep3s()
m.Sleep3s()
}}, }},
nfs.TRASH: {Hand: func(m *ice.Message, arg ...string) { nfs.TRASH: {Hand: func(m *ice.Message, arg ...string) {
gdb.Event(m, DREAM_TRASH, arg) gdb.Event(m, DREAM_TRASH, arg)
nfs.Trash(m, path.Join(ice.USR_LOCAL_WORK, m.Option(mdb.NAME))) nfs.Trash(m, path.Join(ice.USR_LOCAL_WORK, m.Option(mdb.NAME)))
}}, }},
OPEN: {Hand: func(m *ice.Message, arg ...string) { m.ProcessOpen(m.MergePod(m.Option(mdb.NAME))) }}, cli.RUNTIME: {Hand: func(m *ice.Message, arg ...string) {
MAIN: {Name: "main index", Help: "首页", Hand: func(m *ice.Message, arg ...string) { ProcessPodCmd(m, m.Option(mdb.NAME), "", nil, arg...)
m.Cmdy(SPACE, m.Option(mdb.NAME), SPACE, ice.MAIN, m.Option(ctx.INDEX))
}}, }},
DREAM_CLOSE: {Hand: func(m *ice.Message, arg ...string) { "settings": {Name: "settings restart=manual,always access=public,private", Help: "设置", Style: html.DANGER, Hand: func(m *ice.Message, arg ...string) {
if m.Option(cli.DAEMON) == ice.OPS && m.Cmdv(SPACE, m.Option(mdb.NAME), mdb.STATUS) != cli.STOP { kit.If(m.Option(cli.RESTART) == "manual", func() { m.Option(cli.RESTART, "") })
m.Go(func() { m.Sleep300ms(DREAM, cli.START, m.OptionSimple(mdb.NAME)) }) kit.If(m.Option(aaa.ACCESS) == aaa.PUBLIC, func() { m.Option(aaa.ACCESS, "") })
mdb.HashModify(m, m.OptionSimple(mdb.NAME, cli.RESTART, aaa.ACCESS))
}},
SETTOKEN: {Name: "settoken nodename* username*", Help: "令牌", Style: html.DANGER, Hand: func(m *ice.Message, arg ...string) {
token := m.Cmdx(TOKEN, mdb.CREATE, mdb.TYPE, SERVER, mdb.NAME, m.Option(aaa.USERNAME), mdb.TEXT, m.Option(tcp.NODENAME))
m.Cmd(SPACE, m.Option(mdb.NAME), SPIDE, DEV_CREATE_TOKEN, ice.Maps{TOKEN: token})
}},
GETTOKEN: {Help: "令牌", Style: html.DANGER, Hand: func(m *ice.Message, arg ...string) {
m.Options(m.Cmd(SPIDE, m.Option(mdb.NAME)).AppendSimple()).Cmdy(SPIDE, mdb.DEV_REQUEST)
}},
GRANT: {Name: "grant username", Role: aaa.VOID, Hand: func(m *ice.Message, arg ...string) {
if aaa.IsTechOrRoot(m) && m.Option(aaa.USERNAME) != "" {
m.Option(ice.MSG_USERNAME, m.Option(aaa.USERNAME))
}
m.Cmd(CHAT_GRANT, aaa.CONFIRM, kit.Dict(SPACE, m.Option(mdb.NAME)))
}},
OPEN: {Style: html.NOTICE, Role: aaa.VOID, Hand: func(m *ice.Message, arg ...string) {
if strings.HasSuffix(m.Option(ice.MAIN), ".portal") || kit.HasPrefixList(arg, ctx.RUN) {
if !kit.HasPrefixList(arg, ctx.RUN) {
defer m.Push(TITLE, m.Option(mdb.NAME))
defer m.Push("_icon", m.Option(mdb.ICON))
defer m.Push("_style", "portal")
defer m.Push("_height", "844")
defer m.Push("_width", "390")
}
ctx.ProcessFloat(m, CHAT_IFRAME, S(m.Option(mdb.NAME)), arg...)
} else if m.Option(mdb.TYPE) == ORIGIN {
m.ProcessOpen(SpideOrigin(m, m.Option(mdb.NAME)))
} else if p := ProxyDomain(m, m.Option(mdb.NAME)); p != "" {
m.ProcessOpen(p)
} else {
m.ProcessOpen(S(kit.Keys(m.Option(ice.MSG_USERPOD), m.Option(mdb.NAME))))
} }
}}, }},
DREAM_TABLES: {Hand: func(m *ice.Message, arg ...string) { DREAM_OPEN: {Hand: func(m *ice.Message, arg ...string) {}},
kit.Switch(m.Option(mdb.TYPE), []string{WORKER, SERVER}, func() { m.PushButton(OPEN, ice.MAIN) }) DREAM_CLOSE: {Hand: func(m *ice.Message, arg ...string) {
}}, kit.For(arg, func(k, v string) {
}, aaa.RoleAction(), DreamAction(), mdb.ImportantHashAction(ctx.TOOLS, "web.space,web.route,web.code.git.search", mdb.SHORT, mdb.NAME, mdb.FIELD, "time,name,icon,repos,binary,template")), Hand: func(m *ice.Message, arg ...string) { if k == cli.DAEMON && v == ice.OPS && m.Cmdv(SPACE, m.Option(mdb.NAME), mdb.STATUS) != cli.STOP {
if ice.Info.NodeType == WORKER { m.GoSleep300ms(func() { m.Cmd(DREAM, cli.START, m.OptionSimple(mdb.NAME)) })
return
}
if len(arg) == 0 {
_dream_list(m).RewriteAppend(func(value, key string, index int) string {
if key == mdb.ICON {
return kit.MergeURL(ctx.FileURI(value), ice.POD, m.Appendv(mdb.NAME)[index])
} }
return value })
}).Option(ice.MSG_ACTION, "") }},
DREAM_TABLES: {Hand: func(m *ice.Message, arg ...string) {
button := []ice.Any{}
if aaa.IsTechOrRoot(m) {
switch m.Option(mdb.TYPE) {
case ORIGIN:
button = append(button, DREAM, GETTOKEN)
case SERVER:
button = append(button, DREAM, SETTOKEN)
case WORKER:
button = append(button, "settings")
}
}
m.PushButton(append(button, OPEN)...)
}},
SERVE_START: {Hand: func(m *ice.Message, arg ...string) {
for _, cmd := range kit.Reverse(kit.Split(mdb.Config(m, html.BUTTON))) {
m.Cmd(gdb.EVENT, gdb.LISTEN, gdb.EVENT, DREAM_TABLES, ice.CMD, cmd)
m.Cmd(gdb.EVENT, gdb.LISTEN, gdb.EVENT, DREAM_ACTION, ice.CMD, cmd)
aaa.White(m, kit.Keys(m.ShortKey(), ctx.ACTION, cmd))
}
mdb.HashSelects(m.Spawn()).SortStrR(mdb.NAME).Table(func(value ice.Maps) {
if value[cli.RESTART] == ALWAYS && nfs.Exists(m, path.Join(ice.USR_LOCAL_WORK+value[mdb.NAME])) {
m.Cmd(DREAM, cli.START, kit.Dict(mdb.NAME, value[mdb.NAME]))
}
})
}},
STATS_TABLES: {Hand: func(m *ice.Message, arg ...string) {
if msg := _dream_list(m.Spawn()); msg.Length() > 0 {
stat := map[string]int{}
msg.Table(func(value ice.Maps) { stat[value[mdb.TYPE]]++; stat[value[mdb.STATUS]]++ })
PushStats(m, kit.Keys(m.CommandKey(), cli.START), stat[cli.START], "", "已启动空间")
PushStats(m, kit.Keys(m.CommandKey(), SERVER), stat[SERVER], "", "已连接机器")
PushStats(m, kit.Keys(m.CommandKey(), ORIGIN), stat[ORIGIN], "", "已连接主机")
}
}},
ORIGIN: {Hand: func(m *ice.Message, arg ...string) {
m.Cmd(SPACE).Table(func(value ice.Maps, index int, head []string) {
kit.If(value[mdb.TYPE] == m.ActionKey(), func() { m.PushRecord(value, head...) })
})
m.SortStrR(mdb.NAME)
kit.If(len(arg) > 0, func() { m.Cut(arg...) })
}},
SERVER: {Hand: func(m *ice.Message, arg ...string) {
m.Cmd(SPACE).Table(func(value ice.Maps, index int, head []string) {
kit.If(value[mdb.TYPE] == m.ActionKey(), func() { m.PushRecord(value, head...) })
})
m.SortStrR(mdb.NAME)
kit.If(len(arg) > 0, func() { m.Cut(arg...) })
}},
WORKER: {Hand: func(m *ice.Message, arg ...string) {
m.Cmd(SPACE).Table(func(value ice.Maps, index int, head []string) {
kit.If(value[mdb.TYPE] == m.ActionKey(), func() { m.PushRecord(value, head...) })
})
m.SortStrR(mdb.NAME)
kit.If(len(arg) > 0, func() { m.Cut(arg...) })
}},
DOWNLOAD: {Name: "download path link", Hand: func(m *ice.Message, arg ...string) {
GoToast(m, func(toast func(string, int, int)) []string {
SpideSave(m, m.Option(nfs.PATH), kit.MergeURL(m.Option(mdb.LINK), cli.GOOS, runtime.GOOS, cli.GOARCH, runtime.GOARCH), func(count, total, value int) {
toast(m.Option(mdb.NAME), count, total)
})
return nil
})
os.Chmod(m.Option(nfs.PATH), ice.MOD_DIR)
}},
VERSION: {Hand: func(m *ice.Message, arg ...string) {
m.Cmdy("web.code.version")
}},
nfs.GOWORK: {Name: "gowork name", Help: "工作区", Icon: "bi bi-exclude", Hand: func(m *ice.Message, arg ...string) {
m.Cmd(cli.SYSTEM, cli.GO, "work", "init")
kit.For([]string{".", nfs.USR_RELEASE, nfs.USR_ICEBERGS, nfs.USR_TOOLKITS}, func(p string) { m.Cmd(cli.SYSTEM, cli.GO, "work", "use", p) })
DreamEach(m, m.Option(mdb.NAME), "", func(name string) { m.Cmd(cli.SYSTEM, cli.GO, "work", "use", path.Join(ice.USR_LOCAL_WORK, name)) })
m.Cmdy(nfs.CAT, "go.work")
}},
}, StatsAction(), DreamAction(), DreamTablesAction(), mdb.ImportantHashAction(
mdb.SHORT, mdb.NAME, mdb.FIELD, "time,name,main,icons,repos,binary,template,restart,access",
html.BUTTON, kit.JoinWord(PORTAL, DESKTOP, ADMIN, WORD, VIMER, STATUS, COMPILE, XTERM, DREAM),
)), Hand: func(m *ice.Message, arg ...string) {
if len(arg) == 0 {
if ice.Info.NodeType == WORKER {
return
}
_dream_list(m)
if _dream_list_more(m); !aaa.IsTechOrRoot(m) || m.IsCliUA() {
m.Action()
} else if m.IsDebug() && cli.SystemFindGo(m) {
m.Action(mdb.CREATE, STARTALL, STOPALL, cli.BUILD, PUBLISH)
} else {
m.Action(mdb.CREATE, STARTALL, STOPALL)
}
if m.Length() == 0 {
m.EchoInfoButton(m.Trans("please scan or create new dream", "请扫描或创建新空间"), mdb.CREATE, nfs.SCAN)
return
}
ctx.DisplayTableCard(m) ctx.DisplayTableCard(m)
m.Options(ice.MSG_TOOLKIT, "web.code.compose.insight")
m.Sort("type,status,name", []string{aaa.LOGIN, WORKER, SERVER, ORIGIN}, []string{cli.START, cli.STOP, cli.BEGIN}, ice.STR_R)
m.StatusTimeCountStats(mdb.TYPE, mdb.STATUS)
} else if arg[0] == ctx.ACTION { } else if arg[0] == ctx.ACTION {
gdb.Event(m, DREAM_ACTION, arg) m.Cmdy(arg[1], DREAM_ACTION, arg)
} else { // gdb.Event(m, DREAM_ACTION, arg)
m.EchoIFrame(m.MergePod(arg[0]))
} }
}}, }},
}) })
} }
func DreamAction() ice.Actions { func DreamTablesAction(arg ...string) ice.Actions {
return ice.MergeActions(ice.Actions{ return ice.Actions{ice.CTX_INIT: {Hand: DreamWhiteHandle},
DREAM_ACTION: {Hand: func(m *ice.Message, arg ...string) { DreamProcess(m, []string{}, arg...) }}, DREAM_TABLES: {Hand: func(m *ice.Message, _ ...string) {
}, gdb.EventsAction(DREAM_OPEN, DREAM_CLOSE, DREAM_INPUTS, DREAM_CREATE, DREAM_TRASH, DREAM_TABLES, DREAM_ACTION)) m.PushButton(kit.Dict(m.CommandKey(), kit.Select(m.Commands("").Help, arg, 0)))
} }},
func DreamProcess(m *ice.Message, args ice.Any, arg ...string) { DREAM_ACTION: {Hand: func(m *ice.Message, arg ...string) { DreamProcess(m, "", nil, arg...) }},
if kit.HasPrefixList(arg, ctx.RUN) {
ctx.ProcessField(m, m.PrefixKey(), args, kit.Slice(arg, 1)...)
} else if kit.HasPrefixList(arg, ctx.ACTION, m.PrefixKey()) || kit.HasPrefixList(arg, ctx.ACTION, m.CommandKey()) {
if arg = kit.Slice(arg, 2); kit.HasPrefixList(arg, DREAM) {
m.Cmdy(SPACE, m.Option(ice.MSG_USERPOD, arg[1]), m.PrefixKey(), ctx.ACTION, DREAM_ACTION, ctx.RUN, arg[2:])
} else if dream := m.Option(mdb.NAME); dream != "" {
m.Cmdy(SPACE, dream, m.PrefixKey(), ctx.ACTION, DREAM_ACTION, ctx.RUN, arg).Optionv(ice.FIELD_PREFIX, kit.Simple(ctx.ACTION, m.PrefixKey(), DREAM, dream, ctx.RUN))
m.Push("_space", dream)
}
} }
} }
func DreamAction() ice.Actions {
return gdb.EventsAction(
DREAM_INPUTS, DREAM_CREATE, DREAM_REMOVE, DREAM_TRASH, DREAM_OPEN, DREAM_CLOSE,
OPS_ORIGIN_OPEN, OPS_SERVER_OPEN, OPS_DREAM_CREATE, OPS_DREAM_REMOVE,
SERVE_START, SPACE_LOGIN,
)
}
func DreamWhiteHandle(m *ice.Message, arg ...string) {
aaa.White(m, kit.Keys(DREAM, ctx.ACTION, m.ShortKey()))
aaa.White(m, kit.Keys(m.ShortKey(), ctx.ACTION, DREAM_ACTION))
}
func DreamProcessIframe(m *ice.Message, arg ...string) {
if !kit.HasPrefixList(arg, ctx.ACTION, m.ShortKey()) && !kit.HasPrefixList(arg, ctx.ACTION, m.CommandKey()) {
return
}
if len(arg) == 2 {
defer m.Push(TITLE, kit.Keys(m.Option(mdb.NAME), m.ShortKey())+kit.Format("(%s)", m.Command().Help))
defer m.Push("_icon", m.Option(mdb.ICON))
}
DreamProcess(m, CHAT_IFRAME, func() string {
p := S(kit.Keys(m.Option(ice.MSG_USERPOD), m.Option(mdb.NAME)))
kit.If(m.Option(mdb.TYPE) == ORIGIN && m.CommandKey() == PORTAL, func() { p = SpideOrigin(m, m.Option(mdb.NAME)) })
return kit.MergeURL(p+C(m.ShortKey()), ice.MSG_DEBUG, m.Option(ice.MSG_DEBUG))
}, arg...)
}
func DreamProcess(m *ice.Message, cmd string, args ice.Any, arg ...string) {
if !kit.HasPrefixList(arg, ctx.ACTION, m.ShortKey()) && !kit.HasPrefixList(arg, ctx.ACTION, m.CommandKey()) {
return
} else if arg = arg[2:]; len(arg) == 0 {
arg = append(arg, m.Option(mdb.NAME))
defer m.ProcessField(ctx.ACTION, m.ShortKey(), arg[0], ctx.RUN)
defer processSpace(m, arg[0], arg[0], m.ShortKey())
}
ctx.ProcessFloat(m.Options(ice.POD, arg[0]), kit.Select(m.ShortKey(), cmd), args, arg[1:]...)
}
func DreamEach(m *ice.Message, name string, status string, cb func(string)) *ice.Message { func DreamEach(m *ice.Message, name string, status string, cb func(string)) *ice.Message {
reg, err := regexp.Compile(name) reg, err := regexp.Compile(name)
if m.Warn(err) { if m.WarnNotValid(err) {
return m return m
} }
list := []string{} msg := m.Spawn()
m.Spawn().Cmds(DREAM).Table(func(value ice.Maps) { m.Cmds(DREAM, kit.Dict(ice.DREAM_SIMPLE, ice.TRUE)).Table(func(value ice.Maps) {
if value[mdb.STATUS] == kit.Select(cli.START, status) && reg.MatchString(value[mdb.NAME]) { if value[mdb.STATUS] == kit.Select(cli.START, status) && value[mdb.TYPE] == WORKER && (value[mdb.NAME] == name || reg.MatchString(kit.Format("%s:%s=%s@%d", value[mdb.NAME], value[mdb.TYPE], value[nfs.MODULE], value[nfs.VERSION]))) {
list = append(list, value[mdb.NAME]) msg.Push(mdb.NAME, value[mdb.NAME])
} }
}) })
if len(list) == 0 { return GoToastTable(msg, mdb.NAME, func(value ice.Maps) { cb(value[mdb.NAME]) })
return m }
} func DreamListSpide(m *ice.Message, list []string, types string, cb func(dev, origin string)) {
GoToast(m, "", func(toast func(string, int, int)) []string { msg := m.Spawn()
kit.For(list, func(index int, name string) { kit.For(list, func(name string) { msg.Push(mdb.NAME, name) })
toast(name, index, len(list)) m.Cmds(SPACE).Table(func(value ice.Maps) { kit.If(value[mdb.TYPE] == types, func() { msg.Push(mdb.NAME, value[mdb.NAME]) }) })
cb(name) has := map[string]bool{}
}) GoToastTable(msg, mdb.NAME, func(value ice.Maps) {
return nil origin := SpideOrigin(m, value[mdb.NAME])
}) kit.If(!has[origin], func() { has[origin] = true; cb(value[mdb.NAME], origin) })
return m })
}
func DreamList(m *ice.Message) *ice.Message {
return AdminCmd(m.Options(ice.DREAM_SIMPLE, ice.TRUE), DREAM)
}
func DreamStat(m *ice.Message, name string) (res string) {
if cli.SystemFindGit(m) {
text := []string{}
for _, line := range kit.Split(m.Cmdx(cli.SYSTEM, cli.GIT, "diff", "--shortstat", kit.Dict(cli.CMD_DIR, path.Join(ice.USR_LOCAL_WORK, name))), mdb.FS, mdb.FS) {
if list := kit.Split(line); strings.Contains(line, nfs.FILE) {
text = append(text, kit.Format("<span class='files'>%s file</span>", list[0]))
} else if strings.Contains(line, "ins") {
text = append(text, kit.Format("<span class='add'>%s+++</span>", list[0]))
} else if strings.Contains(line, "del") {
text = append(text, kit.Format("<span class='del'>%s---</span>", list[0]))
}
}
res = strings.Join(text, "")
}
return
} }

View File

@ -7,9 +7,70 @@ import (
) )
const ( const (
H1 = "h1" FAVICON = "favicon"
H2 = "h2" Mozilla = "Mozilla"
H3 = "h3" Firefox = "Firefox"
Safari = "Safari"
Chrome = "Chrome"
Edg = "Edg"
Mobile = "Mobile"
Alipay = "Alipay"
MicroMessenger = "MicroMessenger"
Android = "Android"
IPhone = "iPhone"
Mac = "Mac"
Linux = "Linux"
Windows = "Windows"
UserAgent = "User-Agent"
XForwardedFor = "X-Forwarded-For"
XHost = "X-Host"
Referer = "Referer"
Authorization = "Authorization"
Bearer = "Bearer"
Basic = "Basic"
Accept = "Accept"
AcceptLanguage = "Accept-Language"
ContentEncoding = "Content-Encoding"
ContentLength = "Content-Length"
ContentType = "Content-Type"
ApplicationForm = "application/x-www-form-urlencoded"
ApplicationOctet = "application/octet-stream"
ApplicationJSON = "application/json"
TEXT_PLAIN = "text/plain"
)
const (
LABEL = "label"
TABLE = "table"
TR = "tr"
TH = "th"
TD = "td"
H1 = "h1"
H2 = "h2"
H3 = "h3"
SPAN = "span"
TEXT = "text"
PLUG = "plug"
FORM = "form"
TEXTAREA = "textarea"
PASSWORD = "password"
CHECKBOX = "checkbox"
SELECT = "select"
BUTTON = "button"
IMAGE = "image"
SUBMIT = "submit"
CHROME = "chrome"
NEED = "need"
MUST = "must"
STYLE = "style"
FLOAT = "float"
WIDTH = "width"
HEIGHT = "height"
BG_COLOR = "background-color"
FG_COLOR = "color"
) )
const ( const (
DARK = "dark" DARK = "dark"
@ -17,6 +78,8 @@ const (
WHITE = "white" WHITE = "white"
BLACK = "black" BLACK = "black"
SILVER = "silver" SILVER = "silver"
DANGER = "danger"
NOTICE = "notice"
PROJECT = "project" PROJECT = "project"
CONTENT = "content" CONTENT = "content"
@ -24,22 +87,32 @@ const (
DISPLAY = "display" DISPLAY = "display"
VIEW = "view" VIEW = "view"
INPUT = "input"
VALUE = "value" VALUE = "value"
INPUT = "input"
ICON = "icon"
ICONS = "icons"
OUTPUT = "output" OUTPUT = "output"
LAYOUT = "layout" LAYOUT = "layout"
RESIZE = "resize" RESIZE = "resize"
FILTER = "filter" // FILTER = "filter"
REFRESH = "refresh"
CONFIRM = "confirm"
COLOR = "color" PLUGIN_JSON = "/plugin/story/json.js"
BACKGROUND_COLOR = "background-color" PLUGIN_INNER = "/plugin/local/code/inner.js"
) PLUGIN_XTERM = "/plugin/local/code/xterm.js"
ICONS_SSH = "usr/icons/ssh.png"
ICONS_MAIL = "usr/icons/Mail.png"
ICONS_DREAM = "usr/icons/Launchpad.png"
ICONS_SETTINGS = "usr/icons/System Settings.png"
const ( GetLocation = "getLocation"
FLOAT = "float" ConnectWifi = "ConnectWifi"
CHROME = "chrome" GetClipboardData = "getClipboardData"
ScanQRCode = "scanQRCode"
TEXT_PLAIN = "text/plain" ChooseImage = "chooseImage"
Record1 = "record1"
Record2 = "record2"
) )
func IsImage(name, mime string) bool { func IsImage(name, mime string) bool {
@ -51,3 +124,30 @@ func IsVideo(name, mime string) bool {
func IsAudio(name, mime string) bool { func IsAudio(name, mime string) bool {
return strings.HasPrefix(mime, "audio/") return strings.HasPrefix(mime, "audio/")
} }
func Format(tag string, inner string, arg ...string) string {
return kit.Format("<%s %s>%s</%s>", tag, kit.JoinProperty(arg...), inner, tag)
}
func FormatA(inner string, arg ...string) string {
return kit.Format(`<a href="%s">%s</a>`, kit.Select(inner, arg, 0), inner)
}
func FormatDanger(value string) string {
return Format(SPAN, value, STYLE, kit.JoinCSS(BG_COLOR, "var(--danger-bg-color)", FG_COLOR, "var(--danger-fg-color)"))
}
var AgentList = []string{
MicroMessenger,
Alipay,
Edg,
Chrome,
Safari,
Firefox,
"Go-http-client",
}
var SystemList = []string{
Android,
IPhone,
Mac,
Linux,
Windows,
}

36
base/web/matrix.css Normal file
View File

@ -0,0 +1,36 @@
fieldset.web.matrix>div.output>table.content th { padding:var(--input-padding); }
fieldset.web.matrix>div.output>table.content th i { padding:var(--input-padding); }
fieldset.web.matrix>div.output>table.content th i:hover { background-color:var(--hover-bg-color); color:var(--hover-fg-color); }
fieldset.web.matrix>div.output>table.content td { padding:var(--input-padding); }
fieldset.web.matrix>div.output>table.content td:hover { color:unset; }
fieldset.web.matrix>div.output>table.content div.item { display:flex; align-items:center; cursor:default; }
fieldset.web.matrix>div.output>table.content div.item img { height:var(--header-height); width:var(--header-height); cursor:pointer; }
fieldset.web.matrix>div.output>table.content div.item img.jpg { padding:var(--input-padding); }
fieldset.web.matrix>div.output>table.content div.item div.title { text-align:left; padding:var(--input-padding); }
fieldset.web.matrix>div.output>table.content div.item div.title>span { cursor:pointer; }
fieldset.web.matrix>div.output>table.content div.item div.title>span.status { font-size:var(--status-font-size); }
fieldset.web.matrix>div.output>table.content div.item div.title>span.status>span { padding:0 var(--input-padding); }
fieldset.web.matrix>div.output>table.content div.item div.title>span.status>span.files { background-color:purple; color:var(--notice-fg-color);}
fieldset.web.matrix>div.output>table.content div.item div.title>span.status>span.add { background-color:var(--notice-bg-color); color:var(--notice-fg-color);}
fieldset.web.matrix>div.output>table.content div.item div.title>span.status>span.del { background-color:var(--danger-bg-color); color:var(--danger-fg-color);}
fieldset.web.matrix>div.output>table.content div.item div.status i { font-size:var(--status-font-size); padding:0; }
fieldset.web.matrix>div.output>table.content div.item div.action { margin-top:var(--input-margin); overflow:hidden; }
fieldset.web.matrix>div.output>table.content div.item div.action input.icons { display:none; }
fieldset.web.matrix>div.output>table.content div.item div.title:hover { background-color:unset; }
fieldset.web.matrix>div.output>table.content div.item div.title span:hover { background-color:var(--hover-bg-color); }
fieldset.web.matrix>div.output>table.content div.item div.status div.item:hover { background-color:var(--hover-bg-color); }
fieldset.web.matrix>div.output>table.content div.item:hover { background-color:unset; color:unset; }
fieldset.web.matrix>div.output:not(.process)>table.content div.item.notice { background-color:var(--notice-bg-color); color:var(--notice-fg-color); }
fieldset.web.matrix>div.output:not(.process)>table.content div.item.danger { background-color:var(--danger-bg-color); color:var(--danger-fg-color); }
fieldset.web.matrix>div.output:not(.process)>table.content div.item.server { border:var(--box-notice); }
fieldset.web.matrix>div.output:not(.process)>table.content div.item.origin { border:var(--box-danger); }
fieldset.web.matrix>div.output:not(.process)>table.content div.item.danger div.status div.item { color:var(--danger-fg-color); }
fieldset.web.matrix>div.output:not(.process)>table.content div.item.notice div.status div.item { color:var(--notice-fg-color); }
fieldset.web.matrix>div.output:not(.process)>table.content div.item.stop div.title>span { color:var(--disable-fg-color); }
fieldset.web.matrix>div.output.process>table.content div.item.process { background-color:blue; color:var(--notice-fg-color); }
fieldset.web.matrix>div.output>table.content tr:not(:hover) div.action { visibility:hidden; }
body:not(.mobile) fieldset.web.matrix>div.output>table.content th:first-child { position:sticky; left:2px; z-index:2; }
body:not(.mobile) fieldset.web.matrix>div.output>table.content td:first-child { box-shadow:var(--th-box-shadow); background-color:var(--plugin-bg-color); position:sticky; left:2px; z-index:1; }
body:not(.mobile) fieldset.web.matrix>div.output>table.content td:hover { box-shadow:var(--notice-box-shadow); }
body:not(.mobile) fieldset.web.matrix>div.output>table.content th:hover { box-shadow:var(--notice-box-shadow); }
body:not(.mobile) fieldset.web.matrix>div.output>table.content tr.danger td:first-child { background-color:transparent; }

168
base/web/matrix.go Normal file
View File

@ -0,0 +1,168 @@
package web
import (
ice "shylinux.com/x/icebergs"
"shylinux.com/x/icebergs/base/aaa"
"shylinux.com/x/icebergs/base/cli"
"shylinux.com/x/icebergs/base/ctx"
"shylinux.com/x/icebergs/base/mdb"
"shylinux.com/x/icebergs/base/nfs"
"shylinux.com/x/icebergs/base/tcp"
"shylinux.com/x/icebergs/base/web/html"
kit "shylinux.com/x/toolkits"
)
func _matrix_list(m *ice.Message, domain, typ string, value ice.Maps, fields ...string) (server, icons, types []string) {
value[DOMAIN], value[mdb.TYPE] = domain, typ
// istech, isdebug := typ == SERVER || kit.IsIn(value[aaa.ACCESS], aaa.TECH, aaa.ROOT), m.IsDebug()
istech := typ == SERVER || kit.IsIn(value[aaa.ACCESS], aaa.TECH, aaa.ROOT)
compile := kit.Select("", kit.Select(COMPILE, UPGRADE, typ == SERVER), istech)
button := []ice.Any{PORTAL, DESKTOP, ADMIN, WORD, OPEN, compile, DREAM}
kit.If(istech, func() { button = append(button, STATUS) })
kit.If(istech, func() { button = append(button, VIMER, COMPILE, cli.RUNTIME, XTERM) })
m.PushRecord(value, fields...).PushButton(button...)
button = []ice.Any{PORTAL, DESKTOP, ADMIN, WORD, OPEN, compile}
kit.If(istech, func() { button = append(button, STATUS) })
kit.If(istech, func() { button = append(button, VIMER, COMPILE, cli.RUNTIME, XTERM, cli.STOP) })
m.Cmd(Space(m, domain), DREAM).Table(func(value ice.Maps) {
switch value[mdb.TYPE] {
case WORKER:
if value[aaa.ACCESS] == aaa.PRIVATE {
break
}
value[DOMAIN] = domain
kit.If(value[mdb.STATUS] == cli.STOP, func() { value[mdb.ICONS] = nfs.P + nfs.USR_ICONS_ICEBERGS })
kit.If(value[mdb.STATUS] == cli.STOP && istech, func() { button = []ice.Any{cli.START, mdb.REMOVE} })
m.PushRecord(value, fields...).PushButton(button...)
case SERVER, ORIGIN:
server = append(server, kit.Keys(domain, value[mdb.NAME]))
icons = append(icons, value[mdb.ICONS])
types = append(types, value[mdb.TYPE])
}
})
return
}
func _matrix_action(m *ice.Message, action string, arg ...string) {
switch domain := kit.Keys(m.Option(DOMAIN), m.Option(mdb.NAME)); action {
case PORTAL, ADMIN:
if kit.HasPrefixList(arg, ctx.RUN) {
ProcessIframe(m, "", "", arg...)
} else {
title, link := kit.Keys(domain, action), kit.Select("", S(domain), domain != "")+C(action)
if m.Option(mdb.TYPE) == ORIGIN {
link = kit.MergeURL2(SpideOrigin(m, m.Option(DOMAIN)), C(action))
if kit.IsIn(action, ADMIN) {
m.ProcessOpen(link)
break
}
}
ProcessIframe(m, title, kit.Select(nfs.PS, link), arg...).ProcessField(ctx.ACTION, action, ctx.RUN)
}
case OPEN:
link := kit.Select(nfs.PS, S(domain), domain != "")
if m.Option(mdb.TYPE) == ORIGIN {
link = SpideOrigin(m, m.Option(DOMAIN))
} else if m.Option("server.type") == ORIGIN {
link = kit.MergeURL2(SpideOrigin(m, m.Option(DOMAIN)), S(m.Option(mdb.NAME)))
}
m.ProcessOpen(link)
default:
if !kit.HasPrefixList(arg, ctx.RUN) {
kit.If(action == XTERM, func() { arg = []string{cli.SH} })
defer m.ProcessField(ctx.ACTION, action, ctx.RUN, domain, action)
}
ProcessPodCmd(m, domain, action, arg, arg...)
}
}
func _matrix_dream(m *ice.Message, action string, arg ...string) {
m.Cmd(Space(m, m.Option(DOMAIN)), DREAM, kit.Select(m.ActionKey(), action), m.OptionSimple(mdb.NAME), arg)
}
func _matrix_cmd(m *ice.Message, cmd string, arg ...string) *ice.Message {
return m.Cmdy(Space(m, kit.Keys(m.Option(DOMAIN), m.Option(mdb.NAME))), kit.Select(m.ActionKey(), cmd), arg)
}
const (
TARGET = "target"
)
const MATRIX = "matrix"
func init() {
Index.MergeCommands(ice.Commands{
MATRIX: {Name: "matrix refresh", Help: "矩阵", Icon: "Mission Control.png", Meta: kit.Dict(
ice.CTX_ICONS, kit.Dict(STATUS, "bi bi-git"), ice.CTX_TRANS, kit.Dict(
STATUS, "源码", html.INPUT, kit.Dict(MYSELF, "本机", ORIGIN, "主机"),
),
), Actions: ice.MergeActions(ice.Actions{
mdb.INPUTS: {Hand: func(m *ice.Message, arg ...string) { m.Cmdy(SPIDE, mdb.INPUTS, arg) }},
mdb.CREATE: {Name: "create origin* name icons", Hand: func(m *ice.Message, arg ...string) {
m.Cmd(SPIDE, mdb.CREATE, m.OptionSimple("origin,name,icons,token"), mdb.TYPE, nfs.REPOS)
m.Cmd(SPIDE, DEV_CREATE_TOKEN, ice.Maps{CLIENT_NAME: m.Option(mdb.NAME)})
}},
mdb.REMOVE: {Hand: func(m *ice.Message, arg ...string) { _matrix_dream(m, nfs.TRASH); _matrix_dream(m, "") }},
cli.START: {Hand: func(m *ice.Message, arg ...string) { _matrix_dream(m, "") }},
cli.STOP: {Hand: func(m *ice.Message, arg ...string) { _matrix_dream(m, "") }},
UPGRADE: {Hand: func(m *ice.Message, arg ...string) { _matrix_cmd(m, "").Sleep3s(); m.ProcessRefresh() }},
INSTALL: {Hand: func(m *ice.Message, arg ...string) {
if kit.IsIn(m.Cmdv(Space(m, m.Option(DOMAIN)), SPIDE, ice.DEV_IP, CLIENT_HOSTNAME), m.Cmd(tcp.HOST).Appendv(aaa.IP)...) {
m.Option(nfs.BINARY, S(m.Option(mdb.NAME)))
} else {
m.OptionDefault(nfs.BINARY, UserHost(m)+S(m.Option(mdb.NAME)))
}
_matrix_dream(m, mdb.CREATE, kit.Simple(m.OptionSimple(mdb.ICONS, nfs.REPOS, nfs.BINARY))...)
m.Cmd(SPACE, kit.Keys(m.Option(DOMAIN), m.Option(mdb.NAME)), MESSAGE, mdb.CREATE, mdb.TYPE, ORIGIN, mdb.ICONS, m.Option(mdb.ICONS), TARGET, kit.Keys(nfs.FROM, m.Option(mdb.NAME)))
m.Cmd(SPACE, m.Option(mdb.NAME), MESSAGE, mdb.CREATE, mdb.TYPE, SERVER, mdb.ICONS, m.Option(mdb.ICONS), TARGET, kit.Keys(ice.OPS, m.Option(DOMAIN), m.Option(mdb.NAME)))
StreamPushRefreshConfirm(m, m.Trans("refresh for new space ", "刷新列表查看新空间 ")+kit.Keys(m.Option(DOMAIN), m.Option(mdb.NAME)))
SpaceEvent(m, OPS_DREAM_SPAWN, "", m.OptionSimple(mdb.NAME, DOMAIN)...)
}},
}, ctx.ConfAction(
mdb.FIELD, "time,domain,status,type,name,text,icons,repos,binary,module,version,access",
ctx.TOOLS, kit.Simple("web.code.compose.insight", VERSION), ONLINE, ice.TRUE, cli.TIMEOUT, "10s",
)), Hand: func(m *ice.Message, arg ...string) {
if kit.HasPrefixList(arg, ctx.ACTION) {
_matrix_action(m, arg[1], arg[2:]...)
return
}
GoToast(m, func(toast func(name string, count, total int)) []string {
field := kit.Split(mdb.Config(m, mdb.FIELD))
space := m.CmdMap(SPACE, mdb.NAME)
m.Options("space.timeout", mdb.Config(m, cli.TIMEOUT), "dream.simple", ice.TRUE)
list, icons, types := _matrix_list(m, "", MYSELF, ice.Maps{
mdb.TIME: ice.Info.Make.Time,
mdb.ICONS: nfs.P + ice.SRC_MAIN_ICO,
nfs.MODULE: ice.Info.Make.Module,
nfs.VERSION: ice.Info.Make.Versions(),
aaa.ACCESS: m.Option(ice.MSG_USERROLE),
}, field...)
kit.For(list, func(domain string, index int, total int) {
toast(domain, index, total)
_matrix_list(m, domain, types[index], ice.Maps{
mdb.TIME: space[domain][mdb.TIME],
mdb.ICONS: icons[index],
nfs.MODULE: space[domain][nfs.MODULE],
nfs.VERSION: space[domain][nfs.VERSION],
aaa.ACCESS: kit.Format(kit.Value(space[domain], aaa.USERROLE)),
}, field...)
})
m.RewriteAppend(func(value, key string, index int) string {
if key == mdb.ICONS && kit.HasPrefix(value, nfs.P, nfs.REQUIRE) {
if domain := m.Appendv(DOMAIN)[index]; domain != "" && space[domain][mdb.TYPE] == ORIGIN {
value = kit.MergeURL2(space[domain][mdb.TEXT], value, m.Appendv(mdb.NAME)[index])
} else if m.Appendv(mdb.TYPE)[index] == SERVER {
value = kit.MergeURL(value, ice.POD, m.Appendv(DOMAIN)[index])
} else if m.Appendv(mdb.TYPE)[index] == WORKER {
value = kit.MergeURL(value, ice.POD, kit.Keys(m.Appendv(DOMAIN)[index], m.Appendv(mdb.NAME)[index]))
}
}
return value
})
m.Action(mdb.CREATE, UPGRADE).StatusTimeCountStats(mdb.TYPE, mdb.STATUS).Display("")
m.Sort("type,status,name,domain", []string{MYSELF, SERVER, ORIGIN, WORKER, ""}, []string{cli.START, cli.STOP, ""}, ice.STR_R, ice.STR_R)
ctx.Toolkit(m)
return nil
})
}},
})
}

77
base/web/matrix.js Normal file
View File

@ -0,0 +1,77 @@
Volcanos(chat.ONIMPORT, {
_init: function(can, msg) { var list = {}, domain = [""], server = []
msg.Table(function(value) { var name = value.name, _domain = value.domain
list[name] = list[name]||{}, list[name][_domain] = value, domain.indexOf(_domain) == -1 && domain.push(_domain)
value.type == web.SERVER && server.push(value.domain)
}), can.db.list = list, can.db.domain = domain, can.db.server = server
if (domain.length > can.core.Item(list).length) {
can.ui = can.page.Appends(can, can._output, [{view: [wiki.CONTENT, html.TABLE], list: [
{type: html.THEAD, list: [{type: html.TR, list: can.core.Item(list, function(name, value) {
return {type: html.TH, list: [value[""]? can.onimport.item(can, value[""], list): can.onimport.void(can, name, domain, list)]}
}) }]},
{type: html.TBODY, list: can.core.List(domain, function(domain) { if (!domain) { return }
return {type: html.TR, list: can.core.Item(list, function(name, value) { var item = value[domain]
return {type: html.TD, list: [item? can.onimport.item(can, item, list): can.onimport.void(can, name, domain, list)]}
})}
})},
] }]), can.onmotion.delay(can, function() { can.Status(mdb.COUNT, can.core.List(domain).length+"x"+can.core.Item(list).length) })
} else {
can.ui = can.page.Appends(can, can._output, [{view: [wiki.CONTENT, html.TABLE], list: [
{type: html.THEAD, list: [{type: html.TR, list: can.core.List(domain, function(domain) {
return {type: html.TH, list: [can.onimport.item(can, list[""][domain], list)]}
}) }]},
{type: html.TBODY, list: can.core.Item(list, function(name, value) { if (!name) { return }
return {type: html.TR, list: can.core.List(domain, function(domain) { var item = value[domain]
return {type: html.TD, list: [item? can.onimport.item(can, item, list): can.onimport.void(can, name, domain, list)]}
})}
})},
] }]), can.onmotion.delay(can, function() { can.Status(mdb.COUNT, can.core.Item(list).length+"x"+can.core.List(domain).length) })
}
},
void: function(can, name, domain, list) { var worker = list[name][""], server = list[""][domain]
return {view: html.ACTION, _init: function(target) {
worker && server.type != web.ORIGIN && can.onappend.input(can, {type: html.BUTTON, name: code.INSTALL, onclick: function(event) {
can.Update(can.request(event, {name: name, domain: domain}, worker), [ctx.ACTION, code.INSTALL])
}}, "", target)
}}
},
item: function(can, item, list) { var name = item.name, domain = item.domain, worker = list[name][""], server = list[""][domain]; item["server.type"] = server.type
function cb(action) { return function(event) { can.Update(can.request(event, item), [ctx.ACTION, action]) } }
return {view: [[html.ITEM, item.type, item.status, can.onimport.style(can, item, list)]], list: [
{img: item.icons, onclick: cb(web.DESKTOP)},
{view: wiki.TITLE, list: [
{text: item.name||item.domain||location.host, onclick: cb(web.OPEN)},
item.status != cli.STOP && can.onappend.label(can, item, {version: icon.version, time: icon.compile, access: "bi bi-file-lock"}),
{text: [item.text, "", mdb.STATUS]}, can.onappend.buttons(can, item),
]},
], _init: function(target) { item._target = target }}
},
style: function(can, item, list) { var name = item.name, domain = item.domain, worker = list[name][""]
if (worker && worker.module != item.module) { return
can.core.Item(list, function(key, value) { value = value[""]
if (value.module == item.module) { worker = value }
})
}
return !worker? html.NOTICE: (worker.status != cli.STOP && item.status != cli.STOP && (item.version != worker.version ||
(item["server.type"] == "origin"? item.time > worker.time: item.time < worker.time)
))? html.DANGER: ""
},
}, [""])
Volcanos(chat.ONACTION, {
upgrade: function(event, can) { var msg = can.request(event)
if (msg.Option(mdb.NAME) || msg.Option(web.DOMAIN)) { return can.Update(event, [ctx.ACTION, code.UPGRADE]) }
can.page.ClassList.add(can, can._output, ice.PROCESS)
can.core.Next(can.db.server, function(server, next, index) {
can.core.Next(can.core.Item(can.db.list, function(key, value) { return value }), function(list, next, i) {
var item = list[server]; if (!item) { return next() } if (!item.name || item.status != cli.START) { return next() }
can.page.ClassList.add(can, item._target, ice.PROCESS)
can.Update(can.request({}, item, {_handle: ice.TRUE}), [ctx.ACTION, code.UPGRADE], function(msg) { next() })
}, next)
}, function() {
can.core.Next(can.db.server, function(server, next, index) {
var item = can.db.list[""][server]; can.page.ClassList.add(can, item._target, ice.PROCESS)
can.Update(can.request({}, item, {_handle: ice.TRUE}), [ctx.ACTION, code.UPGRADE], function(msg) { next() })
}, function() { can.onmotion.delay(can, function() {can.Update() }, 3000) })
})
},
})

View File

@ -3,14 +3,10 @@ package web
import ( import (
"net/url" "net/url"
"strings" "strings"
"time"
ice "shylinux.com/x/icebergs" ice "shylinux.com/x/icebergs"
"shylinux.com/x/icebergs/base/aaa"
"shylinux.com/x/icebergs/base/cli" "shylinux.com/x/icebergs/base/cli"
"shylinux.com/x/icebergs/base/ctx" "shylinux.com/x/icebergs/base/ctx"
"shylinux.com/x/icebergs/base/lex"
"shylinux.com/x/icebergs/base/log"
"shylinux.com/x/icebergs/base/mdb" "shylinux.com/x/icebergs/base/mdb"
"shylinux.com/x/icebergs/base/nfs" "shylinux.com/x/icebergs/base/nfs"
"shylinux.com/x/icebergs/base/tcp" "shylinux.com/x/icebergs/base/tcp"
@ -18,22 +14,22 @@ import (
"shylinux.com/x/toolkits/file" "shylinux.com/x/toolkits/file"
) )
type Message interface { func UserWeb(m *ice.Message) *url.URL {
Option(key string, arg ...ice.Any) string return kit.ParseURL(m.OptionDefault(ice.MSG_USERWEB, "http://localhost:9020"))
PrefixKey() string
}
func UserWeb(m Message) *url.URL {
return kit.ParseURL(m.Option(ice.MSG_USERWEB))
} }
func UserHost(m *ice.Message) string { func UserHost(m *ice.Message) string {
if u := UserWeb(m); strings.Contains(u.Host, tcp.LOCALHOST) { if p := m.Option(ice.MSG_USERHOST); p != "" {
return p
} else if u := UserWeb(m); u.Hostname() == tcp.LOCALHOST {
if ice.Info.Host != "" {
return m.Option(ice.MSG_USERHOST, strings.ReplaceAll(u.Scheme+"://"+u.Host, tcp.LOCALHOST, ice.Info.Host))
}
return m.Option(ice.MSG_USERHOST, tcp.PublishLocalhost(m, u.Scheme+"://"+u.Host)) return m.Option(ice.MSG_USERHOST, tcp.PublishLocalhost(m, u.Scheme+"://"+u.Host))
} else { } else {
return m.Option(ice.MSG_USERHOST, u.Scheme+"://"+u.Host) return m.Option(ice.MSG_USERHOST, u.Scheme+"://"+u.Host)
} }
} }
func AgentIs(m Message, arg ...string) bool { func AgentIs(m *ice.Message, arg ...string) bool {
for _, k := range arg { for _, k := range arg {
if strings.HasPrefix(strings.ToLower(m.Option(ice.MSG_USERUA)), k) { if strings.HasPrefix(strings.ToLower(m.Option(ice.MSG_USERUA)), k) {
return true return true
@ -41,17 +37,6 @@ func AgentIs(m Message, arg ...string) bool {
} }
return false return false
} }
func MergeURL2(m *ice.Message, url string, arg ...ice.Any) string {
kit.If(m.Option(log.DEBUG) == ice.TRUE, func() { arg = append(arg, log.DEBUG, ice.TRUE) })
kit.If(m.Option(ice.MSG_USERWEB) == "", func() {
m.Option(ice.MSG_USERWEB, Domain(ice.Pulse.Cmdv(tcp.HOST, aaa.IP), ice.Pulse.Cmdv(SERVE, tcp.PORT)))
})
return kit.MergeURL2(m.Option(ice.MSG_USERWEB), url, arg...)
}
func MergeLink(m *ice.Message, url string, arg ...ice.Any) string {
kit.If(m.Option(log.DEBUG) == ice.TRUE, func() { arg = append(arg, log.DEBUG, ice.TRUE) })
return kit.MergeURL(strings.Split(MergeURL2(m, url), QS)[0], arg...)
}
func ParseLink(m *ice.Message, url string) ice.Maps { func ParseLink(m *ice.Message, url string) ice.Maps {
list := ice.Maps{} list := ice.Maps{}
u := kit.ParseURL(url) u := kit.ParseURL(url)
@ -64,33 +49,21 @@ func ParseLink(m *ice.Message, url string) ice.Maps {
kit.For(u.Query(), func(k string, v []string) { list[k] = v[0] }) kit.For(u.Query(), func(k string, v []string) { list[k] = v[0] })
return list return list
} }
func ProcessPodCmd(m *ice.Message, pod, cmd string, arg ...ice.Any) {
m.ProcessOpen(m.MergePodCmd(pod, cmd, arg...))
}
func ProcessIframe(m *ice.Message, name, link string, arg ...string) {
ctx.ProcessField(m, CHAT_IFRAME, func() []string {
return []string{m.Cmdx(CHAT_IFRAME, mdb.CREATE, mdb.TYPE, LINK, mdb.NAME, name, LINK, link)}
}, arg...)
}
func PushPodCmd(m *ice.Message, cmd string, arg ...string) *ice.Message { func PushPodCmd(m *ice.Message, cmd string, arg ...string) *ice.Message {
list := []string{} if m.IsWorker() {
m.Cmds(SPACE, func(value ice.Maps) {
kit.If(kit.IsIn(value[mdb.TYPE], WORKER), func() { list = append(list, value[mdb.NAME]) })
})
if len(list) == 0 {
return m return m
} }
msg := m.Spawn()
m.Cmds(SPACE, func(value ice.Maps) {
kit.If(kit.IsIn(value[mdb.TYPE], WORKER), func() { msg.Push(SPACE, value[mdb.NAME]) })
})
kit.If(m.Length() > 0 && len(m.Appendv(SPACE)) == 0, func() { m.Table(func(value ice.Maps) { m.Push(SPACE, "") }) }) kit.If(m.Length() > 0 && len(m.Appendv(SPACE)) == 0, func() { m.Table(func(value ice.Maps) { m.Push(SPACE, "") }) })
GoToast(m, "", func(toast func(string, int, int)) []string { GoToastTable(msg, SPACE, func(value ice.Maps) {
kit.For(list, func(index int, space string) { m.Cmd(SPACE, value[SPACE], kit.Dict(ice.MSG_USERPOD, value[SPACE]), kit.Select(m.ShortKey(), cmd), arg).Table(func(val ice.Maps, index int, head []string) {
toast(space, index, len(list)) kit.If(!kit.IsIn(SPACE, head...), func() { head = append(head, SPACE) })
m.Cmd(SPACE, space, kit.Dict(ice.MSG_USERPOD, space), kit.Select(m.PrefixKey(), cmd), arg).Table(func(index int, val ice.Maps, head []string) { val[SPACE] = kit.Keys(m.Option(ice.MSG_USERPOD), value[SPACE], val[SPACE])
kit.If(!kit.IsIn(SPACE, head...), func() { head = append(head, SPACE) }) m.Push("", val, head)
val[SPACE] = kit.Keys(space, val[SPACE])
m.Push("", val, head)
})
}) })
return nil
}) })
return m return m
} }
@ -102,67 +75,31 @@ func PushImages(m *ice.Message, name string) {
} }
} }
func PushNotice(m *ice.Message, arg ...ice.Any) { func PushNotice(m *ice.Message, arg ...ice.Any) {
opts := ice.Map{ice.MSG_OPTION: []string{}, ice.MSG_OPTS: []string{}}
kit.For([]string{ice.LOG_DEBUG, ice.LOG_TRACEID}, func(key string) {
opts[ice.MSG_OPTION] = kit.Simple(opts[ice.MSG_OPTION], key)
opts[key] = m.Option(key)
})
if m.Option(ice.MSG_DAEMON) == "" { if m.Option(ice.MSG_DAEMON) == "" {
return return
} else if m.Option(ice.MSG_USERPOD) == "" {
m.Cmd(SPACE, m.Option(ice.MSG_DAEMON), arg, opts)
} else {
m.Cmd(SPACE, kit.Keys(m.Option("__target"), m.Option(ice.MSG_DAEMON)), arg, opts)
} }
opts := ice.Map{ice.MSG_OPTION: []string{}, ice.MSG_OPTS: []string{}}
kit.For([]string{ctx.DISPLAY, ctx.STYLE, cli.DELAY, ice.MSG_TITLE, ice.MSG_STATUS, ice.LOG_DEBUG, ice.LOG_TRACEID, ice.LOG_DISABLE}, func(key string) {
opts[ice.MSG_OPTION], opts[key] = kit.Simple(opts[ice.MSG_OPTION], key), m.Option(key)
})
m.Cmd(SPACE, m.Option(ice.MSG_DAEMON), arg, opts)
}
func PushNoticeToast(m *ice.Message, arg ...ice.Any) {
PushNotice(m, kit.List(TOAST, arg)...)
}
func PushNoticeRefresh(m *ice.Message, arg ...ice.Any) {
PushNotice(m, kit.List("refresh", arg)...)
}
func PushNoticeGrow(m *ice.Message, arg ...ice.Any) {
PushNotice(m.StatusTimeCount(), kit.List("grow", arg)...)
}
func PushNoticeRich(m *ice.Message, arg ...ice.Any) {
PushNotice(m.StatusTimeCount(), kit.Simple("rich", arg))
} }
func PushNoticeToast(m *ice.Message, arg ...ice.Any) { PushNotice(m, kit.List("toast", arg)...) }
func PushNoticeGrow(m *ice.Message, arg ...ice.Any) { PushNotice(m, kit.List("grow", arg)...) }
func PushStream(m *ice.Message) *ice.Message { func PushStream(m *ice.Message) *ice.Message {
m.Options(cli.CMD_OUTPUT, file.NewWriteCloser(func(buf []byte) { PushNoticeGrow(m, string(buf)) }, nil)).ProcessHold(toastContent(m, ice.SUCCESS)) msg := m.SpawnSilent()
m.Options(cli.CMD_OUTPUT, file.NewWriteCloser(func(buf []byte) { PushNoticeGrow(msg, string(buf)) }, nil)).ProcessHold(toastContent(m, ice.SUCCESS))
return m return m
} }
func init() { ice.Info.PushStream = PushStream }
func init() { ice.Info.PushNotice = PushNotice } func init() { ice.Info.PushNotice = PushNotice }
func init() { ice.Info.PushStream = PushStream }
func Toast(m *ice.Message, text string, arg ...ice.Any) *ice.Message { // [title [duration [progress]]]
if len(arg) > 1 {
switch val := arg[1].(type) {
case string:
if value, err := time.ParseDuration(val); err == nil {
arg[1] = int(value / time.Millisecond)
}
}
}
kit.If(len(arg) == 0, func() { arg = append(arg, m.PrefixKey()) })
kit.If(len(arg) > 0, func() { arg[0] = kit.Select(m.PrefixKey(), arg[0]) })
PushNoticeToast(m, text, arg)
return m
}
func toastContent(m *ice.Message, state string) string {
return kit.Join([]string{map[string]string{ice.PROCESS: "🕑", ice.FAILURE: "❌", ice.SUCCESS: "✅"}[state], state, m.ActionKey()}, " ")
}
func ToastSuccess(m *ice.Message, arg ...ice.Any) { Toast(m, toastContent(m, ice.SUCCESS), arg...) }
func ToastFailure(m *ice.Message, arg ...ice.Any) { Toast(m, toastContent(m, ice.FAILURE), arg...) }
func ToastProcess(m *ice.Message, arg ...ice.Any) func() {
kit.If(len(arg) == 0, func() { arg = kit.List("", "-1") })
kit.If(len(arg) == 1, func() { arg = append(arg, "-1") })
Toast(m, toastContent(m, ice.PROCESS), arg...)
return func() { Toast(m, toastContent(m, ice.SUCCESS)) }
}
func GoToast(m *ice.Message, title string, cb func(toast func(string, int, int)) []string) *ice.Message {
_total := 0
toast := func(name string, count, total int) {
kit.If(total == 0, func() { total = 1 })
Toast(m,
kit.Format("%s %s/%s", name, strings.TrimSuffix(kit.FmtSize(int64(count)), "B"), strings.TrimSuffix(kit.FmtSize(int64(total)), "B")),
kit.Format("%s %d%%", kit.Select(m.ActionKey(), title), count*100/total), kit.Select("1000", "30000", count < total), count*100/total,
)
_total = total
}
if list := cb(toast); len(list) > 0 {
Toast(m, strings.Join(list, lex.NL), ice.FAILURE, "30s")
} else {
toast(ice.SUCCESS, _total, _total)
}
return m
}

44
base/web/process.go Normal file
View File

@ -0,0 +1,44 @@
package web
import (
"strings"
ice "shylinux.com/x/icebergs"
"shylinux.com/x/icebergs/base/ctx"
"shylinux.com/x/icebergs/base/mdb"
kit "shylinux.com/x/toolkits"
)
func ProcessIframe(m *ice.Message, title, link string, arg ...string) *ice.Message {
if m.IsMetaKey() {
m.ProcessOpen(link)
return m
} else if !kit.HasPrefixList(arg, ctx.RUN) {
defer m.Push(TITLE, title)
}
return ctx.ProcessFloat(m, CHAT_IFRAME, link, arg...)
}
func ProcessPodCmd(m *ice.Message, pod, cmd string, args ice.Any, arg ...string) *ice.Message {
if kit.HasPrefixList(arg, ctx.RUN) {
pod, cmd, arg = arg[1], arg[2], kit.Simple(arg[0], arg[3:])
} else {
cmd = kit.Select(m.ActionKey(), cmd)
defer processSpace(m, pod, pod, cmd)
}
return ctx.ProcessFloat(m.Options(ice.POD, pod), cmd, args, arg...)
}
func ProcessHashPodCmd(m *ice.Message, arg ...string) (msg *ice.Message) {
if kit.HasPrefixList(arg, ctx.RUN) {
msg = mdb.HashSelects(m.Spawn(), arg[1])
arg = kit.Simple(arg[0], arg[2:])
} else {
msg = mdb.HashSelects(m.Spawn(), m.Option(mdb.HASH))
defer processSpace(m, msg.Append(SPACE), m.Option(mdb.HASH))
}
return ctx.ProcessFloat(m.Options(ice.POD, msg.Append(SPACE)), msg.Append(ctx.INDEX), kit.Split(msg.Append(ctx.ARGS)), arg...)
}
func processSpace(m *ice.Message, pod string, arg ...string) {
m.ProcessField(kit.TransArgs(kit.Simple(ctx.ACTION, m.ActionKey(), ctx.RUN, arg))...)
m.RewriteAppend(func(value, key string, index int) string { return kit.Select("", value, key != SPACE) })
m.Push(ice.MSG_SPACE, strings.TrimPrefix(pod, "ops."))
}

24
base/web/product.go Normal file
View File

@ -0,0 +1,24 @@
package web
import (
"strings"
ice "shylinux.com/x/icebergs"
"shylinux.com/x/icebergs/base/ctx"
"shylinux.com/x/icebergs/base/mdb"
kit "shylinux.com/x/toolkits"
)
const PRODUCT = "product"
func init() {
Index.MergeCommands(ice.Commands{
PRODUCT: {Name: "product refresh", Help: "产品展示", Actions: mdb.HashAction(mdb.SHORT, "index", mdb.FIELD, "time,name,text,order,disable,index,args"), Hand: func(m *ice.Message, arg ...string) {
mdb.HashSelect(m, arg...).SortInt(mdb.ORDER)
}},
})
}
func AddPortalProduct(m *ice.Message, name, text string, order float64, arg ...string) {
m.Cmd("web.product", mdb.CREATE, mdb.NAME, name, mdb.TEXT, strings.TrimSpace(text), mdb.ORDER, order, ctx.INDEX, m.PrefixKey(), ctx.ARGS, kit.Format(arg))
}

View File

@ -14,6 +14,7 @@ import (
"shylinux.com/x/icebergs/base/mdb" "shylinux.com/x/icebergs/base/mdb"
"shylinux.com/x/icebergs/base/nfs" "shylinux.com/x/icebergs/base/nfs"
"shylinux.com/x/icebergs/base/tcp" "shylinux.com/x/icebergs/base/tcp"
"shylinux.com/x/icebergs/base/web/html"
kit "shylinux.com/x/toolkits" kit "shylinux.com/x/toolkits"
) )
@ -23,8 +24,21 @@ const (
COOKIE = "cookie" COOKIE = "cookie"
REQUEST = "request" REQUEST = "request"
RESPONSE = "response" RESPONSE = "response"
CONTENT = "content"
TITLE = "title"
STYLE = "style"
) )
func renderMsg(m *ice.Message) {
m.FormatsMeta(m.W,
ice.MSG_USERIP, ice.MSG_USERUA, ice.MSG_METHOD, ice.MSG_REFERER, ice.MSG_DAEMON,
ice.MSG_LANGUAGE, ice.MSG_THEME, ice.MSG_BG, ice.MSG_FG,
ice.MSG_RIVER, ice.MSG_STORM, ice.MSG_INDEX, ice.MSG_FIELDS,
ice.MSG_SOURCE, ice.MSG_TARGET,
"task.id", "work.id", "space.timeout",
ice.MSG_USERWEB0, ice.MSG_USERPOD0,
)
}
func Render(m *ice.Message, cmd string, args ...ice.Any) bool { func Render(m *ice.Message, cmd string, args ...ice.Any) bool {
if cmd == ice.RENDER_VOID { if cmd == ice.RENDER_VOID {
return true return true
@ -32,7 +46,7 @@ func Render(m *ice.Message, cmd string, args ...ice.Any) bool {
arg := kit.Simple(args...) arg := kit.Simple(args...)
kit.If(len(arg) == 0, func() { args = nil }) kit.If(len(arg) == 0, func() { args = nil })
if cmd != "" { if cmd != "" {
if cmd != ice.RENDER_DOWNLOAD || !kit.HasPrefix(arg[0], ice.SRC_TEMPLATE, ice.USR_INTSHELL, ice.USR_VOLCANOS, ice.USR_ICONS, ice.USR_MODULES) { if cmd != ice.RENDER_DOWNLOAD || !kit.HasPrefix(arg[0], nfs.SRC, nfs.USR, ice.SRC_TEMPLATE, ice.USR_INTSHELL, ice.USR_VOLCANOS) {
if !(cmd == ice.RENDER_RESULT && len(args) == 0) { if !(cmd == ice.RENDER_RESULT && len(args) == 0) {
defer func() { m.Logs("Render", cmd, args) }() defer func() { m.Logs("Render", cmd, args) }()
} }
@ -42,9 +56,14 @@ func Render(m *ice.Message, cmd string, args ...ice.Any) bool {
case COOKIE: // value [name [path [expire]]] case COOKIE: // value [name [path [expire]]]
RenderCookie(m, arg[0], arg[1:]...) RenderCookie(m, arg[0], arg[1:]...)
case STATUS, ice.RENDER_STATUS: // [code [text]] case STATUS, ice.RENDER_STATUS: // [code [text]]
RenderStatus(m.W, kit.Int(kit.Select("200", arg, 0)), kit.Select(m.Result(), strings.Join(kit.Slice(arg, 1), " "))) if m.IsCliUA() {
RenderStatus(m.W, kit.Int(kit.Select("200", arg, 0)), kit.Select(m.Result(), strings.Join(kit.Slice(arg, 1), " ")))
} else {
m.W.WriteHeader(kit.Int(kit.Select("200", arg, 0)))
renderMsg(m)
}
case ice.RENDER_REDIRECT: // url [arg...] case ice.RENDER_REDIRECT: // url [arg...]
http.Redirect(m.W, m.R, kit.MergeURL(arg[0], arg[1:]), http.StatusTemporaryRedirect) http.Redirect(m.W, m.R, m.MergeLink(arg[0], arg[1:]), http.StatusTemporaryRedirect)
case ice.RENDER_DOWNLOAD: // file [type [name]] case ice.RENDER_DOWNLOAD: // file [type [name]]
if strings.HasPrefix(arg[0], HTTP) { if strings.HasPrefix(arg[0], HTTP) {
RenderRedirect(m, arg[0]) RenderRedirect(m, arg[0])
@ -52,10 +71,31 @@ func Render(m *ice.Message, cmd string, args ...ice.Any) bool {
} }
RenderType(m.W, arg[0], kit.Select("", arg, 1)) RenderType(m.W, arg[0], kit.Select("", arg, 1))
RenderHeader(m.W, "Content-Disposition", fmt.Sprintf("filename=%s", kit.Select(path.Base(kit.Select(arg[0], m.Option("filename"))), arg, 2))) RenderHeader(m.W, "Content-Disposition", fmt.Sprintf("filename=%s", kit.Select(path.Base(kit.Select(arg[0], m.Option("filename"))), arg, 2)))
if m.Option("render") == "replace" {
res := m.Cmdx(nfs.CAT, arg[0])
fieldset := "fieldset." + m.Option(ctx.INDEX)
m.W.Write([]byte(kit.ReplaceAll(res,
"$content", fieldset+">div.output>div.layout>div.layout>div.content",
"$profile", fieldset+">div.output>div.layout>div.layout>div.profile",
"$display", fieldset+">div.output>div.layout>div.display",
"$project", fieldset+">div.output>div.project",
"$option", fieldset+">form.option",
"$action", fieldset+">div.action",
"$output", fieldset+">div.output",
"$status", fieldset+">div.status",
"$fieldset", fieldset,
"$body", "body.cmd."+m.Option(ctx.INDEX),
"$index", m.Option(ctx.INDEX),
"$input", "body>div.input.float."+m.Option(ctx.INDEX),
)))
break
}
if _, e := nfs.DiskFile.StatFile(arg[0]); e == nil { if _, e := nfs.DiskFile.StatFile(arg[0]); e == nil {
http.ServeFile(m.W, m.R, kit.Path(arg[0])) http.ServeFile(m.W, m.R, kit.Path(arg[0]))
} else if f, e := nfs.PackFile.OpenFile(arg[0]); e == nil { } else if f, e := nfs.PackFile.OpenFile(arg[0]); e == nil {
defer f.Close() defer f.Close()
t, _ := time.ParseInLocation("2006-01-02 15:04:05", ice.Info.Make.When, time.Local)
RenderHeader(m.W, "Last-Modified", t.UTC().Format(time.RFC1123))
io.Copy(m.W, f) io.Copy(m.W, f)
} }
case ice.RENDER_RESULT: case ice.RENDER_RESULT:
@ -71,16 +111,17 @@ func Render(m *ice.Message, cmd string, args ...ice.Any) bool {
default: default:
kit.If(cmd != "" && cmd != ice.RENDER_RAW, func() { m.Echo(kit.Format(cmd, args...)) }) kit.If(cmd != "" && cmd != ice.RENDER_RAW, func() { m.Echo(kit.Format(cmd, args...)) })
RenderType(m.W, nfs.JSON, "") RenderType(m.W, nfs.JSON, "")
m.FormatsMeta(m.W) renderMsg(m)
} }
m.Render(ice.RENDER_VOID) m.Render(ice.RENDER_VOID)
return true return true
} }
func CookieName(url string) string { return ice.MSG_SESSID + "_" + kit.ParseURLMap(url)[tcp.PORT] } func CookieName(url string) string { return ice.MSG_SESSID + "_" + kit.ParseURLMap(url)[tcp.PORT] }
func RenderCookie(m *ice.Message, value string, arg ...string) { // name path expire func RenderCookie(m *ice.Message, value string, arg ...string) string { // name path expire
http.SetCookie(m.W, &http.Cookie{Value: value, Name: kit.Select(CookieName(m.Option(ice.MSG_USERWEB)), arg, 0), http.SetCookie(m.W, &http.Cookie{Value: value, Name: kit.Select(CookieName(m.Option(ice.MSG_USERWEB)), arg, 0),
Path: kit.Select(nfs.PS, arg, 1), Expires: time.Now().Add(kit.Duration(kit.Select(mdb.MONTH, arg, 2)))}) Path: kit.Select(nfs.PS, arg, 1), Expires: time.Now().Add(kit.Duration(kit.Select(mdb.MONTH, arg, 2)))})
return value
} }
func RenderType(w http.ResponseWriter, name, mime string) { func RenderType(w http.ResponseWriter, name, mime string) {
if mime == "" { if mime == "" {
@ -93,92 +134,124 @@ func RenderType(w http.ResponseWriter, name, mime string) {
mime = "application/" + kit.Ext(name) mime = "application/" + kit.Ext(name)
} }
} }
RenderHeader(w, ContentType, mime) RenderHeader(w, html.ContentType, mime)
} }
func RenderOrigin(w http.ResponseWriter, origin string) { func RenderOrigin(w http.ResponseWriter, origin string) {
RenderHeader(w, "Access-Control-Allow-Origin", origin) RenderHeader(w, "Access-Control-Allow-Origin", origin)
} }
func RenderHeader(w http.ResponseWriter, key, value string) { func RenderHeader(w http.ResponseWriter, key, value string) { w.Header().Set(key, value) }
w.Header().Set(key, value)
}
func RenderStatus(w http.ResponseWriter, code int, text string) { func RenderStatus(w http.ResponseWriter, code int, text string) {
w.WriteHeader(code) w.WriteHeader(code)
w.Write([]byte(text)) w.Write([]byte(text))
} }
func RenderRedirect(m *ice.Message, arg ...ice.Any) { func RenderRedirect(m *ice.Message, arg ...ice.Any) { Render(m, ice.RENDER_REDIRECT, arg...) }
Render(m, ice.RENDER_REDIRECT, arg...) func RenderDownload(m *ice.Message, arg ...ice.Any) { Render(m, ice.RENDER_DOWNLOAD, arg...) }
} func RenderResult(m *ice.Message, arg ...ice.Any) { Render(m, ice.RENDER_RESULT, arg...) }
func RenderDownload(m *ice.Message, arg ...ice.Any) {
Render(m, ice.RENDER_DOWNLOAD, arg...)
}
func RenderResult(m *ice.Message, arg ...ice.Any) {
Render(m, ice.RENDER_RESULT, arg...)
}
func RenderTemplate(m *ice.Message, file string, arg ...ice.Any) *ice.Message { func RenderTemplate(m *ice.Message, file string, arg ...ice.Any) *ice.Message {
return m.RenderResult(kit.Renders(kit.Format(m.Cmdx(nfs.CAT, path.Join(ice.SRC_TEMPLATE, WEB, file)), arg...), m)) return m.RenderResult(kit.Renders(kit.Format(m.Cmdx(nfs.CAT, path.Join(ice.SRC_TEMPLATE, WEB, file)), arg...), m))
} }
func RenderRefresh(m *ice.Message, arg ...string) { // url text delay
RenderTemplate(m, "refresh.html", kit.Select("3", arg, 2), kit.Select(m.Option(ice.MSG_USERWEB), arg, 0), kit.Select("loading...", arg, 1))
}
func RenderMain(m *ice.Message) *ice.Message { func RenderMain(m *ice.Message) *ice.Message {
if m.IsCliUA() { if m.IsCliUA() {
return m.RenderDownload(path.Join(ice.USR_INTSHELL, ice.INDEX_SH)) return m.RenderDownload(path.Join(ice.USR_INTSHELL, ice.INDEX_SH))
} }
m.Option(nfs.VERSION, RenderVersion(m)+kit.Select("", "&pod="+m.Option(ice.MSG_USERPOD), m.Option(ice.MSG_USERPOD) != "")) m.Options(nfs.SCRIPT, ice.SRC_MAIN_JS, nfs.VERSION, RenderVersion(m))
return RenderTemplate(m, "main.html") m.OptionDefault(mdb.ICONS, strings.Split(m.Resource(ice.Info.NodeIcon), "?")[0]+m.Option(nfs.VERSION))
m.OptionDefault(TITLE, kit.Select("", ice.Info.Titles, ice.Info.Titles != "ContextOS"))
kit.If(ice.Info.NodeType == WORKER, func() { m.OptionDefault(TITLE, m.Option(ice.MSG_USERPOD)) })
m.OptionDefault(TITLE, kit.Select("ContextOS", UserWeb(m).Host))
return m.RenderResult(kit.Renders(m.Cmdx(nfs.CAT, ice.SRC_MAIN_HTML), m))
} }
func RenderCmds(m *ice.Message, list ...ice.Any) { func RenderCmds(m *ice.Message, cmds ...ice.Any) {
m.Option(nfs.VERSION, RenderVersion(m)+kit.Select("", "&pod="+m.Option(ice.MSG_USERPOD), m.Option(ice.MSG_USERPOD) != "")) RenderMain(m.Options(ctx.CMDS, kit.Format(cmds)))
RenderTemplate(m.Options(mdb.LIST, kit.Format(list)), "cmds.html")
} }
func RenderPodCmd(m *ice.Message, pod, cmd string, arg ...ice.Any) { func RenderPodCmd(m *ice.Message, pod, cmd string, arg ...ice.Any) {
msg := m.Cmd(Space(m, pod), ctx.COMMAND, kit.Select(m.PrefixKey(), cmd)) if msg := m.Cmd(Space(m, pod), ctx.COMMAND, kit.Select(m.ShortKey(), cmd)); msg.Length() == 0 {
RenderCmds(m, kit.Dict(msg.AppendSimple(mdb.NAME, mdb.HELP), RenderResult(m, kit.Format("not found command %s", cmd))
ctx.INDEX, msg.Append(ctx.INDEX), ctx.ARGS, kit.Simple(arg), ctx.DISPLAY, m.Option(ice.MSG_DISPLAY), } else {
mdb.LIST, kit.UnMarshal(msg.Append(mdb.LIST)), mdb.META, kit.UnMarshal(msg.Append(mdb.META)), if kit.IsIn(msg.Append(ctx.INDEX), "word", "vimer", "web.wiki.word", "web.code.vimer") {
)) m.Option(mdb.ICONS, msg.Option(ice.MSG_NODEICON))
}
m.OptionDefault(mdb.ICONS, m.Resource(kit.Select(ice.Info.NodeIcon, msg.Option(ice.MSG_NODEICON), msg.Append(mdb.ICONS))))
serve := strings.Split(UserHost(m), "://")[1]
pod = kit.Select(pod, msg.Option(ice.MSG_NODENAME), m.Option(ice.MSG_USERPOD) != "")
m.OptionDefault(TITLE, kit.Select(cmd, msg.Append(mdb.HELP), !m.IsEnglish())+" "+kit.Select(serve, pod))
RenderCmds(m, kit.Dict(msg.AppendSimple(), ctx.ARGS, kit.Simple(arg), ctx.DISPLAY, m.Option(ice.MSG_DISPLAY)))
}
} }
func RenderCmd(m *ice.Message, cmd string, arg ...ice.Any) { RenderPodCmd(m, "", cmd, arg...) } func RenderCmd(m *ice.Message, cmd string, arg ...ice.Any) { RenderPodCmd(m, "", cmd, arg...) }
func RenderVersion(m *ice.Message) string { func RenderVersion(m *ice.Message) string {
if ice.Info.Make.Hash == "" { ls := []string{ice.Info.Make.Versions()}
return "" if strings.Contains(ice.Info.Make.Domain, "debug=true") {
if m.Option(log.DEBUG) == ice.TRUE || m.R != nil && strings.Contains(m.R.URL.RawQuery, "debug=true") {
ls = append(ls, kit.Format("%d", time.Now().Unix()-kit.Time(ice.Info.Make.When)/int64(time.Second)))
}
} }
ls := []string{ice.Info.Make.Version, ice.Info.Make.Forword, ice.Info.Make.Hash[:6]} return "?" + kit.JoinQuery(kit.Simple(kit.Dict("_v", strings.Join(ls, "-"), ice.POD, m.Option(ice.MSG_USERPOD)))...)
if m.Option(log.DEBUG) == ice.TRUE || m.R != nil && strings.Contains(m.R.URL.RawQuery, "debug=true") {
ls = append(ls, kit.Format("%d", time.Now().Unix()-kit.Time(ice.Info.Make.When)/int64(time.Second)))
}
return "?_v=" + strings.Join(ls, "-")
} }
const ( const (
CHAT = "chat" PLAY = "play"
CHAT_POD = "/chat/pod/" SHOW = "show"
CHAT_CMD = "/chat/cmd/"
REQUIRE_SRC = "/require/src/"
REQUIRE_USR = "/require/usr/"
REQUIRE_MODULES = "/require/modules/"
VOLCANOS = "/volcanos/"
INTSHELL = "/intshell/"
CODE_GIT_SERVICE = "web.code.git.service" CHAT = "chat"
CODE_GIT_SEARCH = "web.code.git.search" WORD = "word"
CODE_GIT_STATUS = "web.code.git.status" VIMER = "vimer"
CODE_GIT_REPOS = "web.code.git.repos" XTERM = "xterm"
CODE_COMPILE = "web.code.compile" GRANT = "grant"
CODE_UPGRADE = "web.code.upgrade" OAUTH = "oauth"
CODE_PUBLISH = "web.code.publish" DESKTOP = "desktop"
CODE_VIMER = "web.code.vimer" MESSAGE = "message"
CODE_INNER = "web.code.inner"
CODE_XTERM = "web.code.xterm" AUTOGEN = "autogen"
WIKI_FEEL = "web.wiki.feel" BINPACK = "binpack"
WIKI_DRAW = "web.wiki.draw" COMPILE = "compile"
WIKI_WORD = "web.wiki.word" PUBLISH = "publish"
WIKI_PORTAL = "web.wiki.portal" VERSION = "version"
CHAT_PORTAL = "web.chat.portal" UPGRADE = "upgrade"
CHAT_HEADER = "web.chat.header" INSTALL = "install"
CHAT_IFRAME = "web.chat.iframe"
CHAT_FAVOR = "web.chat.favor" CODE_MYSQL_CLIENT = "web.code.mysql.client"
CHAT_FLOWS = "web.chat.flows" CODE_MYSQL_QUERY = "web.code.mysql.query"
TEAM_PLAN = "web.team.plan" CODE_GIT_SERVICE = "web.code.git.service"
CODE_GIT_SEARCH = "web.code.git.search"
CODE_GIT_STATUS = "web.code.git.status"
CODE_GIT_REPOS = "web.code.git.repos"
CODE_AUTOGEN = "web.code.autogen"
CODE_COMPILE = "web.code.compile"
CODE_PUBLISH = "web.code.publish"
CODE_UPGRADE = "web.code.upgrade"
CODE_VIMER = "web.code.vimer"
CODE_INNER = "web.code.inner"
CODE_XTERM = "web.code.xterm"
CODE_MOD = "web.code.mod"
WIKI_FEEL = "web.wiki.feel"
WIKI_DRAW = "web.wiki.draw"
WIKI_WORD = "web.wiki.word"
WIKI_PORTAL = "web.wiki.portal"
CHAT_OAUTH_CLIENT = "web.chat.oauth.client"
CHAT_WX_ACCESS = "web.chat.wx.access"
CHAT_WX_AGENT = "web.chat.wx.agent"
CHAT_WX_TEMPLATE = "web.chat.wx.template"
CHAT_WX_OCR = "web.chat.wx.ocr"
CHAT_MESSAGE = "web.chat.message"
CHAT_HEADER = "web.chat.header"
CHAT_IFRAME = "web.chat.iframe"
CHAT_FAVOR = "web.chat.favor"
CHAT_FLOWS = "web.chat.flows"
CHAT_GRANT = "web.chat.grant"
CHAT_POD = "web.chat.pod"
CHAT_CMD = "web.chat.cmd"
TEAM_PLAN = "web.team.plan"
TEAM_GONGANXITONG_USER = "web.team.gonganxitong.user"
TEAM_GONGANXITONG_CITY = "web.team.gonganxitong.city"
TEAM_GONGANXITONG_DOMAIN = "web.team.gonganxitong.domain"
) )
func MessageInsertJSON(m *ice.Message, zone, name, text string, arg ...string) {
MessageInsert(m, zone, kit.Simple(mdb.TYPE, html.TEXT, mdb.NAME, kit.Select(m.CommandKey(), name),
mdb.TEXT, text, ctx.DISPLAY, html.PLUGIN_JSON, arg)...)
}
func MessageInsert(m *ice.Message, zone string, arg ...string) {
m.Cmd(MESSAGE, mdb.INSERT, zone, tcp.DIRECT, tcp.RECV, arg)
}

View File

@ -11,36 +11,40 @@ import (
"shylinux.com/x/icebergs/base/mdb" "shylinux.com/x/icebergs/base/mdb"
"shylinux.com/x/icebergs/base/nfs" "shylinux.com/x/icebergs/base/nfs"
"shylinux.com/x/icebergs/base/tcp" "shylinux.com/x/icebergs/base/tcp"
"shylinux.com/x/icebergs/base/web/html"
kit "shylinux.com/x/toolkits" kit "shylinux.com/x/toolkits"
) )
func _route_push(m *ice.Message, space string, msg *ice.Message) *ice.Message { func _route_push(m *ice.Message, space string, msg *ice.Message) *ice.Message {
return msg.Table(func(index int, value ice.Maps, head []string) { return msg.Table(func(value ice.Maps, index int, head []string) {
value[SPACE], head = space, append(head, SPACE) value[SPACE], head = space, append(head, SPACE)
m.Push("", value, head) m.Push("", value, head)
}) })
} }
func _route_match(m *ice.Message, space string, cb func(ice.Maps, int, []ice.Maps)) { func _route_match(m *ice.Message, space string, cb func(ice.Maps, int, []ice.Maps)) {
reg, err := regexp.Compile(space) reg, err := regexp.Compile(space)
if m.Warn(err) { if m.WarnNotValid(err) {
return return
} }
list := []ice.Maps{} res := []ice.Maps{}
list := kit.Split(space)
m.Cmd("").Table(func(value ice.Maps) { m.Cmd("").Table(func(value ice.Maps) {
if value[mdb.STATUS] == OFFLINE { if value[mdb.STATUS] == OFFLINE {
} else if value[SPACE] == space { } else if value[SPACE] == space {
list = append(list, value) res = append(res, value)
} else if kit.IsIn(value[SPACE], list...) {
res = append(res, value)
} else if reg.MatchString(kit.Format("%s:%s=%s@%s", value[SPACE], value[mdb.TYPE], value[nfs.MODULE], value[nfs.VERSION])) { } else if reg.MatchString(kit.Format("%s:%s=%s@%s", value[SPACE], value[mdb.TYPE], value[nfs.MODULE], value[nfs.VERSION])) {
list = append(list, value) res = append(res, value)
} }
}) })
for i, item := range list { for i, item := range res {
cb(item, i, list) cb(item, i, res)
} }
} }
func _route_toast(m *ice.Message, space string, args ...string) { func _route_toast(m *ice.Message, space string, args ...string) {
GoToast(m, "", func(toast func(string, int, int)) (list []string) { GoToast(m, func(toast func(string, int, int)) (list []string) {
count, total := 0, 1 count, total := 0, 1
_route_match(m, space, func(value ice.Maps, i int, _list []ice.Maps) { _route_match(m, space, func(value ice.Maps, i int, _list []ice.Maps) {
count, total = i, len(_list) count, total = i, len(_list)
@ -65,7 +69,7 @@ const ROUTE = "route"
func init() { func init() {
Index.MergeCommands(ice.Commands{ Index.MergeCommands(ice.Commands{
ROUTE: {Name: "route space:text cmds:text auto spide cmds build travel prunes", Icon: "Podcasts.png", Help: "路由表", Actions: ice.MergeActions(ice.Actions{ ROUTE: {Name: "route space:text cmds:text auto build travel diagram prunes", Help: "路由表", Icon: "Shortcuts.png", Actions: ice.MergeActions(ice.Actions{
ice.MAIN: {Help: "首页", Hand: func(m *ice.Message, arg ...string) { ctx.ProcessField(m, CHAT_IFRAME, m.MergePod(""), arg...) }}, ice.MAIN: {Help: "首页", Hand: func(m *ice.Message, arg ...string) { ctx.ProcessField(m, CHAT_IFRAME, m.MergePod(""), arg...) }},
mdb.INPUTS: {Hand: func(m *ice.Message, arg ...string) { mdb.INPUTS: {Hand: func(m *ice.Message, arg ...string) {
switch mdb.HashInputs(m, arg); arg[0] { switch mdb.HashInputs(m, arg); arg[0] {
@ -76,43 +80,37 @@ func init() {
kit.For([]string{WORKER, SERVER}, func(key string) { push(kit.Format(":%s=", key)) }) kit.For([]string{WORKER, SERVER}, func(key string) { push(kit.Format(":%s=", key)) })
} }
}}, }},
"spide": {Help: "导图", Hand: func(m *ice.Message, arg ...string) {
ctx.DisplayStorySpide(m.Cmdy(""), nfs.DIR_ROOT, ice.Info.NodeName, mdb.FIELD, SPACE, lex.SPLIT, nfs.PT, ctx.ACTION, ice.MAIN)
}},
ctx.CMDS: {Name: "cmds space index* args", Help: "命令", Hand: func(m *ice.Message, arg ...string) { ctx.CMDS: {Name: "cmds space index* args", Help: "命令", Hand: func(m *ice.Message, arg ...string) {
_route_toast(m, m.Option(SPACE), append([]string{m.Option(ctx.INDEX)}, kit.Split(m.Option(ctx.ARGS))...)...) _route_toast(m, m.Option(SPACE), append([]string{m.Option(ctx.INDEX)}, kit.Split(m.Option(ctx.ARGS))...)...)
}}, }},
cli.BUILD: {Name: "build space", Help: "构建", Hand: func(m *ice.Message, arg ...string) { cli.BUILD: {Name: "build space", Help: "构建", Hand: func(m *ice.Message, arg ...string) {
_route_toast(m, m.Option(SPACE), m.PrefixKey(), "_build") m.Option(ice.MSG_TITLE, kit.Keys(m.Option(ice.MSG_USERPOD0), m.Option(ice.MSG_USERPOD), m.CommandKey()))
func() { defer ToastProcess(m)(); m.Sleep("3s") }() _route_toast(m, m.Option(SPACE), cli.RUNTIME, UPGRADE)
m.Cmdy("", "travel") m.SetAppend().Cmdy("", "travel")
}}, }},
"_build": {Hand: func(m *ice.Message, arg ...string) { "travel": {Help: "遍历", Icon: "bi bi-card-list", Hand: func(m *ice.Message, arg ...string) {
if _, err := nfs.DiskFile.StatFile(ice.SRC_MAIN_GO); err == nil && nfs.Exists(m, ".git") {
m.Cmdy(CODE_VIMER, "compile")
} else if ice.Info.NodeType == SERVER {
m.Cmdy(CODE_UPGRADE)
} else {
m.Cmdy(ice.EXIT, "1")
}
}},
"travel": {Help: "遍历", Hand: func(m *ice.Message, arg ...string) {
kit.For(kit.Split(m.OptionDefault(ice.MSG_FIELDS, mdb.Config(m, mdb.FIELD))), func(key string) { kit.For(kit.Split(m.OptionDefault(ice.MSG_FIELDS, mdb.Config(m, mdb.FIELD))), func(key string) {
switch key { switch key {
case mdb.TIME: case mdb.TIME:
m.Push(key, ice.Info.Make.Time) m.Push(key, ice.Info.Make.Time)
case mdb.TYPE:
m.Push(key, ice.Info.NodeType)
case nfs.MODULE: case nfs.MODULE:
m.Push(key, ice.Info.Make.Module) m.Push(key, ice.Info.Make.Module)
case nfs.VERSION: case nfs.VERSION:
m.Push(key, ice.Info.Make.Versions()) m.Push(key, ice.Info.Make.Versions())
case cli.COMMIT_TIME:
m.Push(key, ice.Info.Make.When)
case cli.COMPILE_TIME:
m.Push(key, ice.Info.Make.Time)
case cli.BOOT_TIME:
m.Push(key, m.Cmdx(cli.RUNTIME, "boot.time"))
case "md5": case "md5":
m.Push(key, ice.Info.Hash) m.Push(key, ice.Info.Hash)
case nfs.SIZE: case nfs.SIZE:
var stats runtime.MemStats var stats runtime.MemStats
runtime.ReadMemStats(&stats) runtime.ReadMemStats(&stats)
m.Push(key, kit.Format("%s/%s/%s", kit.FmtSize(int64(stats.Sys)), ice.Info.Size, m.Cmdx(nfs.DIR, nfs.SIZE))) m.Push(key, kit.Format("%s/%s/%s", ice.Info.Size, kit.FmtSize(int64(stats.Sys)), m.Cmdx(nfs.DIR, nfs.SIZE)))
case mdb.TYPE:
m.Push(key, ice.Info.NodeType)
case nfs.PATH: case nfs.PATH:
m.Push(key, kit.Path("")) m.Push(key, kit.Path(""))
case tcp.HOSTNAME: case tcp.HOSTNAME:
@ -125,12 +123,16 @@ func init() {
PushPodCmd(m, "", m.ActionKey()) PushPodCmd(m, "", m.ActionKey())
m.Table(func(value ice.Maps) { kit.If(value[SPACE], func() { mdb.HashCreate(m.Spawn(), kit.Simple(value)) }) }) m.Table(func(value ice.Maps) { kit.If(value[SPACE], func() { mdb.HashCreate(m.Spawn(), kit.Simple(value)) }) })
}}, }},
"diagram": {Help: "导图", Icon: "bi bi-diagram-3", Hand: func(m *ice.Message, arg ...string) {
ctx.DisplayStorySpide(m.Cmdy(""), nfs.DIR_ROOT, ice.Info.NodeName, mdb.FIELD, SPACE, lex.SPLIT, nfs.PT, ctx.ACTION, ice.MAIN)
}},
mdb.PRUNES: &ice.Action{Name: "prunes status=offline", Hand: func(m *ice.Message, arg ...string) { mdb.PRUNES: &ice.Action{Name: "prunes status=offline", Hand: func(m *ice.Message, arg ...string) {
m.Cmd("", func(value ice.Maps) { m.Cmd("", func(value ice.Maps) {
kit.If(value[mdb.STATUS] == OFFLINE, func() { mdb.HashRemove(m, SPACE, value[SPACE]) }) kit.If(value[mdb.STATUS] == OFFLINE, func() { mdb.HashRemove(m, SPACE, value[SPACE]) })
}) })
m.ProcessRefresh()
}}, }},
}, mdb.HashAction(mdb.SHORT, SPACE, mdb.FIELD, "time,space,type,module,version,md5,size,path,hostname", mdb.SORT, "type,space", mdb.ACTION, ice.MAIN)), Hand: func(m *ice.Message, arg ...string) { }, mdb.HashAction(mdb.SHORT, SPACE, mdb.FIELD, "time,space,type,module,version,commitTime,compileTime,bootTime,md5,size,path,hostname", mdb.SORT, "type,space", html.CHECKBOX, ice.TRUE, mdb.ACTION, ice.MAIN)), Hand: func(m *ice.Message, arg ...string) {
if len(arg) > 1 { if len(arg) > 1 {
_route_match(m, arg[0], func(value ice.Maps, i int, list []ice.Maps) { _route_match(m, arg[0], func(value ice.Maps, i int, list []ice.Maps) {
_route_push(m, value[SPACE], m.Cmd(SPACE, value[SPACE], arg[1:])) _route_push(m, value[SPACE], m.Cmd(SPACE, value[SPACE], arg[1:]))
@ -140,6 +142,7 @@ func init() {
} else { } else {
m.OptionFields("") m.OptionFields("")
list := m.CmdMap(SPACE, mdb.NAME) list := m.CmdMap(SPACE, mdb.NAME)
lists := m.CmdMap(DREAM, mdb.NAME)
mem, disk, stat := 0, 0, map[string]int{} mem, disk, stat := 0, 0, map[string]int{}
m.Table(func(value ice.Maps) { m.Table(func(value ice.Maps) {
disk += kit.Int(kit.Select("", kit.Split(value[nfs.SIZE], nfs.PS), 2)) disk += kit.Int(kit.Select("", kit.Split(value[nfs.SIZE], nfs.PS), 2))
@ -151,6 +154,11 @@ func init() {
m.Push(mdb.STATUS, OFFLINE) m.Push(mdb.STATUS, OFFLINE)
stat[OFFLINE]++ stat[OFFLINE]++
} }
if v, ok := lists[value[SPACE]]; ok {
m.Push(mdb.ICONS, v[mdb.ICONS])
} else {
m.Push(mdb.ICONS, "")
}
}).Sort("status,space", ice.STR_R, ice.STR).StatusTimeCount(stat, nfs.SIZE, kit.Format("%s/%s", kit.FmtSize(mem), kit.FmtSize(disk))).Options(ice.MSG_ACTION, "") }).Sort("status,space", ice.STR_R, ice.STR).StatusTimeCount(stat, nfs.SIZE, kit.Format("%s/%s", kit.FmtSize(mem), kit.FmtSize(disk))).Options(ice.MSG_ACTION, "")
} }
}}, }},

View File

@ -1,8 +1,10 @@
package web package web
import ( import (
"io/ioutil"
"net/http" "net/http"
"net/url" "net/url"
"os"
"path" "path"
"regexp" "regexp"
"runtime" "runtime"
@ -19,57 +21,76 @@ import (
"shylinux.com/x/icebergs/base/nfs" "shylinux.com/x/icebergs/base/nfs"
"shylinux.com/x/icebergs/base/ssh" "shylinux.com/x/icebergs/base/ssh"
"shylinux.com/x/icebergs/base/tcp" "shylinux.com/x/icebergs/base/tcp"
"shylinux.com/x/icebergs/base/web/html"
kit "shylinux.com/x/toolkits" kit "shylinux.com/x/toolkits"
"shylinux.com/x/toolkits/logs" "shylinux.com/x/toolkits/logs"
) )
func _serve_address(m *ice.Message) string { return Domain(tcp.LOCALHOST, m.Option(tcp.PORT)) } func _serve_address(m *ice.Message) string { return HostPort(m, tcp.LOCALHOST, m.Option(tcp.PORT)) }
func _serve_start(m *ice.Message) { func _serve_start(m *ice.Message) {
kit.If(m.Option(aaa.USERNAME), func() { aaa.UserRoot(m, m.Option(aaa.USERNICK), m.Option(aaa.USERNAME)) }) kit.If(m.Option(aaa.USERNAME), func() { aaa.UserRoot(m, "", m.Option(aaa.USERNAME), m.Option(aaa.USERNICK), m.Option(aaa.LANGUAGE)) })
kit.If(m.Option(tcp.PORT) == tcp.RANDOM, func() { m.Option(tcp.PORT, m.Cmdx(tcp.PORT, aaa.RIGHT)) }) kit.If(m.Option(tcp.PORT) == tcp.RANDOM, func() { m.Option(tcp.PORT, m.Cmdx(tcp.PORT, aaa.RIGHT)) })
kit.If(runtime.GOOS == cli.WINDOWS || m.Cmdx(cli.SYSTEM, "lsof", "-i", ":"+m.Option(tcp.PORT)) != "", func() { m.Go(func() {
m.Go(func() { m.Cmd(SPIDE, ice.OPS, _serve_address(m)+"/exit", ice.Maps{CLIENT_TIMEOUT: "300ms"}) }).Sleep300ms() m.Cmd(SPIDE, ice.OPS, _serve_address(m)+nfs.PS+ice.EXIT, ice.Maps{CLIENT_TIMEOUT: cli.TIME_30ms, ice.LOG_DISABLE: ice.TRUE})
}) }).Sleep(cli.TIME_1s)
cli.NodeInfo(m, kit.Select(ice.Info.Hostname, m.Option(tcp.NODENAME)), SERVER) cli.NodeInfo(m, kit.Select(kit.Split(ice.Info.Hostname, nfs.PT)[0], m.Option(tcp.NODENAME)), SERVER, mdb.Config(m, mdb.ICONS))
m.Start("", m.OptionSimple(tcp.HOST, tcp.PORT)...) kit.If(ice.HasVar(), func() { m.Cmd(nfs.SAVE, ice.VAR_LOG_ICE_PORT, m.Option(tcp.PORT)) })
kit.For(kit.Split(m.Option(ice.DEV)), func(dev string) { kit.For(kit.Split(m.Option(ice.DEV)), func(dev string) {
m.Sleep30ms(SPACE, tcp.DIAL, ice.DEV, dev, mdb.NAME, ice.Info.NodeName, m.OptionSimple(TOKEN)) if strings.HasPrefix(dev, HTTP) {
m.Cmd(SPIDE, mdb.CREATE, dev, ice.DEV, "", nfs.REPOS)
m.Cmd(SPIDE, mdb.CREATE, dev, "dev_ip", "", "dev_ip")
dev = ice.DEV
}
if msg := m.Cmd(SPIDE, dev); msg.Append(TOKEN) == "" {
if m.Option(TOKEN) != "" {
m.Cmd(SPACE, tcp.DIAL, ice.DEV, dev, TOKEN, m.Option(TOKEN))
} else {
m.Cmd(SPACE, tcp.DIAL, ice.DEV, dev)
}
}
}) })
m.Spawn(ice.Maps{TOKEN: ""}).Start("", m.OptionSimple(tcp.HOST, tcp.PORT)...)
if m.Cmd(tcp.HOST).Length() == 0 {
return
}
} }
func _serve_main(m *ice.Message, w http.ResponseWriter, r *http.Request) bool { func _serve_main(m *ice.Message, w http.ResponseWriter, r *http.Request) bool {
const ( const (
X_REAL_IP = "X-Real-Ip" X_REAL_IP = "X-Real-Ip"
X_REAL_PORT = "X-Real-Port" X_REAL_PORT = "X-Real-Port"
X_FORWARDED_FOR = "X-Forwarded-For" INDEX_MODULE = "Index-Module"
INDEX_MODULE = "Index-Module"
) )
if r.Header.Get(INDEX_MODULE) == "" { if r.Header.Get(INDEX_MODULE) == "" {
r.Header.Set(INDEX_MODULE, m.Prefix()) r.Header.Set(INDEX_MODULE, m.Prefix())
} else { } else {
return true return true
} }
func() {
defer InfoLock.Lock()()
Info.ServeMainCount++
}()
if ip := r.Header.Get(X_REAL_IP); ip != "" { if ip := r.Header.Get(X_REAL_IP); ip != "" {
if r.Header.Set(ice.MSG_USERIP, ip); r.Header.Get(X_REAL_PORT) != "" { if r.Header.Set(ice.MSG_USERIP, ip); r.Header.Get(X_REAL_PORT) != "" {
r.Header.Set(ice.MSG_USERADDR, ip+nfs.DF+r.Header.Get(X_REAL_PORT)) r.Header.Set(ice.MSG_USERADDR, ip+nfs.DF+r.Header.Get(X_REAL_PORT))
} }
} else if ip := r.Header.Get(X_FORWARDED_FOR); ip != "" { } else if ip := r.Header.Get(html.XForwardedFor); ip != "" {
r.Header.Set(ice.MSG_USERIP, kit.Split(ip)[0]) r.Header.Set(ice.MSG_USERIP, kit.Split(ip)[0])
} else if strings.HasPrefix(r.RemoteAddr, "[") { } else if strings.HasPrefix(r.RemoteAddr, "[") {
r.Header.Set(ice.MSG_USERIP, strings.Split(r.RemoteAddr, "]")[0][1:]) r.Header.Set(ice.MSG_USERIP, strings.Split(r.RemoteAddr, "]")[0][1:])
} else { } else {
r.Header.Set(ice.MSG_USERIP, strings.Split(r.RemoteAddr, nfs.DF)[0]) r.Header.Set(ice.MSG_USERIP, strings.Split(r.RemoteAddr, nfs.DF)[0])
} }
if !kit.HasPrefix(r.URL.String(), VOLCANOS, REQUIRE_MODULES, INTSHELL) { if !kit.HasPrefix(r.URL.String(), nfs.VOLCANOS, nfs.REQUIRE_MODULES, nfs.INTSHELL) {
r.Header.Set(ice.LOG_TRACEID, log.Traceid()) r.Header.Set(ice.LOG_TRACEID, log.Traceid(m))
m.Logs(r.Header.Get(ice.MSG_USERIP), r.Method, r.URL.String(), logs.TraceidMeta(r.Header.Get(ice.LOG_TRACEID))) m.Logs(r.Header.Get(ice.MSG_USERIP), r.Method, r.URL.String(), logs.TraceidMeta(r.Header.Get(ice.LOG_TRACEID)))
} }
if path.Join(r.URL.Path) == nfs.PS && strings.HasPrefix(r.UserAgent(), Mozilla) { if path.Join(r.URL.Path) == nfs.PS && strings.HasPrefix(r.UserAgent(), html.Mozilla) {
r.URL.Path = kit.Select(nfs.PS, mdb.Config(m, ice.MAIN)) r.URL.Path = kit.Select(nfs.PS, mdb.Config(m, ice.MAIN))
} }
if r.Method == http.MethodGet { if r.Method == http.MethodGet {
msg := m.Spawn(w, r).Options(ice.MSG_USERUA, r.UserAgent(), ice.LOG_TRACEID, r.Header.Get(ice.LOG_TRACEID), msg := m.Spawn(w, r).Options(ice.MSG_USERUA, r.UserAgent(), ice.LOG_TRACEID, r.Header.Get(ice.LOG_TRACEID), ParseLink(m, kit.Select(r.URL.String(), r.Referer())))
ParseLink(m, kit.Select(r.URL.String(), r.Referer())))
if path.Join(r.URL.Path) == nfs.PS { if path.Join(r.URL.Path) == nfs.PS {
msg.Options(ice.MSG_USERWEB, _serve_domain(msg))
if Render(RenderMain(msg), msg.Option(ice.MSG_OUTPUT), kit.List(msg.Optionv(ice.MSG_ARGS))...) { if Render(RenderMain(msg), msg.Option(ice.MSG_OUTPUT), kit.List(msg.Optionv(ice.MSG_ARGS))...) {
return false return false
} }
@ -80,80 +101,143 @@ func _serve_main(m *ice.Message, w http.ResponseWriter, r *http.Request) bool {
return true return true
} }
func _serve_static(msg *ice.Message, w http.ResponseWriter, r *http.Request) bool { func _serve_static(msg *ice.Message, w http.ResponseWriter, r *http.Request) bool {
if p := path.Join(kit.Select(ice.USR_VOLCANOS, ice.USR_INTSHELL, msg.IsCliUA()), r.URL.Path); nfs.Exists(msg, p) { // _serve_params(msg, r.Header.Get(html.Referer))
if strings.HasPrefix(r.URL.Path, "/.git/") {
return false
}
_serve_params(msg, r.URL.String())
ispod := msg.Option(ice.POD) != ""
if strings.HasPrefix(r.URL.Path, nfs.V) {
return Render(msg, ice.RENDER_DOWNLOAD, path.Join(ice.USR_VOLCANOS, strings.TrimPrefix(r.URL.Path, nfs.V)))
} else if kit.HasPrefix(r.URL.Path, nfs.P) {
if kit.Contains(r.URL.String(), "render=replace") {
return false
}
p := path.Join(strings.TrimPrefix(r.URL.Path, nfs.P))
if pp := path.Join(nfs.USR_LOCAL_WORK, msg.Option(ice.POD)); ispod && nfs.Exists(msg, pp) && !strings.HasPrefix(p, "require/") {
if kit.HasPrefix(p, "var/", "usr/local/") {
return false
}
if pp = path.Join(pp, p); nfs.Exists(msg, pp) {
return Render(msg, ice.RENDER_DOWNLOAD, pp)
} else if nfs.Exists(msg, p) {
return Render(msg, ice.RENDER_DOWNLOAD, p)
}
}
if kit.HasPrefix(p, ice.USR_ICEBERGS, ice.USR_ICONS) && nfs.Exists(msg, p) {
return Render(msg, ice.RENDER_DOWNLOAD, p)
}
if !ispod {
return (kit.HasPrefix(p, nfs.SRC) && nfs.Exists(msg, p)) && Render(msg, ice.RENDER_DOWNLOAD, p)
}
} else if kit.HasPrefix(r.URL.Path, nfs.M) {
p := nfs.USR_MODULES + strings.TrimPrefix(r.URL.Path, nfs.M)
return nfs.Exists(msg, p) && Render(msg, ice.RENDER_DOWNLOAD, p)
} else if kit.HasPrefix(path.Base(r.URL.Path), "MP_verify_") {
return Render(msg, ice.RENDER_DOWNLOAD, nfs.ETC+path.Base(r.URL.Path))
} else if p := path.Join(kit.Select(ice.USR_VOLCANOS, ice.USR_INTSHELL, msg.IsCliUA()), r.URL.Path); nfs.Exists(msg, p) {
return Render(msg, ice.RENDER_DOWNLOAD, p) return Render(msg, ice.RENDER_DOWNLOAD, p)
} else if p = path.Join(nfs.USR, r.URL.Path); kit.HasPrefix(r.URL.Path, nfs.VOLCANOS, nfs.INTSHELL) && nfs.Exists(msg, p) { } else if p = path.Join(nfs.USR, r.URL.Path); kit.HasPrefix(r.URL.Path, nfs.VOLCANOS, nfs.INTSHELL) && nfs.Exists(msg, p) {
return Render(msg, ice.RENDER_DOWNLOAD, p) return Render(msg, ice.RENDER_DOWNLOAD, p)
} else if p = strings.TrimPrefix(r.URL.Path, nfs.REQUIRE); kit.HasPrefix(r.URL.Path, ice.REQUIRE_SRC, nfs.REQUIRE+ice.USR_ICONS, nfs.REQUIRE+ice.USR_ICEBERGS) && nfs.Exists(msg, p) { }
ispod := kit.Contains(r.URL.String(), CHAT_POD, "pod=") || kit.Contains(r.Header.Get(Referer), CHAT_POD, "pod=") return false
p := ""
if p = strings.TrimPrefix(r.URL.Path, nfs.REQUIRE); kit.HasPrefix(r.URL.Path, nfs.REQUIRE_SRC, nfs.REQUIRE+ice.USR_ICONS, nfs.REQUIRE+ice.USR_ICEBERGS) && nfs.Exists(msg, p) {
return !ispod && Render(msg, ice.RENDER_DOWNLOAD, p) return !ispod && Render(msg, ice.RENDER_DOWNLOAD, p)
} else if p = path.Join(ice.USR_MODULES, strings.TrimPrefix(r.URL.Path, ice.REQUIRE_MODULES)); kit.HasPrefix(r.URL.Path, ice.REQUIRE_MODULES) && nfs.Exists(msg, p) { } else if p = path.Join(nfs.USR_MODULES, strings.TrimPrefix(r.URL.Path, nfs.REQUIRE_MODULES)); kit.HasPrefix(r.URL.Path, nfs.REQUIRE_MODULES) && nfs.Exists(msg, p) {
return Render(msg, ice.RENDER_DOWNLOAD, p) return Render(msg, ice.RENDER_DOWNLOAD, p)
} else { } else {
return false return false
} }
} }
func _serve_params(m *ice.Message, p string) {
if u, e := url.Parse(p); e == nil {
switch arg := strings.Split(strings.TrimPrefix(u.Path, nfs.PS), nfs.PS); arg[0] {
case CHAT:
kit.For(arg[1:], func(k, v string) { m.Option(k, v) })
case SHARE:
m.Option(arg[0], arg[1])
case "s":
m.Option(ice.POD, kit.Select("", arg, 1))
}
kit.For(u.Query(), func(k string, v []string) { m.Optionv(k, v) })
}
}
func _serve_handle(key string, cmd *ice.Command, m *ice.Message, w http.ResponseWriter, r *http.Request) { func _serve_handle(key string, cmd *ice.Command, m *ice.Message, w http.ResponseWriter, r *http.Request) {
debug := strings.Contains(r.URL.String(), "debug=true") || strings.Contains(r.Header.Get(Referer), "debug=true") debug := strings.Contains(r.URL.String(), "debug=true") || strings.Contains(r.Header.Get(html.Referer), "debug=true")
m.Option(ice.LOG_TRACEID, r.Header.Get(ice.LOG_TRACEID)) m.Options(ice.LOG_DEBUG, ice.FALSE, ice.LOG_TRACEID, r.Header.Get(ice.LOG_TRACEID))
_log := func(level string, arg ...ice.Any) *ice.Message { _log := func(level string, arg ...ice.Any) *ice.Message {
if debug || arg[0] == ice.MSG_CMDS { if debug || arg[0] == ice.MSG_CMDS {
return m.Logs(strings.Title(level), arg...) return m.Logs(strings.Title(level), arg...)
} }
return m return m
} }
_log("page", Referer, r.Header.Get(Referer)) kit.If(r.Header.Get(html.Referer), func(p string) { _log("page", html.Referer, p) })
if u, e := url.Parse(r.Header.Get(Referer)); e == nil { _serve_params(m, r.Header.Get(html.Referer))
add := func(k, v string) { _log(nfs.PATH, k, m.Option(k, v)) } _serve_params(m, r.URL.String())
switch arg := strings.Split(strings.TrimPrefix(u.Path, nfs.PS), nfs.PS); arg[0] {
case CHAT:
kit.For(arg[1:], func(k, v string) { add(k, v) })
case SHARE:
add(arg[0], arg[1])
}
kit.For(u.Query(), func(k string, v []string) { _log(ctx.ARGS, k, v).Optionv(k, v) })
}
kit.For(kit.ParseQuery(r.URL.RawQuery), func(k string, v []string) { m.Optionv(k, v) })
if r.Method == http.MethodGet && m.Option(ice.MSG_CMDS) != "" { if r.Method == http.MethodGet && m.Option(ice.MSG_CMDS) != "" {
_log(ctx.ARGS, ice.MSG_CMDS, m.Optionv(ice.MSG_CMDS)) _log(ctx.ARGS, ice.MSG_CMDS, m.Optionv(ice.MSG_CMDS))
} }
switch r.Header.Get(ContentType) { switch kit.Select("", kit.Split(r.Header.Get(html.ContentType)), 0) {
case ApplicationJSON: case html.ApplicationJSON:
kit.For(kit.UnMarshal(r.Body), func(k string, v ice.Any) { m.Optionv(k, v) }) buf, _ := ioutil.ReadAll(r.Body)
m.Option("request.data", string(buf))
kit.For(kit.UnMarshal(string(buf)), func(k string, v ice.Any) { m.Optionv(k, v) })
default: default:
r.ParseMultipartForm(kit.Int64(kit.Select("4096", r.Header.Get(ContentLength)))) r.ParseMultipartForm(kit.Int64(kit.Select("4096", r.Header.Get(html.ContentLength))))
kit.For(r.PostForm, func(k string, v []string) { _log(FORM, k, kit.Join(v, lex.SP)).Optionv(k, v) }) kit.For(r.PostForm, func(k string, v []string) { _log(FORM, k, kit.Join(v, lex.SP)).Optionv(k, v) })
} }
kit.For(r.Cookies(), func(k, v string) { m.Optionv(k, v) }) kit.For(r.Cookies(), func(k, v string) { m.Optionv(k, v) })
m.Options(ice.MSG_METHOD, r.Method, ice.MSG_COUNT, "0") m.Options(ice.MSG_METHOD, r.Method, ice.MSG_COUNT, "0")
m.Options(ice.MSG_REFERER, r.Header.Get(html.Referer))
m.Options(ice.MSG_USERWEB, _serve_domain(m), ice.MSG_USERPOD, m.Option(ice.POD)) m.Options(ice.MSG_USERWEB, _serve_domain(m), ice.MSG_USERPOD, m.Option(ice.POD))
m.Options(ice.MSG_USERUA, r.Header.Get(UserAgent), ice.MSG_USERIP, r.Header.Get(ice.MSG_USERIP)) m.Options(ice.MSG_USERUA, r.Header.Get(html.UserAgent), ice.MSG_USERIP, r.Header.Get(ice.MSG_USERIP))
m.Options(ice.MSG_SESSID, kit.Select(m.Option(ice.MSG_SESSID), m.Option(CookieName(m.Option(ice.MSG_USERWEB))))) m.Options(ice.MSG_SESSID, kit.Select(m.Option(ice.MSG_SESSID), m.Option(CookieName(m.Option(ice.MSG_USERWEB)))))
kit.If(m.Optionv(ice.MSG_CMDS) == nil, func() { kit.If(m.Optionv(ice.MSG_CMDS) == nil, func() {
kit.If(strings.TrimPrefix(r.URL.Path, key), func(p string) { m.Optionv(ice.MSG_CMDS, strings.Split(p, nfs.PS)) }) kit.If(strings.TrimPrefix(r.URL.Path, key), func(p string) { m.Optionv(ice.MSG_CMDS, strings.Split(p, nfs.PS)) })
}) })
UserHost(m)
for k, v := range m.R.Header {
// m.Info("what %v %v", k, v)
kit.If(strings.HasPrefix(k, "Wechatpay"), func() { m.Option(k, v) })
}
m.W.Header().Add(strings.ReplaceAll(ice.LOG_TRACEID, ".", "-"), m.Option(ice.LOG_TRACEID)) m.W.Header().Add(strings.ReplaceAll(ice.LOG_TRACEID, ".", "-"), m.Option(ice.LOG_TRACEID))
defer func() { Render(m, m.Option(ice.MSG_OUTPUT), kit.List(m.Optionv(ice.MSG_ARGS))...) }() defer func() { Render(m, m.Option(ice.MSG_OUTPUT), kit.List(m.Optionv(ice.MSG_ARGS))...) }()
if cmds, ok := _serve_auth(m, key, kit.Simple(m.Optionv(ice.MSG_CMDS)), w, r); ok { if cmds, ok := _serve_auth(m, key, kit.Simple(m.Optionv(ice.MSG_CMDS)), w, r); ok {
m.Option(ice.MSG_COST, "")
defer func() { defer func() {
kit.If(m.Option(ice.MSG_STATUS) == "", func() { m.StatusTimeCount() }) kit.If(m.Option(ice.MSG_STATUS) == "", func() { m.StatusTimeCount() })
m.Cost(kit.Format("%s: %s %v", r.Method, r.URL.String(), m.FormatSize())) m.Cost(kit.Format("%s: %s %v", r.Method, r.URL.String(), m.FormatSize())).Options(ice.MSG_COST, m.FormatCost())
}() }()
m.Option(ice.MSG_OPTS, kit.Simple(m.Optionv(ice.MSG_OPTION), func(k string) bool { return !strings.HasPrefix(k, ice.MSG_SESSID) })) m.Option(ice.MSG_OPTS, kit.Simple(m.Optionv(ice.MSG_OPTION), func(k string) bool { return !strings.HasPrefix(k, ice.MSG_SESSID) }))
if m.Detailv(m.PrefixKey(), cmds); len(cmds) > 1 && cmds[0] == ctx.ACTION { if m.Detailv(m.ShortKey(), cmds); len(cmds) > 1 && cmds[0] == ctx.ACTION && cmds[1] != ctx.ACTION {
if !kit.IsIn(cmds[1], aaa.LOGIN, ctx.RUN, ctx.COMMAND) && m.Warn(r.Method == http.MethodGet, ice.ErrNotAllow) { if !kit.IsIn(cmds[1], aaa.LOGIN, ctx.RUN, ctx.COMMAND) && m.WarnNotAllow(r.Method == http.MethodGet) {
return return
} }
m.ActionHand(cmd, key, cmds[1], cmds[2:]...) m.ActionHand(cmd, key, cmds[1], cmds[2:]...)
} else { } else {
m.CmdHand(cmd, key, cmds...) m.CmdHand(cmd, key, cmds...)
} }
func() {
defer InfoLock.Lock()()
Info.Commands[kit.Select(kit.Select("", cmds, 0), m.Option(ice.MSG_INDEX))]++
switch r.Method {
case http.MethodGet:
Info.ServeGetCount++
case http.MethodPut:
Info.ServePutCount++
case http.MethodPost:
Info.ServePostCount++
case http.MethodDelete:
Info.ServeDeleteCount++
}
}()
} }
} }
func _serve_domain(m *ice.Message) string { func _serve_domain(m *ice.Message) string {
return kit.GetValid( return kit.GetValid(
func() string { return kit.Select("", m.R.Header.Get(Referer), m.R.Method == http.MethodPost) }, func() string { return kit.Select("", m.R.Header.Get(html.Referer), m.R.Method == http.MethodPost) },
func() string { return m.R.Header.Get("X-Host") }, func() string { return m.R.Header.Get(html.XHost) },
func() string { return ice.Info.Domain }, func() string { return ice.Info.Domain },
func() string { func() string {
if b, e := regexp.MatchString("^[0-9.]+$", m.R.Host); b && e == nil { if b, e := regexp.MatchString("^[0-9.]+$", m.R.Host); b && e == nil {
@ -164,24 +248,27 @@ func _serve_domain(m *ice.Message) string {
) )
} }
func _serve_auth(m *ice.Message, key string, cmds []string, w http.ResponseWriter, r *http.Request) ([]string, bool) { func _serve_auth(m *ice.Message, key string, cmds []string, w http.ResponseWriter, r *http.Request) ([]string, bool) {
kit.If(len(cmds) > 0, func() { cmds = append(kit.Split(cmds[0], ","), cmds[1:]...) })
kit.If(!aaa.IsTechOrRoot(m), func() { m.Option("user_uid", "") })
if r.URL.Path == PP(SPACE) { if r.URL.Path == PP(SPACE) {
aaa.SessCheck(m, m.Option(ice.MSG_SESSID))
return cmds, true return cmds, true
} }
defer func() { m.Options(ice.MSG_CMDS, "", ice.MSG_SESSID, "") }() defer func() { m.Options(ice.MSG_CMDS, "") }()
if aaa.SessCheck(m, m.Option(ice.MSG_SESSID)); m.Option(ice.MSG_USERNAME) == "" { if strings.Contains(m.Option(ice.MSG_SESSID), " ") {
ls := kit.Simple(mdb.Cache(m, m.Option(ice.MSG_USERIP), func() ice.Any { m.Cmdy(kit.Split(m.Option(ice.MSG_SESSID)))
if IsLocalHost(m) { } else if aaa.SessCheck(m, m.Option(ice.MSG_SESSID)); m.Option(ice.MSG_USERNAME) == "" {
aaa.UserRoot(m) if ls := kit.Simple(mdb.Cache(m, m.Option(ice.MSG_USERIP), func() ice.Any {
return kit.Simple(m.Time(), m.OptionSplit(ice.MSG_USERNICK, ice.MSG_USERNAME, ice.MSG_USERROLE)) if !IsLocalHost(m) {
return nil
} }
return nil aaa.UserRoot(m)
})) return kit.Simple(m.Time(), m.OptionSplit(ice.MSG_USERNICK, ice.MSG_USERNAME, ice.MSG_USERROLE))
if len(ls) > 0 { })); len(ls) > 0 {
m.Auth(aaa.USERNICK, m.Option(ice.MSG_USERNICK, ls[1]), aaa.USERNAME, m.Option(ice.MSG_USERNAME, ls[2]), aaa.USERROLE, m.Option(ice.MSG_USERROLE, ls[3]), CACHE, ls[0]) aaa.SessAuth(m, kit.Dict(aaa.USERNICK, ls[1], aaa.USERNAME, ls[2], aaa.USERROLE, ls[3]), CACHE, ls[0])
} }
} }
m.Cmd(COUNT, mdb.CREATE, aaa.IP, m.Option(ice.MSG_USERIP), m.Option(ice.MSG_USERUA), kit.Dict(ice.LOG_DISABLE, ice.TRUE)) Count(m, aaa.IP, m.Option(ice.MSG_USERIP), m.Option(ice.MSG_USERUA))
m.Cmd(COUNT, mdb.CREATE, m.R.Method, m.R.URL.Path, kit.Join(kit.Simple(m.Optionv(ice.MSG_CMDS)), " "), kit.Dict(ice.LOG_DISABLE, ice.TRUE))
return cmds, aaa.Right(m, key, cmds) return cmds, aaa.Right(m, key, cmds)
} }
@ -191,45 +278,71 @@ const (
HTTP = "http" HTTP = "http"
HTTPS = "https" HTTPS = "https"
DOMAIN = "domain" DOMAIN = "domain"
ORIGIN = "origin"
FORM = "form" FORM = "form"
BODY = "body" BODY = "body"
HOME = "home"
SERVE_START = "serve.start" SERVE_START = "serve.start"
PROXY_CONF = "proxyConf"
PROXY_PATH = "usr/local/daemon/10000/"
PROXY_CMDS = "./sbin/nginx"
) )
const SERVE = "serve" const SERVE = "serve"
func init() { func init() {
Index.MergeCommands(ice.Commands{P(ice.EXIT): {Hand: func(m *ice.Message, arg ...string) { m.Cmd(ice.EXIT) }}, Index.MergeCommands(ice.Commands{P(ice.EXIT): {Hand: func(m *ice.Message, arg ...string) { m.Cmd(ice.EXIT) }},
SERVE: {Name: "serve name auto main host dark system", Help: "服务器", Actions: ice.MergeActions(ice.Actions{ SERVE: {Name: "serve port auto main host system", Help: "服务器", Actions: ice.MergeActions(ice.Actions{
ice.CTX_INIT: {Hand: func(m *ice.Message, arg ...string) { cli.NodeInfo(m, ice.Info.Pathname, WORKER) }}, ice.MAIN: {Name: "main index space", Help: "首页", Hand: func(m *ice.Message, arg ...string) {
ice.MAIN: {Name: "main index", Help: "首页", Hand: func(m *ice.Message, arg ...string) {
if m.Option(ctx.INDEX) == "" { if m.Option(ctx.INDEX) == "" {
mdb.Config(m, ice.MAIN, "") mdb.Config(m, ice.MAIN, "")
} else if m.Option(SPACE) == "" {
mdb.Config(m, ice.MAIN, C(m.Option(ctx.INDEX)))
} else { } else {
mdb.Config(m, ice.MAIN, CHAT_CMD+m.Option(ctx.INDEX)+nfs.PS) mdb.Config(m, ice.MAIN, S(m.Option(SPACE))+C(m.Option(ctx.INDEX)))
} }
}}, }},
log.TRACEID: {Help: "日志", Hand: func(m *ice.Message, arg ...string) { mdb.ICONS: {Hand: func(m *ice.Message, arg ...string) { mdb.Config(m, mdb.ICONS, arg[0]) }},
kit.If(len(arg) > 0, func() { ice.Info.Traceid = arg[0] }) tcp.HOST: {Help: "公网", Hand: func(m *ice.Message, arg ...string) { m.Echo(kit.Formats(PublicIP(m))) }},
m.Echo(ice.Info.Traceid)
}},
tcp.HOST: {Help: "公网", Hand: func(m *ice.Message, arg ...string) { m.Echo(kit.Formats(PublicIP(m))) }},
cli.DARK: {Help: "主题", Hand: func(m *ice.Message, arg ...string) {
kit.If(tcp.IsLocalHost(m, m.Option(ice.MSG_USERIP)), func() {
m.Cmd(cli.SYSTEM, "osascript", "-e", `tell app "System Events" to tell appearance preferences to set dark mode to not dark mode`)
})
}},
cli.SYSTEM: {Help: "系统", Hand: func(m *ice.Message, arg ...string) { cli.Opens(m, "System Settings.app") }}, cli.SYSTEM: {Help: "系统", Hand: func(m *ice.Message, arg ...string) { cli.Opens(m, "System Settings.app") }},
cli.START: {Name: "start dev proto host port=9020 nodename username usernick", Hand: func(m *ice.Message, arg ...string) { _serve_start(m) }}, cli.START: {Name: "start dev proto host port=9020 nodename username usernick", Hand: func(m *ice.Message, arg ...string) {
SERVE_START: {Hand: func(m *ice.Message, arg ...string) { if runtime.GOOS == cli.LINUX {
m.Go(func() { m.Cmd(nfs.SAVE, nfs.ETC_LOCAL_SH, m.Spawn(ice.Maps{cli.PWD: kit.Path(""), aaa.USER: kit.UserName(), ctx.ARGS: kit.JoinCmds(arg...)}).Template("local.sh")+lex.NL)
ssh.PrintQRCode(m, tcp.PublishLocalhost(m, _serve_address(m))) m.GoSleep("3s", func() { m.Cmd("", PROXY_CONF, kit.Select(ice.Info.NodeName, m.Option("nodename"))) })
cli.Opens(m, mdb.Config(m, cli.OPEN)) } else if runtime.GOOS == cli.WINDOWS {
}) m.Cmd(cli.SYSTEM, cli.ECHO, "-ne", kit.Format("\033]0;%s %s serve start %s\007",
path.Base(kit.Path("")), strings.TrimPrefix(kit.Path(os.Args[0]), kit.Path("")+nfs.PS), kit.JoinCmdArgs(arg...)))
}
_serve_start(m)
}}, }},
}, gdb.EventsAction(SERVE_START), mdb.HashAction(mdb.SHORT, mdb.NAME, mdb.FIELD, "time,status,name,proto,host,port"), mdb.ClearOnExitHashAction()), Hand: func(m *ice.Message, arg ...string) { SERVE_START: {Hand: func(m *ice.Message, arg ...string) {
mdb.HashSelect(m, arg...).Options(ice.MSG_ACTION, "").StatusTimeCount(kit.Dict(ice.MAIN, mdb.Config(m, ice.MAIN))) kit.If(m.Option(ice.DEMO) == ice.TRUE, func() { m.Cmd(CHAT_HEADER, ice.DEMO) })
kit.If(os.Getenv(cli.TERM), func() { m.Go(func() { ssh.PrintQRCode(m, tcp.PublishLocalhost(m, _serve_address(m))) }) })
m.Cmd(SPIDE, mdb.CREATE, HostPort(m, tcp.LOCALHOST, m.Option(tcp.PORT)), ice.OPS, ice.SRC_MAIN_ICO, nfs.REPOS, "")
m.Cmds(SPIDE).Table(func(value ice.Maps) {
kit.If(value[CLIENT_NAME] != ice.OPS && value[TOKEN] != "", func() {
m.Cmd(SPACE, tcp.DIAL, ice.DEV, value[CLIENT_NAME], TOKEN, value[TOKEN], mdb.TYPE, SERVER)
})
})
Count(m, m.ActionKey(), m.Option(tcp.PORT))
if cb, ok := m.Optionv(SERVE_START).(func()); ok {
cb()
}
ice.Info.Important = ice.HasVar()
}},
PROXY_CONF: {Name: "proxyConf name* port host path", Hand: func(m *ice.Message, arg ...string) {
if dir := m.OptionDefault(nfs.PATH, PROXY_PATH, tcp.HOST, "127.0.0.1", tcp.PORT, tcp.PORT_9020); nfs.Exists(m, dir) {
for _, p := range []string{"upstream.conf"} {
m.Cmd(nfs.SAVE, kit.Format("%s/conf/portal/%s/%s", dir, m.Option(mdb.NAME), p), m.Template(p)+lex.NL)
}
for _, p := range []string{"server.conf", "location.conf"} {
m.Cmd(nfs.DEFS, kit.Format("%s/conf/portal/%s/%s", dir, m.Option(mdb.NAME), p), m.Template(p)+lex.NL)
}
m.Cmd(cli.SYSTEM, cli.SUDO, kit.Path(dir, "sbin/nginx"), "-p", kit.Path(dir), "-s", "reload")
}
}},
}, gdb.EventsAction(SERVE_START), mdb.HashAction(
mdb.SHORT, tcp.PORT, mdb.FIELD, "time,status,port,host,proto"), mdb.ClearOnExitHashAction()), Hand: func(m *ice.Message, arg ...string) {
mdb.HashSelect(m, arg...).Action().StatusTimeCount(kit.Dict(ice.MAIN, mdb.Config(m, ice.MAIN)))
}}, }},
}) })
ice.AddMergeAction(func(c *ice.Context, key string, cmd *ice.Command, sub string, action *ice.Action) { ice.AddMergeAction(func(c *ice.Context, key string, cmd *ice.Command, sub string, action *ice.Action) {
@ -248,24 +361,76 @@ func init() {
} }
}) })
} }
func Domain(host, port string) string { return kit.Format("%s://%s:%s", HTTP, host, port) }
func ServeCmdAction() ice.Actions {
return ice.MergeActions(ice.Actions{
nfs.PS: {Hand: func(m *ice.Message, arg ...string) { RenderCmd(m, "", arg) }},
})
}
func IsLocalHost(m *ice.Message) bool {
return (m.R == nil || m.R.Header.Get(html.XForwardedFor) == "") && tcp.IsLocalHost(m, m.Option(ice.MSG_USERIP))
}
func ParseURL(m *ice.Message, p string) []string {
if u, e := url.Parse(p); e == nil {
arg := strings.Split(strings.TrimPrefix(u.Path, nfs.PS), nfs.PS)
for i := 0; i < len(arg); i += 2 {
switch arg[i] {
case "s":
m.Option(ice.POD, kit.Select("", arg, i+1))
case "c":
m.Option(ice.CMD, kit.Select("", arg, i+1))
}
}
kit.For(u.Query(), func(k string, v []string) { m.Optionv(k, v) })
return kit.Split(u.Fragment, ":")
}
return []string{}
}
func ParseUA(m *ice.Message) (res []string) {
res = append(res, aaa.USERROLE, m.Option(ice.MSG_USERROLE))
res = append(res, aaa.USERNAME, m.Option(ice.MSG_USERNAME))
res = append(res, aaa.USERNICK, m.Option(ice.MSG_USERNICK))
res = append(res, aaa.AVATAR, m.Option(ice.MSG_AVATAR))
res = append(res, cli.DAEMON, m.Option(ice.MSG_DAEMON))
for _, p := range html.AgentList {
if strings.Contains(m.Option(ice.MSG_USERUA), p) {
res = append(res, mdb.ICONS, kit.Select(agentIcons[p], m.Option(mdb.ICONS)), AGENT, p)
break
}
}
for _, p := range html.SystemList {
if strings.Contains(m.Option(ice.MSG_USERUA), p) {
res = append(res, cli.SYSTEM, p)
break
}
}
return append(res, aaa.IP, m.Option(ice.MSG_USERIP), aaa.UA, m.Option(ice.MSG_USERUA))
}
func ProxyDomain(m *ice.Message, name string) (domain string) {
p := path.Join(PROXY_PATH, "conf/portal", name, "server.conf")
if !nfs.Exists(m, p) {
domain := UserWeb(m).Hostname()
if domain == "localhost" {
return ""
}
if p = path.Join(PROXY_PATH, "conf/server", kit.Keys(name, kit.Slice(kit.Split(UserWeb(m).Hostname(), "."), -2))) + ".conf"; !nfs.Exists(m, p) {
return ""
}
}
m.Cmd(nfs.CAT, p, func(ls []string) { kit.If(ls[0] == "server_name", func() { domain = ls[1] }) })
return kit.Select("", "https://"+domain, domain != "")
}
func Script(m *ice.Message, str string, arg ...ice.Any) string { func Script(m *ice.Message, str string, arg ...ice.Any) string {
return ice.Render(m, ice.RENDER_SCRIPT, kit.Format(str, arg...)) return ice.Render(m, ice.RENDER_SCRIPT, kit.Format(str, arg...))
} }
func ChatCmdPath(m *ice.Message, arg ...string) string { func ChatCmdPath(m *ice.Message, arg ...string) string {
if p := m.Option(ice.MSG_USERPOD); p != "" { return m.MergePodCmd("", kit.Select(m.ShortKey(), path.Join(arg...)))
return path.Join(CHAT_POD, p, "/cmd/", kit.Select(m.PrefixKey(), path.Join(arg...)))
}
return path.Join(CHAT_CMD, kit.Select(m.PrefixKey(), path.Join(arg...)))
} }
func RequireFile(m *ice.Message, file string) string { func RequireFile(m *ice.Message, file string) string {
if strings.HasPrefix(file, nfs.PS) || strings.HasPrefix(file, ice.HTTP) { if strings.HasPrefix(file, nfs.PS) || strings.HasPrefix(file, ice.HTTP) || strings.Contains(file, "://") {
return file return file
} else if file != "" { } else if file != "" {
return nfs.REQUIRE + file return nfs.P + file
} }
return "" return ""
} }
func IsLocalHost(m *ice.Message) bool {
return (m.R == nil || m.R.Header.Get("X-Forwarded-For") == "") && tcp.IsLocalHost(m, m.Option(ice.MSG_USERIP))
}

View File

@ -18,9 +18,9 @@ import (
func _share_link(m *ice.Message, p string, arg ...ice.Any) string { func _share_link(m *ice.Message, p string, arg ...ice.Any) string {
if strings.HasPrefix(p, ice.USR_PUBLISH) { if strings.HasPrefix(p, ice.USR_PUBLISH) {
return tcp.PublishLocalhost(m, MergeLink(m, strings.TrimPrefix(p, ice.USR), arg...)) return kit.MergeURL2(UserHost(m), strings.TrimPrefix(p, ice.USR), arg...)
} }
return tcp.PublishLocalhost(m, MergeLink(m, kit.Select("", PP(SHARE, LOCAL), !strings.HasPrefix(p, nfs.PS) && !strings.HasPrefix(p, HTTP))+p, arg...)) return kit.MergeURL2(UserHost(m), kit.Select("", PP(SHARE, LOCAL), !strings.HasPrefix(p, nfs.PS) && !strings.HasPrefix(p, HTTP))+p, arg...)
} }
func _share_cache(m *ice.Message, arg ...string) { func _share_cache(m *ice.Message, arg ...string) {
if m.Cmdy(CACHE, arg[0]); m.Length() == 0 { if m.Cmdy(CACHE, arg[0]); m.Length() == 0 {
@ -39,12 +39,12 @@ func _share_cache(m *ice.Message, arg ...string) {
} }
} }
func _share_proxy(m *ice.Message) { func _share_proxy(m *ice.Message) {
if m.Warn(m.Option(SHARE) == "", ice.ErrNotValid) { if m.WarnNotValid(m.Option(SHARE) == "") {
return return
} }
msg := m.Cmd(SHARE, m.Option(SHARE)) msg := m.Cmd(SHARE, m.Option(SHARE))
defer m.Cmd(SHARE, mdb.REMOVE, mdb.HASH, m.Option(SHARE)) defer m.Cmd(SHARE, mdb.REMOVE, mdb.HASH, m.Option(SHARE))
if m.Warn(msg.Append(mdb.TEXT) == "", ice.ErrNotValid) { if m.WarnNotValid(msg.Append(mdb.TEXT) == "") {
return return
} }
p := path.Join(ice.VAR_PROXY, msg.Append(mdb.TEXT), msg.Append(mdb.NAME)) p := path.Join(ice.VAR_PROXY, msg.Append(mdb.TEXT), msg.Append(mdb.NAME))
@ -60,39 +60,43 @@ const (
STORM = "storm" STORM = "storm"
FIELD = "field" FIELD = "field"
LOCAL = "local"
PROXY = "proxy" PROXY = "proxy"
TOAST = "toast" LOCAL = "local"
SHARE_LOCAL = "/share/local/"
SHARE_CACHE = "/share/cache/" SHARE_CACHE = "/share/cache/"
SHARE_LOCAL = "/share/local/"
) )
const SHARE = "share" const SHARE = "share"
func init() { func init() {
Index.MergeCommands(ice.Commands{ Index.MergeCommands(ice.Commands{
SHARE: {Name: "share hash auto login", Help: "共享链", Actions: ice.MergeActions(ice.Actions{ SHARE: {Name: "share hash auto login", Help: "共享链", Icon: "Freeform.png", Role: aaa.VOID, Actions: ice.MergeActions(ice.Actions{
mdb.CREATE: {Name: "create type name text", Hand: func(m *ice.Message, arg ...string) { mdb.CREATE: {Name: "create type name text space", Hand: func(m *ice.Message, arg ...string) {
kit.If(m.Option(mdb.TYPE) == LOGIN, func() { arg = append(arg, mdb.TEXT, tcp.PublishLocalhost(m, m.Option(mdb.TEXT))) }) kit.If(m.Option(mdb.TYPE) == LOGIN && m.Option(mdb.TEXT) == "", func() { arg = append(arg, mdb.TEXT, tcp.PublishLocalhost(m, m.Option(ice.MSG_USERWEB))) })
mdb.HashCreate(m, arg, SPACE, m.Option(ice.MSG_USERPOD), aaa.USERNICK, m.Option(ice.MSG_USERNICK), aaa.USERNAME, m.Option(ice.MSG_USERNAME), aaa.USERROLE, m.Option(ice.MSG_USERROLE)) mdb.HashCreate(m, m.OptionSimple("type,name,text,space"), arg, aaa.USERNICK, m.Option(ice.MSG_USERNICK), aaa.USERNAME, m.Option(ice.MSG_USERNAME), aaa.USERROLE, m.Option(ice.MSG_USERROLE))
m.Option(mdb.LINK, _share_link(m, P(SHARE, m.Result()))) m.Option(mdb.LINK, tcp.PublishLocalhost(m, m.MergeLink(P(SHARE, m.Result()))))
Count(m, "", m.Option(mdb.TYPE))
}}, }},
LOGIN: {Help: "登录", Hand: func(m *ice.Message, arg ...string) { LOGIN: {Help: "登录", Hand: func(m *ice.Message, arg ...string) {
m.EchoQRCode(m.Cmd(SHARE, mdb.CREATE, mdb.TYPE, LOGIN).Option(mdb.LINK)).ProcessInner() m.EchoQRCode(m.Cmd(SHARE, mdb.CREATE, mdb.TYPE, LOGIN).Option(mdb.LINK)).ProcessInner()
}}, }},
OPEN: {Hand: func(m *ice.Message, arg ...string) {
m.ProcessOpen(m.MergeLink(P(SHARE, m.Option(mdb.HASH))))
}},
ctx.COMMAND: {Hand: func(m *ice.Message, arg ...string) { ctx.COMMAND: {Hand: func(m *ice.Message, arg ...string) {
if msg := mdb.HashSelect(m.Spawn(), m.Option(SHARE)); !IsNotValidFieldShare(m, msg) { if msg := mdb.HashSelects(m.Spawn(), m.Option(SHARE)); !IsNotValidFieldShare(m, msg) {
m.Cmdy(ctx.COMMAND, msg.Append(mdb.NAME)) m.Cmdy(Space(m, msg.Append(SPACE)), ctx.COMMAND, msg.Append(mdb.NAME), kit.Dict(ice.MSG_USERPOD, msg.Append(SPACE)))
} }
}}, }},
ctx.RUN: {Hand: func(m *ice.Message, arg ...string) { ctx.RUN: {Hand: func(m *ice.Message, arg ...string) {
if msg := mdb.HashSelect(m.Spawn(), m.Option(SHARE)); !IsNotValidFieldShare(m, msg) { if msg := mdb.HashSelects(m.Spawn(), m.Option(SHARE)); !IsNotValidFieldShare(m, msg) {
aaa.SessAuth(m, kit.Dict(msg.AppendSimple(aaa.USERNICK, aaa.USERNAME, aaa.USERROLE))) aaa.SessAuth(m, kit.Dict(msg.AppendSimple(aaa.USERNICK, aaa.USERNAME, aaa.USERROLE)))
m.Cmdy(Space(m, msg.Append(SPACE)), msg.Append(mdb.NAME), arg[1:]) // m.Cmdy(Space(m, msg.Append(SPACE)), msg.Append(mdb.NAME), kit.UnMarshal(msg.Append(mdb.TEXT)), arg[1:], kit.Dict(ice.MSG_USERPOD, msg.Append(SPACE)))
m.Cmdy(Space(m, msg.Append(SPACE)), msg.Append(mdb.NAME), arg[1:], kit.Dict(ice.MSG_USERPOD, msg.Append(SPACE)))
} }
}}, }},
nfs.PS: {Hand: func(m *ice.Message, arg ...string) { nfs.PS: {Hand: func(m *ice.Message, arg ...string) {
if m.Warn(len(arg) == 0 || arg[0] == "", ice.ErrNotValid, SHARE) { if m.WarnNotValid(len(arg) == 0 || arg[0] == "", SHARE) {
return return
} }
msg := m.Cmd(SHARE, m.Option(SHARE, arg[0])) msg := m.Cmd(SHARE, m.Option(SHARE, arg[0]))
@ -102,36 +106,48 @@ func init() {
} }
switch msg.Append(mdb.TYPE) { switch msg.Append(mdb.TYPE) {
case LOGIN: case LOGIN:
m.RenderRedirect(msg.Append(mdb.TEXT), ice.MSG_SESSID, aaa.SessCreate(m, msg.Append(aaa.USERNAME))) u := kit.ParseURL(m.Option(ice.MSG_USERHOST))
m.RenderRedirect(kit.MergeURL(msg.Append(mdb.TEXT), ice.MSG_SESSID, aaa.SessCreate(m, msg.Append(aaa.USERNAME))))
break
if u.Scheme == ice.HTTP {
m.RenderRedirect(kit.MergeURL(msg.Append(mdb.TEXT), ice.MSG_SESSID, aaa.SessCreate(m, msg.Append(aaa.USERNAME))))
} else {
RenderCookie(m, aaa.SessCreate(m, msg.Append(aaa.USERNAME)))
m.RenderRedirect(msg.Append(mdb.TEXT))
}
case STORM:
RenderCookie(m, aaa.SessCreate(m, msg.Append(aaa.USERNAME)))
m.RenderRedirect(m.MergeLink(kit.Select(nfs.PS, msg.Append(mdb.TEXT)), msg.AppendSimple(RIVER, STORM)))
case FIELD: case FIELD:
RenderPodCmd(m, msg.Append(SPACE), msg.Append(mdb.NAME), kit.UnMarshal(msg.Append(mdb.TEXT))) if msg.Append(mdb.NAME) == "web.chat.grant" {
RenderPodCmd(m, "", msg.Append(mdb.NAME), kit.UnMarshal(msg.Append(mdb.TEXT)))
} else {
RenderPodCmd(m, msg.Append(SPACE), msg.Append(mdb.NAME), kit.UnMarshal(msg.Append(mdb.TEXT)))
}
case DOWNLOAD: case DOWNLOAD:
m.RenderDownload(msg.Append(mdb.TEXT)) m.RenderDownload(msg.Append(mdb.TEXT))
default: default:
RenderMain(m) RenderMain(m)
} }
}}, }},
}, aaa.WhiteAction(), mdb.HashAction(mdb.FIELD, "time,hash,type,name,text,usernick,username,userrole", mdb.EXPIRE, mdb.DAYS)), Hand: func(m *ice.Message, arg ...string) { }, mdb.HashAction(mdb.FIELD, "time,hash,type,name,text,space,usernick,username,userrole", mdb.EXPIRE, mdb.DAYS)), Hand: func(m *ice.Message, arg ...string) {
if kit.IsIn(m.Option(ice.MSG_USERROLE), aaa.ROOT, aaa.TECH) || len(arg) > 0 && arg[0] != "" { if aaa.IsTechOrRoot(m) || len(arg) > 0 && arg[0] != "" {
mdb.HashSelect(m, arg...) mdb.HashSelect(m, arg...).PushAction(OPEN, mdb.REMOVE)
} }
}}, }},
PP(SHARE, PROXY): {Hand: func(m *ice.Message, arg ...string) { _share_proxy(m) }},
PP(SHARE, CACHE): {Hand: func(m *ice.Message, arg ...string) { _share_cache(m, arg...) }}, PP(SHARE, CACHE): {Hand: func(m *ice.Message, arg ...string) { _share_cache(m, arg...) }},
PP(SHARE, LOCAL): {Hand: func(m *ice.Message, arg ...string) { ShareLocalFile(m, arg...) }}, PP(SHARE, LOCAL): {Hand: func(m *ice.Message, arg ...string) { ShareLocalFile(m, arg...) }},
PP(SHARE, PROXY): {Hand: func(m *ice.Message, arg ...string) { _share_proxy(m) }},
PP(SHARE, TOAST): {Hand: func(m *ice.Message, arg ...string) {
m.Options(ice.LOG_DISABLE, ice.TRUE).Cmdy(SPACE, arg[0], kit.UnMarshal(m.Option(ice.ARG)))
}},
}) })
} }
func IsNotValidShare(m *ice.Message, time string) bool { func IsNotValidShare(m *ice.Message, time string) bool {
return m.Warn(time < m.Time(), ice.ErrNotValid, m.Option(SHARE), time, m.Time(), logs.FileLineMeta(2)) return m.WarnNotValid(time < m.Time(), ice.ErrNotValid, m.Option(SHARE), time, m.Time(), logs.FileLineMeta(2))
} }
func IsNotValidFieldShare(m *ice.Message, msg *ice.Message) bool { func IsNotValidFieldShare(m *ice.Message, msg *ice.Message) bool {
if m.Warn(IsNotValidShare(m, msg.Append(mdb.TIME)), kit.Format("共享超时, 请联系 %s(%s), 重新分享 %s %s %s", msg.Append(aaa.USERNICK), msg.Append(aaa.USERNAME), msg.Append(mdb.TYPE), msg.Append(mdb.NAME), msg.Append(mdb.TEXT))) { if m.Warn(IsNotValidShare(m, msg.Append(mdb.TIME)), kit.Format("共享超时, 请联系 %s(%s), 重新分享 %s %s %s", msg.Append(aaa.USERNICK), msg.Append(aaa.USERNAME), msg.Append(mdb.TYPE), msg.Append(mdb.NAME), msg.Append(mdb.TEXT))) {
return true return true
} }
if m.Warn(msg.Append(mdb.NAME) == "") { if m.WarnNotValid(msg.Append(mdb.NAME) == "") {
return true return true
} }
return false return false
@ -139,9 +155,9 @@ func IsNotValidFieldShare(m *ice.Message, msg *ice.Message) bool {
func SharePath(m *ice.Message, p string) string { func SharePath(m *ice.Message, p string) string {
kit.If(!kit.HasPrefix(p, nfs.PS, ice.HTTP), func() { kit.If(!kit.HasPrefix(p, nfs.PS, ice.HTTP), func() {
if kit.HasPrefix(p, nfs.SRC, nfs.USR) && !kit.HasPrefix(p, nfs.USR_LOCAL) { if kit.HasPrefix(p, nfs.SRC, nfs.USR) && !kit.HasPrefix(p, nfs.USR_LOCAL) {
p = kit.MergeURL(path.Join(nfs.REQUIRE, p), ice.POD, m.Option(ice.MSG_USERPOD)) p = m.MergeLink(path.Join(nfs.P, p), ice.POD, m.Option(ice.MSG_USERPOD))
} else { } else {
p = kit.MergeURL(path.Join(SHARE_LOCAL, p), ice.POD, m.Option(ice.MSG_USERPOD)) p = m.MergeLink(path.Join(SHARE_LOCAL, p), ice.POD, m.Option(ice.MSG_USERPOD))
} }
}) })
return p return p
@ -150,24 +166,54 @@ func ShareLocalFile(m *ice.Message, arg ...string) {
p := path.Join(arg...) p := path.Join(arg...)
switch ls := strings.Split(p, nfs.PS); ls[0] { switch ls := strings.Split(p, nfs.PS); ls[0] {
case ice.ETC, ice.VAR: case ice.ETC, ice.VAR:
if m.Warn(m.Option(ice.MSG_USERROLE) == aaa.VOID, ice.ErrNotRight, p) { if m.WarnNotRight(m.Option(ice.MSG_USERROLE) == aaa.VOID, p) {
return return
} }
default: default:
if m.Option(ice.POD) == "" && !aaa.Right(m, ls) { if m.Option(ice.MSG_USERNAME) != "" && strings.HasPrefix(p, nfs.USR_LOCAL_IMAGE+m.Option(ice.MSG_USERNAME)) {
} else if m.Option(ice.POD) == "" && !aaa.Right(m, ls) {
return
} else {
if m.Option(ice.POD) != "" && !strings.Contains(p, "/src/") && !strings.HasPrefix(p, "src/") {
if strings.HasPrefix(p, "usr/local/storage/") {
if m.Cmd(SPACE, "20240903-operation", "web.team.storage.file", aaa.RIGHT, ls[3:]).IsErr() {
return
}
} else if m.WarnNotRight(m.Cmdx(SPACE, m.Option(ice.POD), aaa.ROLE, aaa.RIGHT, aaa.VOID, p) != ice.OK) {
return
}
}
}
}
if m.Option(ice.POD) != "" && nfs.Exists(m, path.Join(ice.USR_LOCAL_WORK, m.Option(ice.POD))) {
if pp := kit.Path(ice.USR_LOCAL_WORK, m.Option(ice.POD), p); nfs.Exists(m, pp) {
m.RenderDownload(pp)
return
} else if nfs.Exists(m, p) {
m.RenderDownload(p)
return return
} }
} }
if m.Option(ice.POD) == "" { if m.Option(ice.POD) == "" || (kit.HasPrefix(p, ice.USR_ICONS, ice.USR_VOLCANOS, ice.USR_ICEBERGS, ice.USR_INTSHELL) && nfs.Exists(m, p)) {
m.RenderDownload(p) m.RenderDownload(p)
} else if pp := kit.Path(ice.USR_LOCAL_WORK, m.Option(ice.POD), p); nfs.Exists(m, pp) { } else if pp := kit.Path(ice.USR_LOCAL_WORK, m.Option(ice.POD), p); nfs.Exists(m, pp) {
m.RenderDownload(pp) m.RenderDownload(pp)
} else if pp := kit.Path(ice.USR_LOCAL_WORK, m.Option(ice.POD)); nfs.Exists(m, pp) { } else if pp := ProxyUpload(m, m.Option(ice.POD), p); nfs.Exists(m, pp) {
m.RenderDownload(p) m.RenderDownload(pp)
} else { } else {
m.RenderDownload(ProxyUpload(m, m.Option(ice.POD), p)) m.RenderDownload(p)
} }
} }
func ShareLocal(m *ice.Message, p string) string {
if kit.HasPrefix(p, nfs.PS, HTTP) {
return p
}
return m.MergeLink(PP(SHARE, LOCAL, p))
}
func ShareField(m *ice.Message, cmd string, arg ...ice.Any) *ice.Message {
return m.EchoQRCode(tcp.PublishLocalhost(m, m.MergeLink(P(SHARE, AdminCmd(m, SHARE, mdb.CREATE, mdb.TYPE, FIELD, mdb.NAME, kit.Select(m.ShortKey(), cmd), mdb.TEXT, kit.Format(kit.Simple(arg...)), SPACE, m.Option(ice.MSG_USERPOD)).Result()))))
}
func ProxyUpload(m *ice.Message, pod string, p string) string { func ProxyUpload(m *ice.Message, pod string, p string) string {
pp := path.Join(ice.VAR_PROXY, pod, p) pp := path.Join(ice.VAR_PROXY, pod, p)
size, cache := int64(0), time.Now().Add(-time.Hour*24) size, cache := int64(0), time.Now().Add(-time.Hour*24)
@ -176,16 +222,14 @@ func ProxyUpload(m *ice.Message, pod string, p string) string {
} else if s, e := file.StatFile(p); e == nil { } else if s, e := file.StatFile(p); e == nil {
size, cache = s.Size(), s.ModTime() size, cache = s.Size(), s.ModTime()
} }
kit.If(p == ice.BIN_ICE_BIN, func() { m.Option(ice.MSG_USERROLE, aaa.TECH) }) if m.Cmdv(SPACE, pod, mdb.TYPE) == ORIGIN {
share := m.Cmdx(SHARE, mdb.CREATE, mdb.TYPE, PROXY, mdb.NAME, p, mdb.TEXT, pod) m.Cmd(SPIDE, pod, SPIDE_SAVE, pp, "/p/"+p)
defer m.Cmd(SHARE, mdb.REMOVE, mdb.HASH, share) } else {
url := tcp.PublishLocalhost(m, MergeLink(m, PP(SHARE, PROXY), SHARE, share)) kit.If(p == ice.BIN_ICE_BIN, func() { m.Option(ice.MSG_USERROLE, aaa.TECH) })
m.Cmd(SPACE, pod, SPIDE, PROXY, URL, url, nfs.SIZE, size, CACHE, cache.Format(ice.MOD_TIME), UPLOAD, mdb.AT+p) share := m.Cmdx(SHARE, mdb.CREATE, mdb.TYPE, PROXY, mdb.NAME, p, mdb.TEXT, pod)
defer m.Cmd(SHARE, mdb.REMOVE, mdb.HASH, share)
url := tcp.PublishLocalhost(m, m.MergeLink(PP(SHARE, PROXY), SHARE, share))
m.Cmd(SPACE, pod, SPIDE, PROXY, URL, url, nfs.SIZE, size, CACHE, cache.Format(ice.MOD_TIME), UPLOAD, mdb.AT+p, kit.Dict(ice.MSG_USERROLE, aaa.TECH))
}
return kit.Select(p, pp, file.ExistsFile(pp)) return kit.Select(p, pp, file.ExistsFile(pp))
} }
func ShareLocal(m *ice.Message, p string) string {
if kit.HasPrefix(p, nfs.PS, HTTP) {
return p
}
return MergeLink(m, "/share/local/"+p)
}

View File

@ -1,8 +1,11 @@
package web package web
import ( import (
"io"
"math/rand" "math/rand"
"net" "net"
"path"
"runtime"
"strings" "strings"
"sync" "sync"
"time" "time"
@ -13,7 +16,6 @@ import (
"shylinux.com/x/icebergs/base/ctx" "shylinux.com/x/icebergs/base/ctx"
"shylinux.com/x/icebergs/base/gdb" "shylinux.com/x/icebergs/base/gdb"
"shylinux.com/x/icebergs/base/lex" "shylinux.com/x/icebergs/base/lex"
"shylinux.com/x/icebergs/base/log"
"shylinux.com/x/icebergs/base/mdb" "shylinux.com/x/icebergs/base/mdb"
"shylinux.com/x/icebergs/base/nfs" "shylinux.com/x/icebergs/base/nfs"
"shylinux.com/x/icebergs/base/ssh" "shylinux.com/x/icebergs/base/ssh"
@ -21,64 +23,119 @@ import (
"shylinux.com/x/icebergs/base/web/html" "shylinux.com/x/icebergs/base/web/html"
"shylinux.com/x/icebergs/misc/websocket" "shylinux.com/x/icebergs/misc/websocket"
kit "shylinux.com/x/toolkits" kit "shylinux.com/x/toolkits"
"shylinux.com/x/toolkits/task"
) )
var Info = struct {
ServeMainCount int
ServeGetCount int
ServePutCount int
ServePostCount int
ServeDeleteCount int
SpaceCmdCount int
SpaceReadCount int
SpaceReadByte int
SpaceWriteCount int
SpaceWriteByte int
Commands map[string]int
}{
Commands: map[string]int{},
}
var InfoLock = &task.Lock{}
func _space_qrcode(m *ice.Message, dev string) { func _space_qrcode(m *ice.Message, dev string) {
ssh.PrintQRCode(m, m.Cmdv(SPACE, dev, cli.PWD, mdb.LINK)) ssh.PrintQRCode(m, m.Cmdv(SPACE, dev, cli.PWD, mdb.LINK))
} }
func _space_dial(m *ice.Message, dev, name string, arg ...string) { func _space_dial(m *ice.Message, dev, name string, arg ...string) {
u := kit.ParseURL(kit.MergeURL2(strings.Replace(m.Cmdv(SPIDE, dev, CLIENT_ORIGIN), HTTP, "ws", 1), PP(SPACE), mdb.TYPE, ice.Info.NodeType, mdb.NAME, name, msg := m.Cmd(SPIDE, dev)
nfs.MODULE, ice.Info.Make.Module, nfs.VERSION, ice.Info.Make.Versions(), arg)) origin := msg.Append(CLIENT_ORIGIN)
args := kit.SimpleKV("type,name,host,port", u.Scheme, dev, u.Hostname(), u := kit.ParseURL(kit.MergeURL2(strings.Replace(origin, HTTP, "ws", 1), PP(SPACE), mdb.TYPE, ice.Info.NodeType, mdb.NAME, name, TOKEN, msg.Append(TOKEN), mdb.ICONS, ice.Info.NodeIcon,
kit.Select(kit.Select("443", "80", u.Scheme == "ws"), u.Port())) ice.MAIN, ice.Info.NodeMain, mdb.TIME, ice.Info.Make.Time, nfs.MODULE, ice.Info.Make.Module, nfs.VERSION, ice.Info.Make.Versions(), cli.GOOS, runtime.GOOS, cli.GOARCH, runtime.GOARCH, arg))
args := kit.SimpleKV("type,name,host,port", u.Scheme, dev, u.Hostname(), kit.Select(kit.Select(tcp.PORT_443, tcp.PORT_80, u.Scheme == "ws"), u.Port()))
gdb.Go(m, func() { gdb.Go(m, func() {
once := sync.Once{} once := sync.Once{}
redial := kit.Dict(mdb.Configv(m, REDIAL)) redial := kit.Dict(mdb.Configv(m, REDIAL))
a, b, c := kit.Int(redial["a"]), kit.Int(redial["b"]), kit.Int(redial["c"]) a, b, _c := kit.Int(redial["a"]), kit.Int(redial["b"]), kit.Int(redial["c"])
for i := 1; i < c; i++ { for i := 1; i < _c; i++ {
next := time.Duration(rand.Intn(a*(i+1))+b*i) * time.Millisecond next := time.Duration(rand.Intn(a*i*i)+b*(i+1)) * time.Millisecond
m.Cmd(tcp.CLIENT, tcp.DIAL, args, func(c net.Conn) { m.Cmd(tcp.CLIENT, tcp.DIAL, args, func(c net.Conn) {
if c, e := websocket.NewClient(c, u); !m.Warn(e, tcp.DIAL, dev, SPACE, u.String()) { if c, e := websocket.NewClient(c, u); !m.WarnNotValid(e, tcp.DIAL, dev, SPACE, u.String()) {
defer mdb.HashCreateDeferRemove(m, kit.SimpleKV("", MASTER, dev, u.Host), kit.Dict(mdb.TARGET, c))() mdb.HashCreate(m, kit.SimpleKV("", ORIGIN, dev, origin), kit.Dict(mdb.TARGET, c))
defer mdb.HashRemove(m, mdb.HASH, dev)
kit.If(ice.Info.Colors, func() { once.Do(func() { m.Go(func() { _space_qrcode(m, dev) }) }) }) kit.If(ice.Info.Colors, func() { once.Do(func() { m.Go(func() { _space_qrcode(m, dev) }) }) })
_space_handle(m.Spawn(), true, dev, c) _space_handle(m.Spawn(), true, dev, c)
i = 0 i = 0
} }
}).Cost(mdb.COUNT, i, mdb.NEXT, next, tcp.DIAL, dev, LINK, u.String()).Sleep(next) }).Cost(mdb.COUNT, i, mdb.NEXT, next, tcp.DIAL, dev, LINK, u.String()).Sleep(next)
if mdb.HashSelect(m.Spawn(), name).Append(mdb.STATUS) == cli.STOP {
break
}
} }
}, kit.Join(kit.Simple(SPACE, name), lex.SP)) }, kit.JoinWord(SPACE, dev))
} }
func _space_fork(m *ice.Message) { func _space_fork(m *ice.Message) {
addr := kit.Select(m.R.RemoteAddr, m.R.Header.Get(ice.MSG_USERADDR)) addr := kit.Select(m.R.RemoteAddr, m.R.Header.Get(ice.MSG_USERADDR))
text := strings.ReplaceAll(kit.Select(addr, m.Option(mdb.TEXT)), "%2F", nfs.PS) text := strings.ReplaceAll(kit.Select(addr, m.Option(mdb.TEXT)), "%2F", nfs.PS)
name := kit.ReplaceAll(kit.Select(addr, m.Option(mdb.NAME)), "[", "_", "]", "_", nfs.DF, "_", nfs.PT, "_") name := SpaceName(kit.Select(addr, m.Option(mdb.NAME)))
if kit.IsIn(m.Option(mdb.TYPE), PORTAL) && m.Option(mdb.NAME) != html.CHROME || mdb.HashSelect(m.Spawn(), name).Length() > 0 || if m.OptionDefault(mdb.TYPE, SERVER) == WORKER && (!nfs.Exists(m, path.Join(ice.USR_LOCAL_WORK, name)) || !tcp.IsLocalHost(m, m.Option(ice.MSG_USERIP))) {
!(IsLocalHost(m) || m.Option(TOKEN) != "" && m.Cmdv(TOKEN, m.Option(TOKEN), mdb.TIME) > m.Time()) { m.Option(mdb.TYPE, SERVER)
name, text = kit.Hashs(name), kit.Select(addr, m.Option(mdb.NAME), m.Option(mdb.TEXT))
} }
if m.Option(mdb.TYPE) == WORKER { if kit.IsIn(m.Option(mdb.TYPE), PORTAL, aaa.LOGIN) && len(name) == 32 && kit.IsIn(mdb.HashSelects(m.Spawn(), name).Append(aaa.IP), "", m.Option(ice.MSG_USERIP)) {
if p := nfs.USR_LOCAL_WORK + m.Option(mdb.NAME); nfs.Exists(m, p) {
text = p } else if kit.IsIn(m.Option(mdb.TYPE), SERVER) && IsLocalHost(m) {
} else if kit.IsIn(m.Option(mdb.TYPE), WORKER) && IsLocalHost(m) {
text = nfs.USR_LOCAL_WORK + name
} else {
name, text = kit.Hashs(name), kit.Select(addr, m.Option(mdb.TEXT))
}
safe := false
if m.Option(ice.MSG_USERNAME, ""); kit.IsIn(m.Option(mdb.TYPE), WORKER, PORTAL) {
if tcp.IsLocalHost(m, m.Option(ice.MSG_USERIP)) {
aaa.SessAuth(m, kit.Dict(m.Cmd(aaa.USER, m.Option(ice.MSG_USERNAME, ice.Info.Username)).AppendSimple()))
}
} else if m.Option(TOKEN) != "" {
if msg := m.Cmd(TOKEN, m.Option(TOKEN)); msg.Append(mdb.TIME) > m.Time() && kit.IsIn(msg.Append(mdb.TYPE), SERVER, SPIDE) {
aaa.SessAuth(m, kit.Dict(m.Cmd(aaa.USER, m.Option(ice.MSG_USERNAME, msg.Append(mdb.NAME))).AppendSimple()))
name = SpaceName(kit.Select(name, msg.Append(mdb.TEXT)))
// kit.If(ProxyDomain(m.Spawn(kit.Dict(ice.MSG_USERROLE, aaa.TECH)), name), func(p string) { text = p })
kit.If(ProxyDomain(m, name), func(p string) { text = p })
safe = aaa.IsTechOrRoot(m)
} }
} }
args := kit.Simple(mdb.TYPE, kit.Select(WORKER, m.Option(mdb.TYPE)), mdb.NAME, name, mdb.TEXT, text, m.OptionSimple(nfs.MODULE, nfs.VERSION, cli.DAEMON)) args := kit.Simple(mdb.TYPE, m.Option(mdb.TYPE), mdb.NAME, name, mdb.TEXT, text, m.OptionSimple(mdb.ICONS, mdb.TIME, nfs.MODULE, nfs.VERSION, cli.DAEMON, "main"))
args = append(args, aaa.UA, m.Option(ice.MSG_USERUA), aaa.IP, m.Option(ice.MSG_USERIP)) args = append(args, aaa.USERNICK, m.Option(ice.MSG_USERNICK), aaa.USERNAME, m.Option(ice.MSG_USERNAME), aaa.USERROLE, m.Option(ice.MSG_USERROLE))
if c, e := websocket.Upgrade(m.W, m.R); !m.Warn(e) { args = append(args, cli.SYSTEM, m.Option(cli.GOOS))
args = append(args, ParseUA(m)...)
if c, e := websocket.Upgrade(m.W, m.R); !m.WarnNotValid(e) {
gdb.Go(m, func() { gdb.Go(m, func() {
defer mdb.HashCreateDeferRemove(m, args, kit.Dict(mdb.TARGET, c))() defer mdb.HashCreateDeferRemove(m, args, kit.Dict(mdb.TARGET, c))()
switch m.Option(mdb.TYPE) { switch m.Option(mdb.TYPE) {
case WORKER:
defer gdb.EventDeferEvent(m, DREAM_OPEN, args)(DREAM_CLOSE, args)
case PORTAL:
m.Go(func() { m.Cmd(SPACE, name, cli.PWD, name) })
case LOGIN: case LOGIN:
if m.Option(ice.MSG_SESSID) != "" && m.Option(ice.MSG_USERNAME) != "" { if m.Option(ice.MSG_SESSID) != "" && m.Option(ice.MSG_USERNAME) != "" {
m.Cmd(SPACE, name, ice.MSG_SESSID, m.Option(ice.MSG_SESSID)) m.Cmd(SPACE, name, ice.MSG_SESSID, m.Option(ice.MSG_SESSID))
} }
gdb.Event(m, SPACE_LOGIN, args) gdb.Event(m, SPACE_LOGIN, args)
defer gdb.Event(m, SPACE_LOGIN_CLOSE, args)
case PORTAL:
gdb.EventDeferEvent(m, PORTAL_OPEN, args)
m.Go(func() { m.Cmd(SPACE, name, cli.PWD, name) })
case WORKER:
defer gdb.EventDeferEvent(m, DREAM_OPEN, args)(DREAM_CLOSE, args)
safe = true
m.Go(func() {
SpacePwd(m, name, kit.Path(""))
// SpaceEvent(m, OPS_DREAM_OPEN, name, args...)
})
case SERVER:
defer gdb.EventDeferEvent(m, SPACE_OPEN, args)(SPACE_CLOSE, args)
m.Go(func() {
SpacePwd(m, name, "")
SpaceEvent(m.Spawn(ice.MSG_USERROLE, aaa.TECH), OPS_SERVER_OPEN, name, args...)
})
} }
_space_handle(m, false, name, c) _space_handle(m.Spawn(), safe, name, c)
}, kit.Join(kit.Simple(SPACE, name), lex.SP)) }, kit.JoinWord(SPACE, name))
} }
} }
func _space_handle(m *ice.Message, safe bool, name string, c *websocket.Conn) { func _space_handle(m *ice.Message, safe bool, name string, c *websocket.Conn) {
@ -89,25 +146,55 @@ func _space_handle(m *ice.Message, safe bool, name string, c *websocket.Conn) {
if e != nil { if e != nil {
break break
} }
func() {
defer InfoLock.Lock()()
Info.SpaceReadCount++
Info.SpaceReadByte += len(b)
}()
msg := m.Spawn(b) msg := m.Spawn(b)
if safe { // 下行权限 if safe && msg.Option(ice.MSG_UNSAFE) != ice.TRUE { // 下行权限
msg.OptionDefault(ice.MSG_USERROLE, aaa.UserRole(msg, msg.Option(ice.MSG_USERNAME))) if !aaa.IsTechOrRoot(msg) && msg.Option(ice.MSG_HANDLE) != ice.TRUE {
msg.Option(ice.MSG_USERROLE, kit.Select(msg.Option(ice.MSG_USERROLE), aaa.UserRole(msg, msg.Option(ice.MSG_USERNAME))))
}
// kit.If(kit.IsIn(msg.Option(ice.MSG_USERROLE), "", aaa.VOID), func() { msg.Option(ice.MSG_USERROLE, aaa.UserRole(msg, msg.Option(ice.MSG_USERNAME))) })
} else { // 上行权限 } else { // 上行权限
msg.Option(ice.MSG_UNSAFE, ice.TRUE)
kit.If(msg.Option(ice.MSG_USERROLE), func() { msg.Option(ice.MSG_USERROLE, aaa.VOID) }) kit.If(msg.Option(ice.MSG_USERROLE), func() { msg.Option(ice.MSG_USERROLE, aaa.VOID) })
} }
source, target := kit.Simple(msg.Optionv(ice.MSG_SOURCE), name), kit.Simple(msg.Optionv(ice.MSG_TARGET)) source, target := kit.Simple(msg.Optionv(ice.MSG_SOURCE), name), kit.Simple(msg.Optionv(ice.MSG_TARGET))
msg.Log(tcp.RECV, "%v->%v %v %v", source, target, msg.Detailv(), msg.FormatsMeta(nil)) msg.Log(kit.Select(tcp.RECV, tcp.ECHO, msg.Option(ice.MSG_HANDLE) == ice.TRUE), "%d %v->%v %v %v", len(b), source, target, msg.Detailv(), msg.FormatMeta())
if next := msg.Option(ice.MSG_TARGET); next == "" || len(target) == 0 { if next := msg.Option(ice.MSG_TARGET); next == "" || len(target) == 0 {
m.Go(func() { _space_exec(msg, source, target, c) }, strings.Join(kit.Simple(SPACE, name, msg.Detailv()), lex.SP)) msg.Go(func() {
} else { if k := kit.Keys(msg.Option(ice.MSG_USERPOD), "_token"); msg.Option(k) != "" {
m.Warn(!mdb.HashSelectDetail(m, next, func(value ice.Map) { aaa.SessCheck(msg, msg.Option(k))
switch c := value[mdb.TARGET].(type) {
case (*websocket.Conn): // 转发报文
_space_echo(msg, source, target, c)
case ice.Handler: // 接收响应
m.Go(func() { c(msg) })
} }
}), ice.ErrNotFound, next) msg.Option(ice.MSG_OPTS, kit.Simple(msg.Optionv(ice.MSG_OPTION), func(k string) bool { return !strings.HasPrefix(k, ice.MSG_SESSID) }))
_space_exec(msg, name, source, target, c)
}, strings.Join(kit.Simple(SPACE, name, msg.Detailv()), lex.SP))
} else {
for i := 0; i < 5; i++ {
if !m.WarnNotFoundSpace(!mdb.HashSelectDetail(m, next, func(value ice.Map) {
switch c := value[mdb.TARGET].(type) {
case (*websocket.Conn): // 转发报文
kit.If(value[mdb.TYPE] == ORIGIN && msg.Option(ice.MSG_HANDLE) == ice.FALSE, func() {
msg.Optionv(ice.MSG_USERWEB, kit.Simple(value[mdb.TEXT], msg.Optionv(ice.MSG_USERWEB)))
msg.Optionv(ice.MSG_USERPOD, kit.Simple(kit.Keys(target[1:]), msg.Optionv(ice.MSG_USERPOD)))
})
_space_echo(msg, source, target, c)
case ice.Handler: // 接收响应
msg.Go(func() { c(msg) })
}
}), SPACE, next) {
break
}
if kit.HasPrefixList(msg.Detailv(), "toast") {
break
}
if msg.Option("space.noecho") == "true" {
break
}
m.Sleep3s()
}
} }
} }
} }
@ -122,108 +209,192 @@ func _space_domain(m *ice.Message) (link string) {
return "" return ""
}, },
func() string { return tcp.PublishLocalhost(m, m.Option(ice.MSG_USERWEB)) }, func() string { return tcp.PublishLocalhost(m, m.Option(ice.MSG_USERWEB)) },
func() string { return Domain(m.Cmdv(tcp.HOST, aaa.IP), m.Cmdv(SERVE, tcp.PORT)) }) func() string { return HostPort(m, m.Cmdv(tcp.HOST, aaa.IP), m.Cmdv(SERVE, tcp.PORT)) },
)
} }
func _space_exec(m *ice.Message, source, target []string, c *websocket.Conn) { func _space_exec(m *ice.Message, name string, source, target []string, c *websocket.Conn) {
switch kit.Select(cli.PWD, m.Detailv(), 0) { m.Option(ice.MSG_HANDLE, ice.TRUE)
switch kit.Select("", m.Detailv(), 0) {
case "":
m.Warn(true, ice.ErrNotValid)
return
case cli.PWD: case cli.PWD:
m.Push(mdb.LINK, m.MergePod(kit.Select("", source, -1))) m.Push(mdb.LINK, m.MergePod(kit.Select("", source, -1)))
if m.Option(cli.SYSTEM) == "" {
m.Optionv(ice.MSG_OPTION, []string{})
break
}
args := m.OptionSimple(mdb.ICONS, mdb.TIME, nfs.MODULE, nfs.VERSION, AGENT, cli.SYSTEM)
kit.If(name == ice.OPS, func() { args = append(args, m.OptionSimple(mdb.TEXT)...) })
mdb.HashModify(m, mdb.HASH, name, ParseUA(m), args)
// SpaceEvent(m, OPS_ORIGIN_OPEN, name, kit.Simple(mdb.NAME, name, args)...)
default: default:
m.Options("__target", kit.Reverse(kit.Simple(source))).OptionDefault(ice.MSG_COUNT, "0") if m.IsErr() {
return
}
func() {
defer InfoLock.Lock()()
Info.SpaceCmdCount++
Info.Commands[kit.Select(kit.Select("", m.Detailv(), 0), m.Option(ice.MSG_INDEX))]++
}()
m.Options(ice.MSG_ARGS, "", ice.MSG_COUNT, "0")
kit.If(m.Option(ice.MSG_DAEMON), func(p string) {
m.Option(ice.MSG_DAEMON0, m.Option(ice.MSG_DAEMON))
m.Option(ice.MSG_DAEMON, kit.Keys(kit.Slice(kit.Reverse(kit.Simple(source)), 0, -1), p))
})
m.Option(ice.FROM_SPACE, kit.Keys(kit.Reverse(kit.Simple(source[1:]))))
kit.If(aaa.Right(m, m.Detailv()), func() { m.TryCatch(true, func(_ *ice.Message) { m = m.Cmd() }) }) kit.If(aaa.Right(m, m.Detailv()), func() { m.TryCatch(true, func(_ *ice.Message) { m = m.Cmd() }) })
kit.If(m.Optionv(ice.MSG_ARGS) != nil, func() { m.Options(ice.MSG_ARGS, kit.Simple(m.Optionv(ice.MSG_ARGS))) })
} }
defer m.Cost(kit.Format("%v->%v %v %v", source, target, m.Detailv(), m.FormatSize())) defer m.Cost(kit.Format("%v->%v %v %v", source, target, m.Detailv(), m.FormatSize()))
_space_echo(m.Set(ice.MSG_OPTS).Options(log.DEBUG, m.Option(log.DEBUG)), []string{}, kit.Reverse(kit.Simple(source)), c) if m.Option(ice.SPACE_NOECHO) == ice.TRUE {
return
}
m.Options(ice.MSG_USERWEB, m.Optionv(ice.MSG_USERWEB), ice.MSG_USERPOD, m.Optionv(ice.MSG_USERPOD))
_space_echo(m.Set(ice.MSG_OPTS).Options(m.OptionSimple(ice.MSG_HANDLE, ice.LOG_DEBUG, ice.LOG_DISABLE, ice.LOG_TRACEID)), []string{}, kit.Reverse(kit.Simple(source)), c)
} }
func _space_echo(m *ice.Message, source, target []string, c *websocket.Conn) { func _space_echo(m *ice.Message, source, target []string, c *websocket.Conn) {
defer func() { m.Warn(recover()) }() defer func() { m.WarnNotValid(recover()) }()
if m.Options(ice.MSG_SOURCE, source, ice.MSG_TARGET, target[1:]); !m.Warn(c.WriteMessage(1, []byte(m.FormatMeta()))) { m.Options(ice.MSG_SOURCE, source, ice.MSG_TARGET, target[1:])
m.Log(tcp.SEND, "%v->%v %v %v", source, target, m.Detailv(), m.FormatsMeta(nil)) data := m.FormatMeta()
if !m.WarnNotValid(c.WriteMessage(1, []byte(data))) {
func() {
defer InfoLock.Lock()()
Info.SpaceWriteCount++
Info.SpaceWriteByte += len(data)
}()
if source != nil {
m.Log(kit.Select(tcp.SEND, tcp.DONE, m.Option(ice.MSG_HANDLE) == ice.TRUE), "%d %v->%v %v %v", len(data), source, target,
kit.ReplaceAll(kit.Format("%v", m.Detailv()), "\r\n", "\\r\\n", "\t", "\\t", "\n", "\\n"), data)
}
} }
} }
func _space_send(m *ice.Message, name string, arg ...string) (h string) { func _space_send(m *ice.Message, name string, arg ...string) (h string) {
wait, done := m.Wait("180s", func(msg *ice.Message, arg ...string) { withecho := m.Option(ice.SPACE_NOECHO) != ice.TRUE
kit.If(len(arg) > 0 && arg[0] == TOAST, func() { withecho = false; m.Option(ice.MSG_DEBUG, ice.FALSE) })
wait, done := m.Wait(kit.Select("", m.OptionDefault(ice.SPACE_TIMEOUT, "180s"), withecho), func(msg *ice.Message, arg ...string) {
m.Cost(kit.Format("%v->[%v] %v %v", m.Optionv(ice.MSG_SOURCE), name, m.Detailv(), msg.FormatSize())).Copy(msg) m.Cost(kit.Format("%v->[%v] %v %v", m.Optionv(ice.MSG_SOURCE), name, m.Detailv(), msg.FormatSize())).Copy(msg)
}) })
h = mdb.HashCreate(m.Spawn(), mdb.TYPE, tcp.SEND, mdb.NAME, kit.Keys(name, m.Target().ID()), mdb.TEXT, kit.Join(arg, lex.SP), kit.Dict(mdb.TARGET, done)) if withecho {
defer mdb.HashRemove(m.Spawn(), mdb.HASH, h) h = mdb.HashCreate(m.SpawnSilent(), mdb.TYPE, tcp.SEND, mdb.NAME, kit.Keys(name, m.Target().ID()), mdb.TEXT, kit.Join(arg, lex.SP), kit.Dict(mdb.TARGET, done))
defer mdb.HashRemove(m.SpawnSilent(), mdb.HASH, h)
}
if target := kit.Split(name, nfs.PT, nfs.PT); !mdb.HashSelectDetail(m, target[0], func(value ice.Map) { if target := kit.Split(name, nfs.PT, nfs.PT); !mdb.HashSelectDetail(m, target[0], func(value ice.Map) {
if c, ok := value[mdb.TARGET].(*websocket.Conn); !m.Warn(!ok, ice.ErrNotValid, mdb.TARGET) { if c, ok := value[mdb.TARGET].(*websocket.Conn); !m.WarnNotValid(!ok, mdb.TARGET) {
kit.For([]string{ice.MSG_USERROLE}, func(k string) { m.Optionv(k, m.Optionv(k)) }) kit.If(kit.Format(value[mdb.TYPE]) == ORIGIN && target[0] != ice.OPS, func() {
kit.For(m.Optionv(ice.MSG_OPTS), func(k string) { m.Optionv(k, m.Optionv(k)) }) m.Optionv(ice.MSG_USERWEB, kit.Simple(value[mdb.TEXT], m.Optionv(ice.MSG_USERWEB)))
_space_echo(m.Set(ice.MSG_DETAIL, arg...), []string{h}, target, c) m.Optionv(ice.MSG_USERPOD, kit.Simple(kit.Keys(target[1:]), m.Optionv(ice.MSG_USERPOD)))
m.Options(ice.MSG_USERHOST, "", ice.MSG_USERWEB0, m.Option(ice.MSG_USERWEB), ice.MSG_USERPOD0, name)
})
m.Option(ice.MSG_HANDLE, ice.FALSE)
kit.For([]string{ice.MSG_USERROLE, ice.LOG_TRACEID, ice.SPACE_NOECHO}, func(k string) { m.Optionv(k, m.Optionv(k)) })
kit.For(kit.Filters(kit.Simple(m.Optionv(ice.MSG_OPTS)), "task.id", "work.id"), func(k string) { m.Optionv(k, m.Optionv(k)) })
if withecho {
_space_echo(m.Set(ice.MSG_DETAIL, arg...), []string{h}, target, c)
} else {
_space_echo(m.Set(ice.MSG_DETAIL, arg...), nil, target, c)
}
} }
}) { }) {
m.Warn(kit.IndexOf([]string{ice.OPS, ice.DEV}, target[0]) == -1, ice.ErrNotFound, SPACE, name) if name == ice.OPS && ice.Info.NodeType == SERVER {
} else { m.Cmdy(arg)
m.Warn(!wait(), "time out") return
}
kit.If(m.IsDebug(), func() {
m.WarnNotFoundSpace(kit.IndexOf([]string{ice.OPS, ice.DEV}, target[0]) == -1, SPACE, name)
})
} else if withecho {
m.Warn(!wait(), kit.Format("space %v %v time out", name, arg))
} }
return return
} }
const ( const (
WEIXIN = "weixin"
PORTAL = "portal" PORTAL = "portal"
WORKER = "worker" WORKER = "worker"
SERVER = "server" SERVER = "server"
MASTER = "master" MYSELF = "myself"
ORIGIN = "origin"
REDIAL = "redial" REDIAL = "redial"
AGENT = "agent"
) )
const ( const (
SPACE_LOGIN = "space.login" OPS_ORIGIN_OPEN = "ops.origin.open"
OPS_SERVER_OPEN = "ops.server.open"
OPS_DREAM_SPAWN = "ops.dream.spawn"
OPS_DREAM_OPEN = "ops.dream.open"
SPACE_LOGIN = "space.login"
SPACE_LOGIN_CLOSE = "space.login.close"
SPACE_GRANT = "space.grant"
SPACE_OPEN = "space.open"
SPACE_CLOSE = "space.close"
PORTAL_OPEN = "portal.open"
PORTAL_CLOSE = "portal.close"
) )
const SPACE = "space" const SPACE = "space"
func init() { func init() {
ice.Info.Inputs = append(ice.Info.Inputs, func(m *ice.Message, arg ...string) {
switch kit.TrimPrefix(arg[0], "extra.") {
case SPACE:
m.Cmd(SPACE, func(value ice.Maps) {
kit.If(kit.IsIn(value[mdb.TYPE], WORKER, SERVER), func() { m.Push(arg[0], value[mdb.NAME]) })
})
case mdb.ICON:
m.Cmdy(nfs.DIR, ice.USR_ICONS, nfs.PATH).CutTo(nfs.PATH, arg[0])
case ctx.INDEX:
if space := m.Option(SPACE); space != "" {
m.Options(SPACE, []string{}).Cmdy(SPACE, space, ctx.COMMAND)
} else {
m.Cmdy(ctx.COMMAND)
}
case ctx.ARGS:
m.OptionDefault(ctx.INDEX, m.Option("extra.index"))
if space := m.Option(SPACE); space != "" {
m.Options(SPACE, []string{}).Cmdy(SPACE, space, ctx.COMMAND, mdb.INPUTS, m.Option(ctx.INDEX))
} else {
m.Cmdy(ctx.COMMAND, mdb.INPUTS, m.Option(ctx.INDEX))
}
}
})
ctx.PodCmd = func(m *ice.Message, arg ...ice.Any) bool {
Upload(m)
for _, key := range []string{ice.POD} {
if pod := m.Option(key); pod != "" {
if ls := kit.Simple(m.Optionv(ice.MSG_UPLOAD)); len(ls) > 1 {
m.Cmd(SPACE, pod, SPIDE, ice.DEV, CACHE, SHARE_CACHE+ls[0])
}
m.Options(key, []string{}, ice.MSG_USERPOD, pod).Cmdy(append(kit.List(ice.SPACE, pod), arg...)...)
if m.IsErr() {
m.Warn(m.IsErr(), kit.Select("", m.Resultv(), 1), kit.Slice(m.Resultv(), 2))
}
return true
}
}
return false
}
Index.MergeCommands(ice.Commands{ Index.MergeCommands(ice.Commands{
SPACE: {Help: "空间站", Actions: ice.MergeActions(ice.Actions{ "p": {Help: "资源", Actions: ApiWhiteAction(), Hand: func(m *ice.Message, arg ...string) {
ice.CTX_INIT: {Hand: func(m *ice.Message, arg ...string) { aaa.White(m, SPACE, ice.MAIN) }}, if arg[0] == "require" {
ice.MAIN: {Name: "main index", Help: "首页", Hand: func(m *ice.Message, arg ...string) { m.Cmdy("/require/", arg[1:])
return
}
if kit.IsIn(arg[0], ice.SRC, ice.USR) {
ShareLocalFile(m, arg...)
} else {
m.Cmdy(PP(ice.REQUIRE), arg)
}
}},
"m": {Help: "模块", Actions: ApiWhiteAction(), Hand: func(m *ice.Message, arg ...string) {
p := path.Join(nfs.USR_MODULES, path.Join(arg...))
kit.If(!nfs.Exists(m, p), func() {
if kit.IsIn(m.Option(ice.MSG_USERROLE), aaa.TECH, aaa.ROOT) {
kit.If(!nfs.Exists(m, nfs.USR_PACKAGE), func() {
m.Cmd(nfs.SAVE, nfs.USR_PACKAGE, kit.Formats(kit.Dict(mdb.NAME, "usr", nfs.VERSION, "0.0.1")))
})
m.Cmd(cli.SYSTEM, "npm", "install", arg[0], kit.Dict(cli.CMD_DIR, ice.USR))
}
})
m.RenderDownload(p)
}},
"c": {Help: "命令", Actions: ApiWhiteAction(), Hand: func(m *ice.Message, arg ...string) { m.Cmdy(CHAT_CMD, arg) }},
"s": {Help: "空间", Actions: ApiWhiteAction(), Hand: func(m *ice.Message, arg ...string) { m.Cmdy(CHAT_POD, arg) }},
SPACE: {Name: "space name cmds auto", Help: "空间站", Actions: ice.MergeActions(ice.Actions{
ice.CTX_INIT: {Hand: func(m *ice.Message, arg ...string) {
cli.NodeInfo(m, ice.Info.Pathname, WORKER)
aaa.White(m, SPACE, ice.MAIN)
if kit.IsIn(ice.Info.NodeIcon, "src/main.ico", "") {
nfs.Exists(m, "src/main.ico", func(p string) { ice.Info.NodeIcon = p })
nfs.Exists(m, "src/main.jpg", func(p string) { ice.Info.NodeIcon = p })
nfs.Exists(m, "src/main.png", func(p string) { ice.Info.NodeIcon = p })
}
}},
mdb.ICONS: {Hand: func(m *ice.Message, arg ...string) {
cli.NodeInfo(m, ice.Info.Pathname, WORKER, arg[0])
m.Cmd(SERVE, m.ActionKey(), arg)
}},
ice.MAIN: {Name: "main index", Role: aaa.VOID, Hand: func(m *ice.Message, arg ...string) {
if len(arg) > 0 { if len(arg) > 0 {
mdb.Config(m, ice.MAIN, m.Option(ctx.INDEX)) ice.Info.NodeMain = m.Option(ctx.INDEX)
m.Cmd(SERVE, m.ActionKey(), arg)
return return
} }
kit.If(mdb.Config(m, ice.MAIN), func(cmd string) { RenderPodCmd(m, "", cmd) }, func() { RenderMain(m) }) m.Options(mdb.ICONS, "")
m.Optionv(ice.MSG_ARGS, kit.Simple(m.Optionv(ice.MSG_ARGS))) kit.If(ice.Info.NodeMain, func(cmd string) { RenderPodCmd(m, "", cmd) }, func() { RenderMain(m) })
}},
ice.INFO: {Role: aaa.VOID, Hand: func(m *ice.Message, arg ...string) {
m.Push(mdb.TIME, ice.Info.Make.Time)
m.Push(mdb.NAME, ice.Info.NodeName)
m.Push(mdb.ICONS, ice.Info.NodeIcon)
m.Push(nfs.MODULE, ice.Info.Make.Module)
m.Push(nfs.VERSION, ice.Info.Make.Versions())
m.Push(nfs.PATHNAME, ice.Info.Pathname)
m.Push(tcp.HOSTPORT, HostPort(m, m.Cmd(tcp.HOST).Append(aaa.IP), m.Cmd(SERVER).Append(tcp.PORT)))
m.Push(ORIGIN, m.Option(ice.MSG_USERHOST))
}}, }},
mdb.SEARCH: {Hand: func(m *ice.Message, arg ...string) { mdb.SEARCH: {Hand: func(m *ice.Message, arg ...string) {
if mdb.IsSearchPreview(m, arg) { if mdb.IsSearchPreview(m, arg) {
@ -231,7 +402,7 @@ func init() {
switch value[mdb.TYPE] { switch value[mdb.TYPE] {
case SERVER: case SERVER:
m.PushSearch(mdb.TEXT, m.MergePod(value[mdb.NAME]), value) m.PushSearch(mdb.TEXT, m.MergePod(value[mdb.NAME]), value)
case MASTER: case ORIGIN:
m.PushSearch(mdb.TEXT, m.Cmdv(SPIDE, value[mdb.NAME], CLIENT_ORIGIN), value) m.PushSearch(mdb.TEXT, m.Cmdv(SPIDE, value[mdb.NAME], CLIENT_ORIGIN), value)
} }
}) })
@ -239,58 +410,182 @@ func init() {
}}, }},
cli.START: {Hand: func(m *ice.Message, arg ...string) { m.Cmdy("", tcp.DIAL, arg) }}, cli.START: {Hand: func(m *ice.Message, arg ...string) { m.Cmdy("", tcp.DIAL, arg) }},
tcp.DIAL: {Name: "dial dev=ops name", Hand: func(m *ice.Message, arg ...string) { tcp.DIAL: {Name: "dial dev=ops name", Hand: func(m *ice.Message, arg ...string) {
if strings.HasPrefix(m.Option(ice.DEV), HTTP) {
m.Cmd(SPIDE, mdb.CREATE, m.OptionSimple(ice.DEV))
m.Option(ice.DEV, ice.DEV)
}
_space_dial(m, m.Option(ice.DEV), kit.Select(ice.Info.NodeName, m.Option(mdb.NAME)), arg...) _space_dial(m, m.Option(ice.DEV), kit.Select(ice.Info.NodeName, m.Option(mdb.NAME)), arg...)
ice.Info.Important = ice.HasVar()
}}, }},
cli.CLOSE: {Hand: func(m *ice.Message, arg ...string) { mdb.HashRemove(m, m.OptionSimple(mdb.NAME)) }},
mdb.REMOVE: {Hand: func(m *ice.Message, arg ...string) { mdb.REMOVE: {Hand: func(m *ice.Message, arg ...string) {
defer ToastProcess(m)() defer ToastProcess(m)()
mdb.HashModify(m, m.OptionSimple(mdb.NAME), mdb.STATUS, cli.STOP) mdb.HashModify(m, m.OptionSimple(mdb.NAME), mdb.STATUS, cli.STOP)
m.Cmd("", m.Option(mdb.NAME), ice.EXIT) msg := mdb.HashSelect(m.Spawn(), m.Option(mdb.NAME))
m.Sleep3s() if msg.Append(mdb.TYPE) == ORIGIN {
if target, ok := mdb.HashSelectTarget(m, m.Option(mdb.NAME), nil).(io.Closer); ok {
target.Close()
}
} else {
m.Cmd("", m.Option(mdb.NAME), ice.EXIT).Sleep3s()
}
}}, }},
DOMAIN: {Hand: func(m *ice.Message, arg ...string) { m.Echo(_space_domain(m)) }}, DOMAIN: {Hand: func(m *ice.Message, arg ...string) { m.Echo(_space_domain(m)) }},
LOGIN: {Help: "授权", Hand: func(m *ice.Message, arg ...string) { LOGIN: {Help: "授权", Hand: func(m *ice.Message, arg ...string) {
m.Option(ice.MSG_USERUA, m.Cmdv("", kit.Select(m.Option(mdb.NAME), arg, 0), ice.MSG_USERUA)) msg := m.Cmd("", kit.Select(m.Option(mdb.NAME), arg, 0))
m.Options(ice.MSG_USERIP, msg.Append(aaa.IP), ice.MSG_USERUA, msg.Append(aaa.UA))
m.Cmd("", kit.Select(m.Option(mdb.NAME), arg, 0), ice.MSG_SESSID, aaa.SessCreate(m, m.Option(ice.MSG_USERNAME))) m.Cmd("", kit.Select(m.Option(mdb.NAME), arg, 0), ice.MSG_SESSID, aaa.SessCreate(m, m.Option(ice.MSG_USERNAME)))
}}, }},
SPACE_LOGIN: {Hand: func(m *ice.Message, arg ...string) {
kit.If(m.Option(ice.FROM_DAEMON), func(p string) { m.Cmd("", p, GRANT, m.Option(mdb.NAME), -1) })
}},
OPEN: {Hand: func(m *ice.Message, arg ...string) { OPEN: {Hand: func(m *ice.Message, arg ...string) {
switch m.Option(mdb.TYPE) { switch m.Option(mdb.TYPE) {
case MASTER: case ORIGIN:
m.ProcessOpen(m.Cmdv(SPIDE, m.Option(mdb.NAME), CLIENT_ORIGIN)) ProcessIframe(m, m.Option(mdb.NAME), SpideOrigin(m, m.Option(mdb.NAME)), arg...)
default: default:
m.ProcessOpen(m.MergePod(m.Option(mdb.NAME), arg)) ProcessIframe(m, m.Option(mdb.NAME), m.MergePod(m.Option(mdb.NAME)), arg...)
} }
}}, }},
nfs.PS: {Hand: func(m *ice.Message, arg ...string) { _space_fork(m) }}, nfs.PS: {Hand: func(m *ice.Message, arg ...string) { _space_fork(m) }},
}, mdb.HashAction(mdb.LIMIT, 1000, mdb.LEAST, 500, mdb.SHORT, mdb.NAME, mdb.FIELD, "time,type,name,text,module,version", ctx.ACTION, OPEN, REDIAL, kit.Dict("a", 3000, "b", 1000, "c", 1000)), mdb.ClearOnExitHashAction()), Hand: func(m *ice.Message, arg ...string) { }, gdb.EventsAction(SPACE_LOGIN), mdb.HashAction(mdb.LIMIT, 1000, mdb.LEAST, 500,
mdb.SHORT, mdb.NAME, mdb.FIELD, "time,type,name,text,main,icons,module,version,agent,system,ip,usernick,username,userrole",
ctx.ACTION, OPEN, REDIAL, kit.Dict("a", 1000, "b", 100, "c", 1000),
), mdb.ClearOnExitHashAction()), Hand: func(m *ice.Message, arg ...string) {
if len(arg) < 2 { if len(arg) < 2 {
if len(arg) == 1 && strings.Contains(arg[0], nfs.PT) {
ls := kit.Split(arg[0], nfs.PT)
m.Cmdy(SPACE, ls[0], SPACE, kit.Keys(ls[1:]))
return
}
defer m.StatusTimeCount(kit.Dict(ice.MAIN, mdb.Config(m, ice.MAIN))) defer m.StatusTimeCount(kit.Dict(ice.MAIN, mdb.Config(m, ice.MAIN)))
m.Option(ice.MSG_USERWEB, tcp.PublishLocalhost(m, m.Option(ice.MSG_USERWEB)))
kit.If(len(arg) > 0 && arg[0] != "", func() { m.OptionFields(ice.MSG_DETAIL) }) kit.If(len(arg) > 0 && arg[0] != "", func() { m.OptionFields(ice.MSG_DETAIL) })
mdb.HashSelect(m.Spawn(), arg...).Table(func(index int, value ice.Maps, field []string) { mdb.HashSelect(m.Spawn(), arg...).Table(func(value ice.Maps) {
if m.Push("", value, kit.Split(mdb.Config(m, mdb.FIELD))); len(arg) > 0 && arg[0] != "" { if m.Push("", value, kit.Split(mdb.Config(m, mdb.FIELD))); len(arg) > 0 && arg[0] != "" {
m.Push(mdb.STATUS, value[mdb.STATUS]) m.Push(mdb.STATUS, value[mdb.STATUS]).Push(aaa.UA, value[aaa.UA])
m.Push(aaa.UA, value[aaa.UA])
m.Push(aaa.IP, value[aaa.IP])
} }
if kit.IsIn(value[mdb.TYPE], WORKER, SERVER) { if kit.IsIn(value[mdb.TYPE], WEIXIN, PORTAL) && value[mdb.NAME] != html.CHROME {
m.Push(mdb.LINK, m.MergeLink(value[mdb.TEXT]))
} else if kit.IsIn(value[mdb.TYPE], WORKER, SERVER) {
m.Push(mdb.LINK, m.MergePod(value[mdb.NAME])) m.Push(mdb.LINK, m.MergePod(value[mdb.NAME]))
} else if value[mdb.TYPE] == PORTAL && value[mdb.NAME] != html.CHROME { } else if kit.IsIn(value[mdb.TYPE], ORIGIN) {
m.Push(mdb.LINK, MergeURL2(m, value[mdb.TEXT])) m.Push(mdb.LINK, value[mdb.TEXT])
} else { } else {
m.Push(mdb.LINK, "") m.Push(mdb.LINK, "")
} }
m.PushButton(kit.Select(OPEN, LOGIN, value[mdb.TYPE] == LOGIN), mdb.REMOVE) m.PushButton(kit.Select(OPEN, LOGIN, value[mdb.TYPE] == LOGIN), mdb.REMOVE)
}) })
// kit.If(len(arg) == 1, func() { m.EchoIFrame(m.MergePod(arg[0])) }, func() { m.Action(ice.MAIN) }) m.RewriteAppend(func(value, key string, index int) string {
if key == mdb.ICONS && !kit.HasPrefix(value, HTTP) {
if m.Appendv(mdb.TYPE)[index] == ORIGIN {
if !kit.HasPrefix(value, nfs.PS) {
value = kit.MergeURL(nfs.P + value)
}
if m.Appendv(mdb.NAME)[index] == ice.OPS {
value = kit.MergeURL2(m.Option(ice.MSG_USERWEB), value)
} else {
value = kit.MergeURL2(m.Appendv(mdb.TEXT)[index], value)
}
} else {
if !kit.HasPrefix(value, nfs.PS) {
value = kit.MergeURL(nfs.P+value, ice.POD, kit.Keys(m.Option(ice.MSG_USERPOD), m.Appendv(mdb.NAME)[index]))
}
}
}
return value
})
m.Sort("", kit.Simple(aaa.LOGIN, WEIXIN, PORTAL, WORKER, SERVER, ORIGIN))
} else { } else {
_space_send(m, arg[0], kit.Simple(kit.Split(arg[1]), arg[2:])...) if ice.Info.NodeType != WORKER && arg[0] == ice.OPS {
m.Cmdy(arg[1:])
return
}
if kit.IsIn(arg[0], "", ice.Info.NodeName) {
m.Cmdy(arg[1:])
return
}
if ice.Info.NodeType == WORKER && !strings.HasPrefix(arg[0], ice.OPS) {
arg[0] = kit.Keys(ice.OPS, arg[0])
}
for i := 0; i < 5; i++ {
if _space_send(m, arg[0], kit.Simple(kit.Split(arg[1]), arg[2:])...); !m.IsErrNotFoundSpace() {
break
} else if i < 4 {
m.SetAppend().SetResult().Sleep3s()
}
}
} }
}}, }},
}) })
ice.Info.Inputs = append(ice.Info.Inputs, func(m *ice.Message, arg ...string) {
switch kit.TrimPrefix(arg[0], "extra.") {
case DREAM:
m.SetAppend()
AdminCmd(m, DREAM).Table(func(value ice.Maps) {
kit.If(kit.IsIn(value[mdb.TYPE], WORKER), func() {
m.Push(arg[0], value[mdb.NAME])
m.PushRecord(value, nfs.VERSION, mdb.TIME, nfs.MODULE, mdb.ICONS)
})
})
case SPACE:
AdminCmd(m, SPACE).Table(func(value ice.Maps) {
kit.If(kit.IsIn(value[mdb.TYPE], WORKER, SERVER), func() { m.Push(arg[0], value[mdb.NAME]) })
})
case SERVER:
AdminCmd(m, SPACE).Table(func(value ice.Maps) {
kit.If(kit.IsIn(value[mdb.TYPE], SERVER), func() { m.Push(arg[0], value[mdb.NAME]) })
})
case ORIGIN:
m.SetAppend().Push(arg[0], SpideOrigin(m, ice.DEV))
m.Copy(m.Cmd(SPIDE, kit.Dict(ice.MSG_FIELDS, CLIENT_ORIGIN)).CutTo(CLIENT_ORIGIN, arg[0]).Sort(arg[0]))
case mdb.ICONS:
m.Options(nfs.DIR_DEEP, ice.TRUE, nfs.DIR_REG, kit.ExtReg(nfs.PNG, nfs.JPG, nfs.JPEG))
m.Cmdy(nfs.DIR, nfs.SRC, nfs.PATH)
if aaa.IsTechOrRoot(m) {
m.Cmdy(nfs.DIR, nfs.USR_LOCAL_IMAGE, nfs.PATH)
}
m.Cmdy(nfs.DIR, nfs.USR_IMAGE, nfs.PATH)
m.Cmdy(nfs.DIR, nfs.USR_ICONS, nfs.PATH)
m.CutTo(nfs.PATH, arg[0])
case ctx.INDEX, ice.CMD:
m.OptionFields(ctx.INDEX)
if space := m.Option(SPACE); space != "" {
if ice.Info.NodeType == WORKER {
m.Options(SPACE, []string{}).Cmdy(SPACE, kit.Keys(ice.OPS, space), ctx.COMMAND)
} else {
m.Options(SPACE, []string{}).Cmdy(SPACE, space, ctx.COMMAND)
}
} else {
m.Cmdy(ctx.COMMAND)
}
m.CutTo(ctx.INDEX, arg[0])
case ctx.ARGS:
m.OptionDefault(ctx.INDEX, m.Option("extra.index"))
if space := m.Option(SPACE); space != "" {
m.Options(SPACE, []string{}).Cmdy(SPACE, space, ctx.COMMAND, mdb.INPUTS, m.Option(ctx.INDEX))
} else {
m.Cmdy(ctx.COMMAND, mdb.INPUTS, m.Option(ctx.INDEX))
}
case tcp.WIFI:
m.Cmdy(tcp.WIFI).CutTo(tcp.SSID, arg[0])
case MESSAGE:
m.Cmdy(MESSAGE).Cut(mdb.HASH, mdb.ZONE, mdb.ICONS)
case TARGET:
m.AdminCmd(MATRIX).Table(func(value ice.Maps) {
m.Push(arg[0], kit.Keys(kit.Select("", ice.OPS, ice.Info.NodeType == WORKER), value[DOMAIN], value[mdb.NAME]))
m.Push(mdb.TYPE, value[mdb.TYPE])
})
m.Sort("type,target", []string{MYSELF, SERVER, ORIGIN, WORKER}, ice.STR_R)
}
})
ice.Info.AdminCmd = AdminCmd
ctx.PodCmd = func(m *ice.Message, arg ...ice.Any) bool {
Upload(m)
if pod := m.Option(ice.POD); pod != "" {
if ls := kit.Simple(m.Optionv(ice.MSG_UPLOAD)); len(ls) > 1 {
// m.Cmd(SPACE, pod, SPIDE, ice.DEV, CACHE, SHARE_CACHE+ls[0])
}
m.Options(ice.POD, []string{}, ice.MSG_USERPOD, strings.TrimPrefix(pod, "ops.")).Cmdy(append(kit.List(ice.SPACE, pod), arg...)...)
return true
}
return false
}
} }
func Space(m *ice.Message, arg ice.Any) []string { func Space(m *ice.Message, arg ice.Any) []string {
if arg == nil || arg == "" { if arg == nil || arg == "" {
@ -300,9 +595,30 @@ func Space(m *ice.Message, arg ice.Any) []string {
} }
func PodCmd(m *ice.Message, key string, arg ...string) bool { func PodCmd(m *ice.Message, key string, arg ...string) bool {
if pod := m.Option(key); pod != "" { if pod := m.Option(key); pod != "" {
m.Options(key, "", ice.MSG_USERPOD, pod).Cmdy(SPACE, pod, m.PrefixKey(), arg) m.Options(key, "", ice.MSG_USERPOD, strings.TrimPrefix(pod, "ops.")).Cmdy(SPACE, pod, m.ShortKey(), arg)
return true return true
} else { } else {
return false return false
} }
} }
func SpaceName(name string) string {
return kit.ReplaceAll(name, nfs.DF, "_", nfs.PS, "_", nfs.PT, "_", "[", "_", "]", "_")
}
func SpacePwd(m *ice.Message, name, text string) {
m.Optionv(ice.MSG_OPTS, m.OptionSimple(ice.MSG_USERROLE, ice.MSG_USERNAME))
m.Cmd(SPACE, name, cli.PWD, name, kit.Dict(ice.SPACE_NOECHO, ice.TRUE,
mdb.ICONS, ice.Info.NodeIcon, mdb.TEXT, text, AGENT, "Go-http-client", cli.SYSTEM, runtime.GOOS,
mdb.TIME, ice.Info.Make.Time, nfs.MODULE, ice.Info.Make.Module, nfs.VERSION, ice.Info.Make.Versions(),
))
}
func SpaceEvent(m *ice.Message, event, skip string, arg ...string) {
m.Optionv(ice.MSG_OPTS, m.OptionSimple(ice.MSG_USERROLE, ice.MSG_USERNAME))
m.Cmds(SPACE).Table(func(value ice.Maps) {
if kit.IsIn(value[mdb.TYPE], WORKER) && value[mdb.NAME] != skip {
m.Cmd(SPACE, value[mdb.NAME], gdb.EVENT, gdb.HAPPEN, gdb.EVENT, event, arg, kit.Dict(
ice.MSG_USERROLE, aaa.TECH, ice.SPACE_NOECHO, ice.TRUE,
))
}
})
m.Cmd(gdb.EVENT, gdb.HAPPEN, gdb.EVENT, event, arg, kit.Dict(ice.MSG_USERROLE, aaa.TECH))
}

View File

@ -2,33 +2,37 @@ package web
import ( import (
"bytes" "bytes"
"crypto/tls"
"encoding/json" "encoding/json"
"io" "io"
"io/ioutil" "io/ioutil"
"mime/multipart" "mime/multipart"
"net/http" "net/http"
"net/url" "net/url"
"os"
"path" "path"
"strings" "strings"
"time" "time"
ice "shylinux.com/x/icebergs" ice "shylinux.com/x/icebergs"
"shylinux.com/x/icebergs/base/aaa"
"shylinux.com/x/icebergs/base/cli" "shylinux.com/x/icebergs/base/cli"
"shylinux.com/x/icebergs/base/ctx" "shylinux.com/x/icebergs/base/ctx"
"shylinux.com/x/icebergs/base/log" "shylinux.com/x/icebergs/base/log"
"shylinux.com/x/icebergs/base/mdb" "shylinux.com/x/icebergs/base/mdb"
"shylinux.com/x/icebergs/base/nfs" "shylinux.com/x/icebergs/base/nfs"
"shylinux.com/x/icebergs/base/tcp" "shylinux.com/x/icebergs/base/tcp"
"shylinux.com/x/icebergs/base/web/html"
kit "shylinux.com/x/toolkits" kit "shylinux.com/x/toolkits"
) )
func _spide_create(m *ice.Message, name, link string) { func _spide_create(m *ice.Message, link, types, name, icons, token string) {
if u, e := url.Parse(link); !m.Warn(e != nil || link == "", ice.ErrNotValid, link) { if u, e := url.Parse(link); !m.WarnNotValid(e != nil || link == "", link) {
dir, file := path.Split(u.EscapedPath()) dir, file := path.Split(u.EscapedPath())
m.Logs(mdb.INSERT, SPIDE, name, LINK, link) m.Logs(mdb.INSERT, SPIDE, name, LINK, link)
mdb.HashSelectUpdate(m, mdb.HashCreate(m, CLIENT_NAME, name), func(value ice.Map) { mdb.HashSelectUpdate(m, mdb.HashCreate(m, CLIENT_NAME, name), func(value ice.Map) {
value[SPIDE_CLIENT] = kit.Dict(mdb.NAME, name, SPIDE_METHOD, http.MethodGet, URL, link, ORIGIN, u.Scheme+"://"+u.Host, value[mdb.ICONS], value[TOKEN] = icons, kit.Select(kit.Format(value[TOKEN]), token)
value[SPIDE_CLIENT] = kit.Dict(mdb.NAME, name, mdb.TYPE, types,
SPIDE_METHOD, http.MethodGet, URL, link, ORIGIN, u.Scheme+"://"+u.Host,
tcp.PROTOCOL, u.Scheme, tcp.HOSTNAME, u.Hostname(), tcp.HOST, u.Host, nfs.PATH, dir, nfs.FILE, file, cli.TIMEOUT, "300s", tcp.PROTOCOL, u.Scheme, tcp.HOSTNAME, u.Hostname(), tcp.HOST, u.Host, nfs.PATH, dir, nfs.FILE, file, cli.TIMEOUT, "300s",
) )
}) })
@ -36,21 +40,22 @@ func _spide_create(m *ice.Message, name, link string) {
} }
func _spide_show(m *ice.Message, name string, arg ...string) { func _spide_show(m *ice.Message, name string, arg ...string) {
file := "" file := ""
action, arg := _spide_args(m, arg, SPIDE_RAW, SPIDE_MSG, SPIDE_SAVE, SPIDE_CACHE) action, arg := _spide_args(m, arg, SPIDE_RAW, SPIDE_DETAIL, SPIDE_MSG, SPIDE_SAVE, SPIDE_CACHE, SPIDE_STREAM)
kit.If(action == SPIDE_SAVE, func() { file, arg = arg[0], arg[1:] }) kit.If(action == SPIDE_SAVE, func() { file, arg = arg[0], arg[1:] })
msg := mdb.HashSelects(m.Spawn(), name) msg := mdb.HashSelects(m.Spawn(), name)
method, arg := _spide_args(m, arg, http.MethodGet, http.MethodPut, http.MethodPost, http.MethodDelete) method, arg := _spide_args(m, arg, http.MethodGet, http.MethodPut, http.MethodPost, http.MethodDelete)
method = kit.Select(http.MethodGet, msg.Append(CLIENT_METHOD), method) method = kit.Select(http.MethodGet, msg.Append(CLIENT_METHOD), method)
uri, arg := arg[0], arg[1:] uri, arg := arg[0], arg[1:]
body, head, arg := _spide_body(m, method, arg...) body, head, arg := _spide_body(m, method, arg...)
if m.Option("_break") == ice.TRUE { if m.Option("spide.break") == ice.TRUE {
return return
} }
if c, ok := body.(io.Closer); ok { if c, ok := body.(io.Closer); ok {
defer c.Close() defer c.Close()
} }
req, e := http.NewRequest(method, kit.MergeURL2(msg.Append(CLIENT_URL), uri, arg), body) _uri := kit.MergeURL2(msg.Append(CLIENT_URL), uri, arg)
if m.Warn(e, ice.ErrNotValid, uri) { req, e := http.NewRequest(method, _uri, body)
if m.WarnNotValid(e, uri) {
return return
} }
mdb.HashSelectDetail(m, name, func(value ice.Map) { _spide_head(m, req, head, value) }) mdb.HashSelectDetail(m, name, func(value ice.Map) { _spide_head(m, req, head, value) })
@ -58,17 +63,22 @@ func _spide_show(m *ice.Message, name string, arg ...string) {
kit.For(req.Header, func(k string, v []string) { m.Logs(REQUEST, k, v) }) kit.For(req.Header, func(k string, v []string) { m.Logs(REQUEST, k, v) })
} }
res, e := _spide_send(m, name, req, kit.Format(m.OptionDefault(CLIENT_TIMEOUT, msg.Append(CLIENT_TIMEOUT)))) res, e := _spide_send(m, name, req, kit.Format(m.OptionDefault(CLIENT_TIMEOUT, msg.Append(CLIENT_TIMEOUT))))
if m.Warn(e, ice.ErrNotFound, uri) { if m.WarnNotFound(e, SPIDE, uri) {
return return
} }
defer res.Body.Close() defer res.Body.Close()
m.Cost(cli.STATUS, res.Status, nfs.SIZE, kit.FmtSize(kit.Int64(res.Header.Get(ContentLength))), mdb.TYPE, res.Header.Get(ContentType)) m.Cost(cli.STATUS, res.Status, nfs.SIZE, kit.FmtSize(kit.Int64(res.Header.Get(html.ContentLength))), mdb.TYPE, res.Header.Get(html.ContentType))
m.Push(mdb.TYPE, STATUS).Push(mdb.NAME, res.StatusCode).Push(mdb.VALUE, res.Status) if action == SPIDE_DETAIL {
m.Push(mdb.TYPE, STATUS).Push(mdb.NAME, res.StatusCode).Push(mdb.VALUE, res.Status)
}
m.Options(STATUS, res.Status)
kit.For(res.Header, func(k string, v []string) { kit.For(res.Header, func(k string, v []string) {
if m.Option(log.DEBUG) == ice.TRUE { if m.Option(log.DEBUG) == ice.TRUE {
m.Logs(RESPONSE, k, v) m.Logs(RESPONSE, k, v)
} }
m.Push(mdb.TYPE, SPIDE_HEADER).Push(mdb.NAME, k).Push(mdb.VALUE, v[0]) if m.Options(k, v); action == SPIDE_DETAIL {
m.Push(mdb.TYPE, SPIDE_HEADER).Push(mdb.NAME, k).Push(mdb.VALUE, v[0])
}
}) })
mdb.HashSelectUpdate(m, name, func(value ice.Map) { mdb.HashSelectUpdate(m, name, func(value ice.Map) {
kit.For(res.Cookies(), func(v *http.Cookie) { kit.For(res.Cookies(), func(v *http.Cookie) {
@ -76,10 +86,12 @@ func _spide_show(m *ice.Message, name string, arg ...string) {
if m.Option(log.DEBUG) == ice.TRUE { if m.Option(log.DEBUG) == ice.TRUE {
m.Logs(RESPONSE, v.Name, v.Value) m.Logs(RESPONSE, v.Name, v.Value)
} }
m.Push(mdb.TYPE, COOKIE).Push(mdb.NAME, v.Name).Push(mdb.VALUE, v.Value) if action == SPIDE_DETAIL {
m.Push(mdb.TYPE, COOKIE).Push(mdb.NAME, v.Name).Push(mdb.VALUE, v.Value)
}
}) })
}) })
if m.Warn(res.StatusCode != http.StatusOK && res.StatusCode != http.StatusCreated, ice.ErrNotValid, uri, cli.STATUS, res.Status) { if m.WarnNotValid(res.StatusCode != http.StatusOK && res.StatusCode != http.StatusCreated && res.StatusCode != http.StatusNoContent, uri, cli.STATUS, res.Status) {
switch res.StatusCode { switch res.StatusCode {
case http.StatusNotFound, http.StatusUnauthorized: case http.StatusNotFound, http.StatusUnauthorized:
return return
@ -101,26 +113,25 @@ func _spide_body(m *ice.Message, method string, arg ...string) (io.Reader, ice.M
head := ice.Maps{} head := ice.Maps{}
switch kit.If(len(arg) == 1, func() { arg = []string{SPIDE_DATA, arg[0]} }); arg[0] { switch kit.If(len(arg) == 1, func() { arg = []string{SPIDE_DATA, arg[0]} }); arg[0] {
case SPIDE_FORM: case SPIDE_FORM:
arg = kit.Simple(arg, func(v string) string { return url.QueryEscape(v) }) // arg = kit.Simple(arg, func(v string) string { return url.QueryEscape(v) })
_data := kit.JoinKV("=", "&", arg[1:]...) head[html.ContentType], body = html.ApplicationForm, bytes.NewBufferString(kit.JoinQuery(arg[1:]...))
head[ContentType], body = ApplicationForm, bytes.NewBufferString(_data) m.Info("debug what %v", kit.JoinQuery(arg[1:]...))
case SPIDE_PART: case SPIDE_PART:
head[ContentType], body = _spide_part(m, arg...) head[html.ContentType], body = _spide_part(m, arg...)
case SPIDE_FILE: case SPIDE_FILE:
if f, e := nfs.OpenFile(m, arg[1]); m.Assert(e) { if f, e := nfs.OpenFile(m, arg[1]); m.Assert(e) {
m.Logs(nfs.LOAD, nfs.FILE, arg[1]) m.Logs(nfs.LOAD, nfs.FILE, arg[1])
body = f body = f
} }
case SPIDE_DATA: case SPIDE_DATA:
head[ContentType], body = ApplicationJSON, bytes.NewBufferString(kit.Select("{}", arg, 1)) head[html.ContentType], body = html.ApplicationJSON, bytes.NewBufferString(kit.Select("{}", arg, 1))
case SPIDE_JSON: case SPIDE_JSON:
arg = arg[1:] arg = arg[1:]
fallthrough fallthrough
default: default:
data := ice.Map{} data := ice.Map{}
kit.For(arg, func(k, v string) { kit.Value(data, k, v) }) kit.For(arg, func(k, v string) { kit.Value(data, k, v) })
_data := kit.Format(data) head[html.ContentType], body = html.ApplicationJSON, bytes.NewBufferString(kit.Format(data))
head[ContentType], body = ApplicationJSON, bytes.NewBufferString(_data)
} }
return body, head, arg[:0] return body, head, arg[:0]
} }
@ -133,25 +144,25 @@ func _spide_part(m *ice.Message, arg ...string) (string, io.Reader) {
if arg[i] == nfs.SIZE { if arg[i] == nfs.SIZE {
size = kit.Int64(arg[i+1]) size = kit.Int64(arg[i+1])
} else if arg[i] == SPIDE_CACHE { } else if arg[i] == SPIDE_CACHE {
if t, e := time.ParseInLocation(ice.MOD_TIME, arg[i+1], time.Local); !m.Warn(e, ice.ErrNotValid) { if t, e := time.ParseInLocation(ice.MOD_TIME, arg[i+1], time.Local); !m.WarnNotValid(e) {
cache = t cache = t
} }
} else if strings.HasPrefix(arg[i+1], mdb.AT) { } else if strings.HasPrefix(arg[i+1], mdb.AT) {
p := arg[i+1][1:] p := arg[i+1][1:]
if s, e := nfs.StatFile(m, p); !m.Warn(e, ice.ErrNotValid) { if s, e := nfs.StatFile(m, p); !m.WarnNotValid(e) {
if s.Size() == size && s.ModTime().Before(cache) { if s.Size() == size && s.ModTime().Before(cache) {
m.Option("_break", ice.TRUE) m.Option("spide.break", ice.TRUE)
continue continue
} else if s.Size() == size && !nfs.Exists(m.Spawn(kit.Dict(ice.MSG_FILES, nfs.DiskFile)), p) { } else if s.Size() == size && !nfs.Exists(m.Spawn(kit.Dict(ice.MSG_FILES, nfs.DiskFile)), p) {
m.Option("_break", ice.TRUE) m.Option("spide.break", ice.TRUE)
continue continue
} }
m.Logs(nfs.FIND, LOCAL, s.ModTime(), nfs.SIZE, s.Size(), CACHE, cache, nfs.SIZE, size) m.Logs(nfs.FIND, LOCAL, s.ModTime(), nfs.SIZE, s.Size(), CACHE, cache, nfs.SIZE, size)
} }
if f, e := nfs.OpenFile(m, p); !m.Warn(e, ice.ErrNotValid, arg[i+1]) { if f, e := nfs.OpenFile(m, p); !m.WarnNotValid(e, arg[i+1]) {
defer f.Close() defer f.Close()
if p, e := mp.CreateFormFile(arg[i], path.Base(p)); !m.Warn(e, ice.ErrNotValid, arg[i+1]) { if p, e := mp.CreateFormFile(arg[i], path.Base(p)); !m.WarnNotValid(e, arg[i+1]) {
if n, e := io.Copy(p, f); !m.Warn(e, ice.ErrNotValid, arg[i+1]) { if n, e := io.Copy(p, f); !m.WarnNotValid(e, arg[i+1]) {
m.Logs(nfs.LOAD, nfs.FILE, arg[i+1], nfs.SIZE, n) m.Logs(nfs.LOAD, nfs.FILE, arg[i+1], nfs.SIZE, n)
} }
} }
@ -169,39 +180,56 @@ func _spide_head(m *ice.Message, req *http.Request, head ice.Maps, value ice.Map
kit.For(value[SPIDE_COOKIE], func(k string, v string) { req.AddCookie(&http.Cookie{Name: k, Value: v}) }) kit.For(value[SPIDE_COOKIE], func(k string, v string) { req.AddCookie(&http.Cookie{Name: k, Value: v}) })
kit.For(kit.Simple(m.Optionv(SPIDE_COOKIE)), func(k, v string) { req.AddCookie(&http.Cookie{Name: k, Value: v}) }) kit.For(kit.Simple(m.Optionv(SPIDE_COOKIE)), func(k, v string) { req.AddCookie(&http.Cookie{Name: k, Value: v}) })
kit.For(kit.Simple(m.Optionv(SPIDE_HEADER)), func(k, v string) { req.Header.Set(k, v) }) kit.For(kit.Simple(m.Optionv(SPIDE_HEADER)), func(k, v string) { req.Header.Set(k, v) })
kit.If(req.Method == http.MethodPost, func() { m.Logs(kit.Select(ice.AUTO, req.Header.Get(ContentLength)), req.Header.Get(ContentType)) }) kit.If(req.Method == http.MethodPost, func() {
m.Logs(kit.Select(ice.AUTO, req.Header.Get(html.ContentLength)), req.Header.Get(html.ContentType))
})
} }
func _spide_send(m *ice.Message, name string, req *http.Request, timeout string) (*http.Response, error) { func _spide_send(m *ice.Message, name string, req *http.Request, timeout string) (*http.Response, error) {
client := mdb.HashSelectTarget(m, name, func() ice.Any { return &http.Client{Timeout: kit.Duration(timeout)} }).(*http.Client) client := mdb.HashSelectTarget(m, name, func() ice.Any {
if name == ice.OPS {
return &http.Client{Timeout: kit.Duration(timeout), Transport: &http.Transport{TLSClientConfig: &tls.Config{InsecureSkipVerify: true}}}
}
return &http.Client{Timeout: kit.Duration(timeout)}
}).(*http.Client)
return client.Do(req) return client.Do(req)
} }
func _spide_save(m *ice.Message, action, file, uri string, res *http.Response) { func _spide_save(m *ice.Message, action, file, uri string, res *http.Response) {
if action == SPIDE_RAW { m.SetResult()
m.SetResult()
} else {
m.SetResult().SetAppend()
}
switch action { switch action {
case SPIDE_RAW: case SPIDE_RAW, SPIDE_DETAIL:
if b, _ := ioutil.ReadAll(res.Body); strings.HasPrefix(res.Header.Get(ContentType), ApplicationJSON) { b, _ := ioutil.ReadAll(res.Body)
// m.Echo(kit.Formats(kit.UnMarshal(string(b)))) m.Echo(string(b))
m.Echo(string(b))
} else {
m.Echo(string(b))
}
case SPIDE_MSG: case SPIDE_MSG:
var data map[string][]string var data map[string][]string
m.Assert(json.NewDecoder(res.Body).Decode(&data)) m.Assert(json.NewDecoder(res.Body).Decode(&data))
kit.For(data[ice.MSG_OPTION], func(k string) { m.Options(k, data[k]) })
kit.For(data[ice.MSG_APPEND], func(k string) { kit.For(data[k], func(v string) { m.Push(k, v) }) }) kit.For(data[ice.MSG_APPEND], func(k string) { kit.For(data[k], func(v string) { m.Push(k, v) }) })
m.Resultv(data[ice.MSG_RESULT]) m.Resultv(data[ice.MSG_RESULT])
case SPIDE_SAVE: case SPIDE_SAVE:
_cache_download(m, res, file, m.OptionCB(SPIDE)) if strings.HasSuffix(file, "/") {
file += kit.Select("", kit.Split(m.Option("Content-Disposition"), ";="), -1)
m.Info("save file %v", file)
}
m.Echo(_cache_download(m, res, file, m.OptionCB(SPIDE)))
case SPIDE_CACHE: case SPIDE_CACHE:
m.Cmdy(CACHE, DOWNLOAD, res.Header.Get(ContentType), uri, kit.Dict(RESPONSE, res), m.OptionCB(SPIDE)) m.Cmdy(CACHE, DOWNLOAD, res.Header.Get(html.ContentType), uri, kit.Dict(RESPONSE, res), m.OptionCB(SPIDE))
m.Echo(m.Append(mdb.HASH)) m.Echo(m.Append(mdb.HASH))
case SPIDE_STREAM:
cb, ok := m.Optionv(SPIDE_STREAM).(func(string))
if !ok {
cb = func(text string) { PushNoticeGrow(m, m.Option("which"), text) }
}
b := make([]byte, 1024)
for {
if n, e := res.Body.Read(b); e != nil {
break
} else {
cb(string(b[:n]))
}
}
default: default:
var data ice.Any var data ice.Any
if b, e := ioutil.ReadAll(res.Body); !m.Warn(e) { if b, e := ioutil.ReadAll(res.Body); !m.WarnNotFound(e) {
if json.Unmarshal(b, &data) == nil { if json.Unmarshal(b, &data) == nil {
m.Push("", kit.KeyValue(ice.Map{}, "", m.Optionv(SPIDE_RES, data))) m.Push("", kit.KeyValue(ice.Map{}, "", m.Optionv(SPIDE_RES, data)))
} else { } else {
@ -212,10 +240,12 @@ func _spide_save(m *ice.Message, action, file, uri string, res *http.Response) {
} }
const ( const (
SPIDE_RAW = "raw" SPIDE_RAW = "raw"
SPIDE_MSG = "msg" SPIDE_DETAIL = "detail"
SPIDE_SAVE = "save" SPIDE_MSG = "msg"
SPIDE_CACHE = "cache" SPIDE_SAVE = "save"
SPIDE_CACHE = "cache"
SPIDE_STREAM = "stream"
SPIDE_BODY = "body" SPIDE_BODY = "body"
SPIDE_FORM = "form" SPIDE_FORM = "form"
@ -225,24 +255,10 @@ const (
SPIDE_JSON = "json" SPIDE_JSON = "json"
SPIDE_RES = "content_data" SPIDE_RES = "content_data"
Basic = "Basic" IMAGE_JPEG = "image/jpeg"
Bearer = "Bearer" IMAGE_PNG = "image/png"
Authorization = "Authorization" TEXT_HTML = "text/html"
AcceptLanguage = "Accept-Language" TEXT_CSS = "text/css"
ContentLength = "Content-Length"
ContentType = "Content-Type"
UserAgent = "User-Agent"
Referer = "Referer"
Accept = "Accept"
Mozilla = "Mozilla"
ApplicationForm = "application/x-www-form-urlencoded"
ApplicationOctet = "application/octet-stream"
ApplicationJSON = "application/json"
IMAGE_PNG = "image/png"
TEXT_HTML = "text/html"
TEXT_CSS = "text/css"
) )
const ( const (
SPIDE_CLIENT = "client" SPIDE_CLIENT = "client"
@ -250,13 +266,15 @@ const (
SPIDE_COOKIE = "cookie" SPIDE_COOKIE = "cookie"
SPIDE_HEADER = "header" SPIDE_HEADER = "header"
CLIENT_URL = "client.url"
CLIENT_NAME = "client.name" CLIENT_NAME = "client.name"
CLIENT_TYPE = "client.type"
CLIENT_METHOD = "client.method" CLIENT_METHOD = "client.method"
CLIENT_ORIGIN = "client.origin"
CLIENT_TIMEOUT = "client.timeout" CLIENT_TIMEOUT = "client.timeout"
CLIENT_PROTOCOL = "client.protocol" CLIENT_PROTOCOL = "client.protocol"
CLIENT_HOSTNAME = "client.hostname" CLIENT_HOSTNAME = "client.hostname"
CLIENT_ORIGIN = "client.origin" CLIENT_HOST = "client.host"
CLIENT_URL = "client.url"
OPEN = "open" OPEN = "open"
MAIN = "main" MAIN = "main"
@ -267,49 +285,37 @@ const (
QS = "?" QS = "?"
) )
var agentIcons = map[string]string{
html.Safari: "usr/icons/Safari.png",
html.Chrome: "usr/icons/Chrome.png",
html.Edg: "usr/icons/Edg.png",
html.MicroMessenger: "usr/icons/wechat.png",
"Go-http-client": "usr/icons/go.png",
}
const SPIDE = "spide" const SPIDE = "spide"
func init() { func init() {
nfs.TemplatePath = func(m *ice.Message, arg ...string) string {
if p := path.Join(ice.SRC_TEMPLATE, m.PrefixKey(), path.Join(arg...)); nfs.Exists(m, p) {
return p + kit.Select("", nfs.PS, len(arg) == 0)
} else {
return path.Join(path.Dir(ctx.GetCmdFile(m, m.PrefixKey())), path.Join(arg...)) + kit.Select("", nfs.PS, len(arg) == 0)
}
}
nfs.TemplateText = func(m *ice.Message, p string) string {
if p := nfs.TemplatePath(m, path.Base(p)); kit.HasPrefix(p, "/require/", ice.HTTP) {
return m.Cmdx(SPIDE, ice.DEV, SPIDE_RAW, http.MethodGet, p)
} else {
return m.Cmdx(nfs.CAT, p)
}
}
nfs.DocumentPath = func(m *ice.Message, arg ...string) string {
if p := path.Join(ice.SRC_DOCUMENT, m.PrefixKey(), path.Join(arg...)); nfs.Exists(m, p) {
return p + kit.Select("", nfs.PS, len(arg) == 0)
} else {
return path.Join(path.Dir(ctx.GetCmdFile(m, m.PrefixKey())), path.Join(arg...)) + kit.Select("", nfs.PS, len(arg) == 0)
}
}
nfs.DocumentText = func(m *ice.Message, p string) string {
if p := nfs.DocumentPath(m, path.Base(p)); kit.HasPrefix(p, "/require/", ice.HTTP) {
return m.Cmdx(SPIDE, ice.DEV, SPIDE_RAW, http.MethodGet, p)
} else {
return m.Cmdx(nfs.CAT, p)
}
}
Index.MergeCommands(ice.Commands{ Index.MergeCommands(ice.Commands{
// SPIDE: {Name: "spide client.name action=raw,msg,save,cache method=GET,PUT,POST,DELETE url format=form,part,json,data,file arg run create", Help: "蜘蛛侠", Actions: ice.MergeActions(ice.Actions{ // SPIDE: {Name: "spide client.name action=raw,msg,save,cache method=GET,PUT,POST,DELETE url format=form,part,json,data,file arg run create", Help: "蜘蛛侠", Actions: ice.MergeActions(ice.Actions{
SPIDE: {Help: "蜘蛛侠", Actions: ice.MergeActions(ice.Actions{ SPIDE: {Help: "蜘蛛侠", Icon: "Find My.png", Meta: kit.Dict(ice.CTX_TRANS, kit.Dict(html.INPUT, kit.Dict(
CLIENT_TYPE, "类型", CLIENT_NAME, "名称", CLIENT_URL, "地址",
CLIENT_METHOD, "方法", CLIENT_ORIGIN, "服务", CLIENT_TIMEOUT, "超时",
CLIENT_PROTOCOL, "协议", CLIENT_HOST, "主机", CLIENT_HOSTNAME, "机器",
))), Actions: ice.MergeActions(ice.Actions{
ice.CTX_INIT: {Hand: func(m *ice.Message, arg ...string) { ice.CTX_INIT: {Hand: func(m *ice.Message, arg ...string) {
conf := mdb.Confm(m, cli.RUNTIME, cli.CONF) conf := mdb.Confm(m, cli.RUNTIME, cli.CONF)
m.Cmd("", mdb.CREATE, ice.OPS, kit.Select("http://localhost:9020", conf[cli.CTX_OPS])) dev := kit.Select("https://dev.shylinux.com", ice.Info.Make.Domain, conf[cli.CTX_DEV])
m.Cmd("", mdb.CREATE, ice.DEV, kit.Select(kit.Select("https://contexts.com.cn", ice.Info.Make.Domain), conf[cli.CTX_DEV])) m.Cmd("", mdb.CREATE, dev, ice.DEV, ice.SRC_MAIN_ICO, nfs.REPOS)
m.Cmd("", mdb.CREATE, ice.SHY, kit.Select(kit.Select("https://shylinux.com", ice.Info.Make.Remote), conf[cli.CTX_SHY])) m.Cmd("", mdb.CREATE, kit.Select(dev, os.Getenv("ctx_dev_ip")), ice.DEV_IP, ice.SRC_MAIN_ICO, "dev_ip")
m.Cmd("", mdb.CREATE, ice.COM, kit.Select("https://2021.shylinux.com", conf[cli.CTX_COM])) m.Cmd("", mdb.CREATE, kit.Select("http://localhost:9020", conf[cli.CTX_OPS]), ice.OPS, ice.SRC_MAIN_ICO, nfs.REPOS)
m.Cmd("", mdb.CREATE, ice.HUB, kit.Select("https://repos.shylinux.com", conf[cli.CTX_HUB])) m.Cmd("", mdb.CREATE, kit.Select("https://shylinux.com", conf[cli.CTX_SHY]), ice.SHY, ice.SRC_MAIN_ICO, nfs.REPOS)
m.Cmd("", mdb.CREATE, nfs.REPOS, kit.Select("https://repos.shylinux.com", conf[cli.CTX_HUB])) m.Cmd("", mdb.CREATE, kit.Select("https://mail.shylinux.com", conf[cli.CTX_MAIL]), ice.MAIL, "usr/icons/Mail.png", "mail")
m.Cmd("", mdb.CREATE, aaa.EMAIL, "https://mail.shylinux.com") m.Cmd("", mdb.CREATE, kit.Select("https://demo.shylinux.com", conf[cli.CTX_DEMO]), ice.DEMO, ice.SRC_MAIN_ICO, "demo")
m.Cmd("", mdb.CREATE, "https://2023.shylinux.com", "2023-ContextOS", ice.SRC_MAIN_ICO, nfs.REPOS)
m.Cmd("", mdb.CREATE, "https://2024.shylinux.com", "2024-ContextOS", ice.SRC_MAIN_ICO, nfs.REPOS)
m.Cmd("", mdb.CREATE, "https://2025.shylinux.com", "2025-ContextOS", ice.SRC_MAIN_ICO, nfs.REPOS)
}}, }},
mdb.SEARCH: {Hand: func(m *ice.Message, arg ...string) { mdb.SEARCH: {Hand: func(m *ice.Message, arg ...string) {
if mdb.IsSearchPreview(m, arg) { if mdb.IsSearchPreview(m, arg) {
@ -328,17 +334,47 @@ func init() {
case HEADER: case HEADER:
switch arg[0] { switch arg[0] {
case mdb.KEY: case mdb.KEY:
m.Push(arg[0], Authorization) m.Push(arg[0], html.Authorization)
} }
case CLIENT_NAME:
mdb.HashSelectValue(m.Spawn(), func(value ice.Map) {
m.Push(arg[0], kit.Value(value, CLIENT_NAME))
m.Push(mdb.TYPE, kit.Value(value, CLIENT_TYPE))
})
m.Sort(arg[0])
default: default:
mdb.HashSelectValue(m.Spawn(), func(value ice.Map) { m.Push(kit.Select(ORIGIN, arg, 0), kit.Value(value, CLIENT_ORIGIN)) }) switch arg[0] {
case mdb.NAME, mdb.ICONS:
m.SplitIndex(m.Cmdx(SPIDE, ice.DEV, kit.MergeURL2(m.Option(ORIGIN), C(SPACE, ice.INFO)))).Cut(arg[0])
mdb.HashInputs(m, arg)
default:
mdb.HashSelectValue(m.Spawn(), func(value ice.Map) {
m.Push(kit.Select(ORIGIN, arg, 0), kit.Value(value, kit.Keys("client", arg[0])))
})
kit.If(arg[0] == mdb.TYPE, func() { m.Push(arg[0], nfs.REPOS) })
m.Sort(arg[0])
}
} }
}}, }},
mdb.CREATE: {Name: "create name link", Hand: func(m *ice.Message, arg ...string) { _spide_create(m, m.Option(mdb.NAME), m.Option(LINK)) }}, mdb.CREATE: {Name: "create origin* name icons type token", Hand: func(m *ice.Message, arg ...string) {
COOKIE: {Name: "cookie key* value", Hand: func(m *ice.Message, arg ...string) { if m.Option(mdb.TYPE) == nfs.REPOS && (m.Option(mdb.NAME) == "" || m.Option(mdb.ICONS) == "") {
msg := m.Spawn().SplitIndex(m.Cmdx(SPIDE, ice.DEV, kit.MergeURL2(m.Option(ORIGIN), C(SPACE, ice.INFO))))
if m.OptionDefault(mdb.NAME, msg.Append(mdb.NAME)); msg.Append(mdb.ICONS) != "" {
m.OptionDefault(mdb.ICONS, m.Resource(msg.Append(mdb.ICONS), msg.Append(ORIGIN)))
}
}
if u, e := url.Parse(m.Option(ORIGIN)); m.WarnNotValid(e != nil || u.Host == "", m.Option(ORIGIN)) {
return
} else {
m.OptionDefault(mdb.NAME, kit.Split(u.Host, ".:")[0])
kit.If(u.Query().Get(TOKEN), func(p string) { m.OptionDefault(TOKEN, p) })
_spide_create(m, m.Option(ORIGIN), m.Option(mdb.TYPE), m.Option(mdb.NAME), m.Option(mdb.ICONS), m.Option(TOKEN))
}
}},
COOKIE: {Name: "cookie key* value", Help: "状态量", Hand: func(m *ice.Message, arg ...string) {
mdb.HashModify(m, m.OptionSimple(CLIENT_NAME), kit.Keys(COOKIE, m.Option(mdb.KEY)), m.Option(mdb.VALUE)) mdb.HashModify(m, m.OptionSimple(CLIENT_NAME), kit.Keys(COOKIE, m.Option(mdb.KEY)), m.Option(mdb.VALUE))
}}, }},
HEADER: {Name: "header key* value", Hand: func(m *ice.Message, arg ...string) { HEADER: {Name: "header key* value", Help: "请求头", Hand: func(m *ice.Message, arg ...string) {
mdb.HashModify(m, m.OptionSimple(CLIENT_NAME), kit.Keys(HEADER, m.Option(mdb.KEY)), m.Option(mdb.VALUE)) mdb.HashModify(m, m.OptionSimple(CLIENT_NAME), kit.Keys(HEADER, m.Option(mdb.KEY)), m.Option(mdb.VALUE))
}}, }},
MERGE: {Hand: func(m *ice.Message, arg ...string) { MERGE: {Hand: func(m *ice.Message, arg ...string) {
@ -347,42 +383,97 @@ func init() {
PROXY: {Name: "proxy url size cache upload", Hand: func(m *ice.Message, arg ...string) { PROXY: {Name: "proxy url size cache upload", Hand: func(m *ice.Message, arg ...string) {
m.Cmdy(SPIDE, ice.DEV, SPIDE_RAW, http.MethodPost, m.Option(URL), SPIDE_PART, arg[2:]) m.Cmdy(SPIDE, ice.DEV, SPIDE_RAW, http.MethodPost, m.Option(URL), SPIDE_PART, arg[2:])
}}, }},
}, mdb.HashAction(mdb.SHORT, CLIENT_NAME, mdb.FIELD, "time,client.name,client.url")), Hand: func(m *ice.Message, arg ...string) { "disconn": {Help: "断连", Icon: "bi bi-person-x", Style: "danger", Hand: func(m *ice.Message, arg ...string) {
m.Cmd(SPACE, cli.CLOSE, kit.Dict(mdb.NAME, m.Option(CLIENT_NAME)))
mdb.HashModify(m, mdb.NAME, m.Option(CLIENT_NAME), TOKEN, "")
}},
DEV_CREATE_TOKEN: {Hand: func(m *ice.Message, arg ...string) {
m.OptionDefault(CLIENT_NAME, m.Option(ice.FROM_SPACE))
mdb.HashModify(m, m.OptionSimple(CLIENT_NAME, TOKEN))
m.Cmd(SPACE, tcp.DIAL, m.Option(CLIENT_NAME)).Sleep300ms()
}},
DEV_REQUEST_TEXT: {Hand: func(m *ice.Message, arg ...string) { m.Echo(SpaceName(ice.Info.NodeName)) }},
}, DevTokenAction(CLIENT_NAME, CLIENT_URL), mdb.ImportantHashAction(mdb.SHORT, CLIENT_NAME, mdb.FIELD, "time,icons,client.name,client.url,client.type,token")), Hand: func(m *ice.Message, arg ...string) {
if len(arg) < 2 || arg[0] == "" || (len(arg) > 3 && arg[3] == "") { if len(arg) < 2 || arg[0] == "" || (len(arg) > 3 && arg[3] == "") {
mdb.HashSelect(m, kit.Slice(arg, 0, 1)...).Sort(CLIENT_NAME) list := m.CmdMap(SPACE, mdb.NAME)
mdb.HashSelect(m, kit.Slice(arg, 0, 1)...).Table(func(value ice.Maps) {
if value[CLIENT_TYPE] == nfs.REPOS {
if _, ok := list[value[CLIENT_NAME]]; ok {
m.Push(mdb.STATUS, ONLINE).PushButton(mdb.DEV_REQUEST, "disconn", mdb.REMOVE)
} else {
m.Push(mdb.STATUS, "").PushButton(mdb.DEV_REQUEST, mdb.REMOVE)
}
} else {
m.Push(mdb.STATUS, "").PushButton(mdb.REMOVE)
}
})
kit.If(len(arg) > 0 && arg[0] != "", func() { m.Action(COOKIE, HEADER) }) kit.If(len(arg) > 0 && arg[0] != "", func() { m.Action(COOKIE, HEADER) })
m.Sort("client.type,client.name", []string{nfs.REPOS, "dev_ip", "demo", "mail"})
} else { } else {
_spide_show(m, arg[0], arg[1:]...) _spide_show(m, arg[0], arg[1:]...)
} }
}}, }},
http.MethodGet: {Name: "GET url key value run", Help: "蜘蛛侠", Hand: func(m *ice.Message, arg ...string) { http.MethodGet: {Name: "GET url key value run", Hand: func(m *ice.Message, arg ...string) {
m.Echo(kit.Formats(kit.UnMarshal(m.Cmdx(SPIDE, ice.DEV, SPIDE_RAW, http.MethodGet, arg[0], arg[1:])))) m.Echo(kit.Formats(kit.UnMarshal(m.Cmdx(SPIDE, ice.DEV, SPIDE_RAW, http.MethodGet, arg[0], arg[1:]))))
}}, }},
http.MethodPut: {Name: "PUT url key value run", Help: "蜘蛛侠", Hand: func(m *ice.Message, arg ...string) { http.MethodPut: {Name: "PUT url key value run", Hand: func(m *ice.Message, arg ...string) {
m.Echo(kit.Formats(kit.UnMarshal(m.Cmdx(SPIDE, ice.DEV, SPIDE_RAW, http.MethodPut, arg[0], arg[1:])))) m.Echo(kit.Formats(kit.UnMarshal(m.Cmdx(SPIDE, ice.DEV, SPIDE_RAW, http.MethodPut, arg[0], arg[1:]))))
}}, }},
http.MethodPost: {Name: "POST url key value run", Help: "蜘蛛侠", Hand: func(m *ice.Message, arg ...string) { http.MethodPost: {Name: "POST url key value run", Hand: func(m *ice.Message, arg ...string) {
m.Echo(kit.Formats(kit.UnMarshal(m.Cmdx(SPIDE, ice.DEV, SPIDE_RAW, http.MethodPost, arg[0], arg[1:])))) m.Echo(kit.Formats(kit.UnMarshal(m.Cmdx(SPIDE, ice.DEV, SPIDE_RAW, http.MethodPost, arg[0], arg[1:]))))
}}, }},
http.MethodDelete: {Name: "DELETE url key value run", Help: "蜘蛛侠", Hand: func(m *ice.Message, arg ...string) { http.MethodDelete: {Name: "DELETE url key value run", Hand: func(m *ice.Message, arg ...string) {
m.Echo(kit.Formats(kit.UnMarshal(m.Cmdx(SPIDE, ice.DEV, SPIDE_RAW, http.MethodDelete, arg[0], arg[1:])))) m.Echo(kit.Formats(kit.UnMarshal(m.Cmdx(SPIDE, ice.DEV, SPIDE_RAW, http.MethodDelete, arg[0], arg[1:]))))
}}, }},
}) })
} nfs.TemplateText = func(m *ice.Message, p string) string {
if p := kit.Select(nfs.TemplatePath(m, p), m.Option("_template")); kit.HasPrefix(p, nfs.P, nfs.REQUIRE, ice.HTTP) {
func HostPort(m *ice.Message, host, port string) string { return kit.Format(mdb.Cache(ice.Pulse, p, func() ice.Any { return m.Cmdx(SPIDE, ice.OPS, SPIDE_RAW, http.MethodGet, p) }))
kit.If(host == "", func() { host = kit.ParseURL(UserHost(m)).Hostname() }) } else if p == "" {
if port == "443" { return ""
return kit.Format("https://%s", host) } else if nfs.Exists(m, p) {
} else if port == "80" || port == "" { return m.Cmdx(nfs.CAT, p)
return kit.Format("http://%s", host) } else if strings.Contains(p, "/pkg/mod/") {
} else { ls := strings.Split(p, "/pkg/mod/")
return kit.Format("http://%s:%s", host, port) return kit.Format(mdb.Cache(ice.Pulse, p, func() ice.Any { return m.Cmdx(SPIDE, ice.OPS, SPIDE_RAW, http.MethodGet, nfs.REQUIRE+ls[1]) }))
} else if strings.Contains(p, "/usr/local/work/") {
ls := strings.Split(strings.Split(p, "/usr/local/work/")[1], "/src/")
pp := kit.MergeURL2(ice.Info.Make.Domain, "/p/src/"+ls[1]+"?pod="+ls[0])
return kit.Format(mdb.Cache(ice.Pulse, p, func() ice.Any { return m.Cmdx(SPIDE, ice.OPS, SPIDE_RAW, http.MethodGet, pp) }))
} else {
return ""
}
}
nfs.TemplatePath = func(m *ice.Message, arg ...string) string {
if p := path.Join(ice.SRC_TEMPLATE, m.PrefixKey(), path.Join(arg...)); nfs.Exists(m, p) {
return p + kit.Select("", nfs.PS, len(arg) == 0)
} else {
p := m.FileURI(ctx.GetCmdFile(m, m.PrefixKey()))
if pp := kit.TrimPrefix(path.Join(path.Dir(p), path.Join(arg...)), nfs.P, nfs.REQUIRE); nfs.Exists(m, pp) {
return pp
}
if ice.Info.Important {
return kit.MergeURL2(SpideOrigin(m, ice.OPS)+p, path.Join(arg...))
}
return ""
}
}
nfs.DocumentPath = func(m *ice.Message, arg ...string) string {
if p := path.Join(nfs.USR_LEARNING_PORTAL, m.PrefixKey(), path.Join(arg...)); nfs.Exists(m, p) {
return p + kit.Select("", nfs.PS, len(arg) == 0)
} else {
return kit.MergeURL2(UserHost(m)+ctx.GetCmdFile(m, m.PrefixKey()), path.Join(arg...))
}
}
nfs.DocumentText = func(m *ice.Message, p string) string {
if p := nfs.DocumentPath(m, path.Base(p)); kit.HasPrefix(p, nfs.P, nfs.REQUIRE, ice.HTTP) {
return m.Cmdx(SPIDE, ice.DEV, SPIDE_RAW, http.MethodGet, p)
} else {
return m.Cmdx(nfs.CAT, p)
}
} }
} }
func PublicIP(m *ice.Message) ice.Any {
return SpideGet(m, "http://ip-api.com/json")
}
func SpideGet(m *ice.Message, arg ...ice.Any) ice.Any { func SpideGet(m *ice.Message, arg ...ice.Any) ice.Any {
return kit.UnMarshal(m.Cmdx(http.MethodGet, arg)) return kit.UnMarshal(m.Cmdx(http.MethodGet, arg))
} }
@ -395,9 +486,59 @@ func SpidePost(m *ice.Message, arg ...ice.Any) ice.Any {
func SpideDelete(m *ice.Message, arg ...ice.Any) ice.Any { func SpideDelete(m *ice.Message, arg ...ice.Any) ice.Any {
return kit.UnMarshal(m.Cmdx(http.MethodDelete, arg)) return kit.UnMarshal(m.Cmdx(http.MethodDelete, arg))
} }
func SpideSave(m *ice.Message, file, link string, cb func(count int, total int, value int)) *ice.Message { func SpideCache(m *ice.Message, link string) *ice.Message {
return m.Cmd(Prefix(SPIDE), ice.DEV, SPIDE_SAVE, file, http.MethodGet, link, cb) return m.Cmd(Prefix(SPIDE), ice.DEV_IP, SPIDE_CACHE, http.MethodGet, link)
} }
func SpideOrigin(m *ice.Message, name string) string { func SpideSave(m *ice.Message, file, link string, cb func(count, total, value int)) *ice.Message {
return m.Cmdv("web.spide", name, CLIENT_ORIGIN) for _, p := range []string{ice.DEV_IP, ice.DEV} {
msg := m.Cmd(Prefix(SPIDE), p, SPIDE_SAVE, file, http.MethodGet, link, cb)
if !msg.IsErr() {
return msg
}
}
return m
}
func SpideOrigin(m *ice.Message, name string) string { return m.Cmdv(SPIDE, name, CLIENT_ORIGIN) }
func SpideURL(m *ice.Message, name string) string { return m.Cmdv(SPIDE, name, CLIENT_URL) }
func SpideList(m *ice.Message) *ice.Message { return m.Copy(AdminCmd(m, SPIDE)) }
func SpideReposList(m *ice.Message) *ice.Message {
AdminCmd(m, SPIDE).Table(func(value ice.Maps) {
if value[CLIENT_TYPE] == nfs.REPOS {
m.Push(mdb.NAME, value[CLIENT_NAME])
m.Push(mdb.ICONS, value[mdb.ICONS])
}
})
ctx.DisplayInputKey(m, "style", "_nameicon")
return m
}
func PublicIP(m *ice.Message, arg ...string) ice.Any {
if len(arg) == 0 {
return SpideGet(m, "http://ip-api.com/json")
}
return mdb.Cache(m, "web.spide.location."+arg[0], func() ice.Any {
return kit.Format(kit.Value(SpideGet(m, "http://opendata.baidu.com/api.php?co=&resource_id=6006&oe=utf8", "query", arg[0]), "data.0.location"))
})
}
func HostPort(m *ice.Message, host, port string, arg ...string) string {
p := ""
if len(arg) > 0 {
kit.If(kit.Select("", arg, 0), func(pod string) { p += S(pod) })
kit.If(kit.Select("", arg, 1), func(cmd string) { p += C(cmd) })
}
kit.If(m.Option(ice.LOG_DEBUG) == ice.TRUE, func() { p += "?debug=true" })
kit.If(host == "", func() {
if u := kit.ParseURL(UserHost(m)); u != nil {
host = u.Hostname()
}
})
host = kit.Select("localhost", host)
if port == tcp.PORT_443 {
return kit.Format("https://%s", host) + p
} else if port == tcp.PORT_80 {
return kit.Format("http://%s", host) + p
} else if port == "" {
return kit.Format("%s://%s", UserWeb(m).Scheme, host) + p
} else {
return kit.Format("http://%s:%s", host, port) + p
}
} }

57
base/web/stats.go Normal file
View File

@ -0,0 +1,57 @@
package web
import (
ice "shylinux.com/x/icebergs"
"shylinux.com/x/icebergs/base/aaa"
"shylinux.com/x/icebergs/base/ctx"
"shylinux.com/x/icebergs/base/gdb"
"shylinux.com/x/icebergs/base/mdb"
"shylinux.com/x/icebergs/base/nfs"
kit "shylinux.com/x/toolkits"
)
const (
STATS_TABLES = "stats.tables"
)
const STATS = "stats"
func init() {
Index.MergeCommands(ice.Commands{
STATS: {Help: "汇总量", Hand: func(m *ice.Message, arg ...string) {
defer ctx.DisplayStory(m, "")
if m.Option(ice.MSG_USERPOD) == "" {
PushStats(m, "", "", "", "共享总数", SHARE)
PushStats(m, "", "", "", "令牌总数", TOKEN)
PushStats(m, "", "", "", "注册总数", aaa.APPLY)
PushStats(m, "", "", "", "邀请总数", aaa.OFFER)
if ice.Info.Username == ice.Info.Make.Username {
PushStats(m, "", m.Cmd(aaa.USER).Length()-1, "", "用户总数", aaa.USER)
} else {
PushStats(m, "", m.Cmd(aaa.USER).Length()-2, "", "用户总数", aaa.USER)
}
PushStats(m, "", "", "", "会话总数", aaa.SESS)
PushStats(m, "", m.Cmd(mdb.SELECT, aaa.ROLE, "", mdb.HASH).Length(), "", "角色总数", aaa.ROLE)
PushStats(m, "", "", "", "命令总数", ctx.COMMAND)
}
gdb.Event(m, STATS_TABLES)
PushPodCmd(m, "", arg...)
}},
})
}
func StatsAction(arg ...string) ice.Actions {
return ice.MergeActions(ice.Actions{
STATS_TABLES: {Hand: func(m *ice.Message, _ ...string) {
if msg := mdb.HashSelects(m.Spawn()); msg.Length() > 0 {
PushStats(m, kit.Keys(m.CommandKey(), mdb.TOTAL), msg.Length(), arg...)
}
}},
}, gdb.EventsAction(STATS_TABLES))
}
func PushStats(m *ice.Message, name string, value ice.Any, arg ...string) {
index := kit.Select(m.ShortKey(), arg, 2)
kit.If(name == "", func() { name = kit.Keys(kit.Select("", kit.Split(index, nfs.PT), -1), mdb.TOTAL) })
kit.If(value == "", func() { value = m.Cmd(index).Length() })
kit.If(value != 0, func() {
m.Push(mdb.NAME, name).Push(mdb.VALUE, value).Push(mdb.UNITS, kit.Select("", arg, 0)).Push(ctx.TRANS, kit.Select("", arg, 1)).Push(ctx.INDEX, index)
})
}

7
base/web/store.css Normal file
View File

@ -0,0 +1,7 @@
$project div.list { margin-left:25px; }
$project div.item span.exists { color:var(--notice-bg-color); padding:0 var(--input-padding); }
$content>div.item { box-shadow:var(--th-box-shadow); border:var(--plugin-border); border-radius:var(--plugin-radius); }
$content>div.item:hover { box-shadow:var(--notice-box-shadow); }
$content>div.item div.title div.label { font-size:var(--status-font-size); font-weight:normal; margin-top:var(--input-margin); }
$content>div.item div.title div.label span { padding:var(--input-padding); padding-right:var(--input-margin); }
$content>div.item div.content { height:70px; }

131
base/web/store.go Normal file
View File

@ -0,0 +1,131 @@
package web
import (
ice "shylinux.com/x/icebergs"
"shylinux.com/x/icebergs/base/aaa"
"shylinux.com/x/icebergs/base/cli"
"shylinux.com/x/icebergs/base/ctx"
"shylinux.com/x/icebergs/base/mdb"
"shylinux.com/x/icebergs/base/nfs"
"shylinux.com/x/icebergs/base/tcp"
kit "shylinux.com/x/toolkits"
)
const STORE = "store"
func init() {
Index.MergeCommands(ice.Commands{
STORE: {Name: "store refresh", Help: "商店", Icon: "App Store.png", Role: aaa.VOID, Actions: ice.MergeActions(ice.Actions{
ice.AFTER_INIT: {Hand: func(m *ice.Message, arg ...string) {
AddPortalProduct(m, "云商店", `
每个用户都可以将自己的空间列表以系统商店的方式分享给其它用户
同样的每个用户也可以添加任意多个商店直接将空间下载到本机使用
`, 300.0)
}},
mdb.INPUTS: {Hand: func(m *ice.Message, arg ...string) {
switch arg[0] {
case ORIGIN:
m.Cmd(BROAD).Table(func(value ice.Maps) {
m.Push(arg[0], HostPort(m, value[tcp.HOST], value[tcp.PORT]))
})
}
m.Cmdy(SPIDE, mdb.INPUTS, arg)
}},
mdb.CREATE: {Name: "create origin* name icons", Hand: func(m *ice.Message, arg ...string) {
m.Cmd(SPIDE, mdb.CREATE, m.OptionSimple("origin,name,icons"), mdb.TYPE, nfs.REPOS)
}},
mdb.REMOVE: {Hand: func(m *ice.Message, arg ...string) {
m.Cmd(SPIDE, mdb.REMOVE, CLIENT_NAME, m.Option(mdb.NAME))
}},
tcp.DIAL: {Hand: func(m *ice.Message, arg ...string) {
m.Options(m.Cmd(SPIDE, m.Option(mdb.NAME)).AppendSimple())
m.Cmdy(SPIDE, mdb.DEV_REQUEST)
}},
INSTALL: {Name: "install name*", Hand: func(m *ice.Message, arg ...string) {
if !kit.HasPrefixList(arg, ctx.RUN) {
m.Cmdy(DREAM, mdb.CREATE, m.OptionSimple(mdb.NAME, nfs.REPOS, nfs.BINARY))
m.Cmdy(DREAM, cli.START, m.OptionSimple(mdb.NAME))
}
ProcessIframe(m, m.Option(mdb.NAME), S(m.Option(mdb.NAME)), arg...)
}},
PORTAL: {Role: aaa.VOID, Hand: func(m *ice.Message, arg ...string) {
ProcessIframe(m, m.Option(mdb.NAME), m.Option(ORIGIN)+S(m.Option(mdb.NAME))+C(m.ActionKey()), arg...)
}},
OPEN: {Hand: func(m *ice.Message, arg ...string) {
if m.Option(mdb.TYPE) == ORIGIN {
m.ProcessOpen(m.Option(ORIGIN))
} else {
m.ProcessOpen(S(m.Option(mdb.NAME)))
}
}},
}, ctx.ConfAction(CLIENT_TIMEOUT, cli.TIME_3s), DREAM), Hand: func(m *ice.Message, arg ...string) {
if kit.HasPrefixList(arg, ctx.ACTION) {
m.Cmdy(DREAM, arg)
} else if m.Display("").DisplayCSS(""); len(arg) == 0 {
list := m.Spawn(ice.Maps{ice.MSG_FIELDS: ""}).CmdMap(SPACE, mdb.NAME)
m.Cmd(SPIDE, arg, kit.Dict(ice.MSG_FIELDS, "time,icons,client.type,client.name,client.origin")).Table(func(value ice.Maps) {
kit.If(value[CLIENT_TYPE] == nfs.REPOS && value[CLIENT_NAME] != ice.SHY, func() {
kit.If(value[CLIENT_NAME] == ice.OPS, func() { value[CLIENT_ORIGIN] = UserHost(m) })
m.Push(mdb.TYPE, ORIGIN).Push(mdb.NAME, value[CLIENT_NAME]).Push(mdb.ICONS, value[mdb.ICONS]).Push(ORIGIN, value[CLIENT_ORIGIN])
if _, ok := list[value[CLIENT_NAME]]; ok || kit.IsIn(value[CLIENT_NAME], ice.OPS, ice.DEV) {
m.Push(mdb.STATUS, ice.TRUE)
} else {
m.Push(mdb.STATUS, ice.FALSE)
}
})
})
if m.SortStrR(mdb.NAME); ice.Info.NodeType == WORKER || !aaa.IsTechOrRoot(m) {
m.Action()
} else {
m.PushAction(OPEN, tcp.DIAL, mdb.REMOVE).Action(mdb.CREATE)
}
} else {
defer ToastProcess(m, ice.LIST, arg[0])()
if arg[0] == ice.OPS && ice.Info.NodeType == SERVER {
m.Cmdy(DREAM)
return
}
dream := C(DREAM)
origin := SpideOrigin(m, arg[0])
kit.If(origin == "", func() { arg[0], origin, dream = ice.DEV, arg[0], arg[0]+dream })
// if kit.IsIn(kit.ParseURL(origin).Hostname(), append(m.Cmds(tcp.HOST).Appendv(aaa.IP), tcp.LOCALHOST)...) {
// if kit.IsIn(kit.ParseURL(origin).Hostname(), tcp.LOCALHOST) {
// origin = m.Option(ice.MSG_USERHOST)
// } else {
// origin = tcp.PublishLocalhost(m, origin)
// }
// origin = tcp.PublishLocalhost(m, origin)
stat := map[string]int{}
list := m.Spawn(ice.Maps{ice.MSG_FIELDS: ""}).CmdMap(SPACE, mdb.NAME)
m.SetAppend().Spawn().SplitIndex(m.Cmdx(SPIDE, arg[0], dream, kit.Dict(mdb.ConfigSimple(m, CLIENT_TIMEOUT)))).Table(func(value ice.Maps) {
if value[mdb.TYPE] == ORIGIN {
return
}
stat[value[mdb.TYPE]]++
if value[nfs.BINARY] == "" {
value[nfs.BINARY] = origin + S(value[mdb.NAME])
}
m.Push("", value, kit.Split("time,type,name,icons,repos,binary,module,version"))
if _, ok := list[value[mdb.NAME]]; ok {
m.Push(mdb.STATUS, ice.TRUE)
} else {
m.Push(mdb.STATUS, ice.FALSE)
}
if value[mdb.TYPE] == SERVER {
m.Push(mdb.TEXT, value[mdb.TEXT]).Push(ORIGIN, value[mdb.TEXT]).PushButton()
return
}
m.Push(mdb.TEXT, value[nfs.REPOS]).Push(ORIGIN, origin)
button := []ice.Any{PORTAL}
if _, ok := list[value[mdb.NAME]]; ok {
button = append(button, OPEN)
} else if aaa.IsTechOrRoot(m) {
button = append(button, INSTALL)
}
m.PushButton(button...)
})
m.StatusTimeCount(ORIGIN, origin, stat)
}
}},
})
}

27
base/web/store.js Normal file
View File

@ -0,0 +1,27 @@
Volcanos(chat.ONIMPORT, {
_init: function(can, msg, cb) {
can.db.hash[0] = can.db.hash[0]||(can.user.info.nodetype == web.WORKER? ice.OPS: ice.DEV)
can.ui = can.onappend.layout(can), can.onimport._project(can, msg, [])
cb && cb(msg), can.onappend._filter(can)
},
_project: function(can, msg, dev, target) {
msg.Table(function(value) { if (value.type == web.WORKER) { return }
value.nick = [{text: value.name}, value.status == "true" && {text: ["●", "", "exists"]}]
value._hash = dev.concat([value.name]).join(":"), value._select = can.base.beginWith(can.db.hash.join(":"), value._hash)
value.icons = can.misc.Resource(can, value.icons||"usr/icons/icebergs.png", "", value.origin)
can.onimport.itemlist(can, [value], function(event, item, show, target) {
can.onimport.tabsCache(can, value, target, function(event) {
can.run(event, [value.origin], function(msg) {
can.onimport._project(can, msg, dev.concat([value.name]), target)
can.onimport._content(can, msg), can.onappend._status(can, msg)
})
})
}, null, target)
})
},
_content: function(can, msg) {
can.onimport.card(can, msg, null, function(value) { if (value.type == web.SERVER) { return true }
value.icons = can.misc.Resource(can, value.icons||"usr/icons/icebergs.png", "", value.origin)
}), can.onappend.style(can, "output card", can.ui.content), can.onimport.layout(can)
},
})

79
base/web/stream.go Normal file
View File

@ -0,0 +1,79 @@
package web
import (
"strings"
ice "shylinux.com/x/icebergs"
"shylinux.com/x/icebergs/base/aaa"
"shylinux.com/x/icebergs/base/cli"
"shylinux.com/x/icebergs/base/ctx"
"shylinux.com/x/icebergs/base/gdb"
"shylinux.com/x/icebergs/base/mdb"
"shylinux.com/x/icebergs/base/nfs"
"shylinux.com/x/icebergs/base/web/html"
kit "shylinux.com/x/toolkits"
)
func _stream_subkey(m *ice.Message, arg ...string) *ice.Message {
kit.If(len(arg) == 0, func() { arg = append(arg, kit.Hashs(kit.Fields(m.Option(ice.MSG_SPACE), m.Option(ice.MSG_INDEX)))) })
return m.Options(mdb.SUBKEY, kit.Keys(mdb.HASH, arg[0]), ice.MSG_FIELDS, mdb.Config(m, mdb.FIELDS))
}
const (
PUSH = "push"
)
const STREAM = "stream"
func init() {
Index.MergeCommands(ice.Commands{
STREAM: {Name: "stream hash daemon auto", Help: "推送流", Actions: ice.MergeActions(ice.Actions{
ONLINE: {Hand: func(m *ice.Message, arg ...string) {
if m.Option(ice.MSG_DAEMON) == "" {
return
}
mdb.HashCreate(m, SPACE, m.Option(ice.MSG_SPACE), ctx.INDEX, m.Option(ice.MSG_INDEX), mdb.SHORT, cli.DAEMON, mdb.FIELD, mdb.Config(m, mdb.FIELDS))
mdb.HashCreate(_stream_subkey(m), ParseUA(m))
mdb.HashSelect(m)
}},
PUSH: {Role: aaa.VOID, Hand: func(m *ice.Message, arg ...string) {
m.Options(ice.MSG_SPACE, arg[0], ice.MSG_INDEX, arg[1])
mdb.HashSelect(_stream_subkey(m)).Table(func(value ice.Maps) {
if !kit.IsIn(value[cli.DAEMON], strings.TrimPrefix(m.Option(ice.MSG_DAEMON), "ops."), m.Option(ice.MSG_DAEMON0)) {
m.Options(mdb.SUBKEY, "").Cmd(SPACE, value[cli.DAEMON], arg[2:])
}
})
}},
PORTAL_CLOSE: {Hand: func(m *ice.Message, arg ...string) {
mdb.HashSelect(m).Table(func(value ice.Maps) {
mdb.HashSelect(_stream_subkey(m, value[mdb.HASH]).Spawn()).Table(func(value ice.Maps) {
if strings.HasPrefix(value[cli.DAEMON], m.Option(mdb.NAME)) {
mdb.HashRemove(m, mdb.HASH, kit.Hashs(value[cli.DAEMON]))
}
})
})
}},
}, gdb.EventsAction(PORTAL_CLOSE), mdb.ClearOnExitHashAction(), mdb.HashAction(
mdb.SHORT, "space,index", mdb.FIELD, "time,hash,space,index",
mdb.FIELDS, "time,daemon,userrole,username,usernick,avatar,icons,agent,system,ip,ua",
)), Hand: func(m *ice.Message, arg ...string) {
if len(arg) == 0 {
mdb.HashSelect(m)
} else {
mdb.HashSelect(_stream_subkey(m, arg[0]), arg[1:]...)
}
}},
})
}
func StreamPush(m *ice.Message, arg ...string) {
AdminCmd(m, STREAM, PUSH, m.Option(ice.MSG_USERPOD), m.ShortKey(), arg)
}
func StreamPushRefresh(m *ice.Message, arg ...string) {
StreamPush(m.Spawn(ice.Maps{ice.SPACE_NOECHO: ice.TRUE}), kit.Simple(html.REFRESH, arg)...)
if strings.Contains(m.Option(ice.MSG_USERPOD), nfs.PT) {
AdminCmd(m.Spawn(ice.Maps{ice.SPACE_NOECHO: ice.TRUE}), SPACE, ice.DEV, STREAM, PUSH, m.Option(ice.MSG_USERPOD), m.ShortKey(), kit.Simple(html.REFRESH, arg))
}
}
func StreamPushRefreshConfirm(m *ice.Message, arg ...string) {
kit.If(len(arg) == 0, func() { arg = append(arg, m.Trans("refresh for new data ", "刷新列表,查看最新数据 ")) })
StreamPushRefresh(m, kit.Simple(html.CONFIRM, arg)...)
}

138
base/web/toast.go Normal file
View File

@ -0,0 +1,138 @@
package web
import (
"strings"
"time"
ice "shylinux.com/x/icebergs"
"shylinux.com/x/icebergs/base/cli"
"shylinux.com/x/icebergs/base/ctx"
"shylinux.com/x/icebergs/base/lex"
"shylinux.com/x/icebergs/base/mdb"
"shylinux.com/x/icebergs/base/nfs"
"shylinux.com/x/icebergs/base/web/html"
kit "shylinux.com/x/toolkits"
)
const (
TOAST_INIT = "init"
TOAST_DONE = "done"
)
const TOAST = "toast"
func init() {
Index.MergeCommands(ice.Commands{
TOAST: {Help: "进度条", Actions: ice.MergeActions(ice.Actions{
ctx.PREVIEW: &ice.Action{Hand: func(m *ice.Message, arg ...string) { ProcessHashPodCmd(m, arg...) }},
mdb.PRUNES: &ice.Action{Name: "prunes status=done"},
}, mdb.ClearOnExitHashAction(), mdb.StatusHashAction(html.CHECKBOX, ice.TRUE,
mdb.FIELD, "time,hash,type,name,text,cost,status,index,icons,agent,system,ip,ua",
)), Hand: func(m *ice.Message, arg ...string) {
mdb.HashSelect(m, arg...).PushAction(ctx.PREVIEW, mdb.REMOVE).Action(mdb.PRUNES)
m.Sort("status,cost", []string{"", TOAST_INIT, TOAST_DONE}, func(value string) int { return -int(kit.Duration(value)) })
}},
})
}
func toastCreate(m *ice.Message, arg ...string) (string, time.Time) {
return m.Cmdx(TOAST, mdb.CREATE, mdb.TYPE, kit.FuncName(2), mdb.NAME, toastTitle(m), mdb.STATUS, TOAST_INIT, ctx.INDEX, m.ShortKey(), ParseUA(m), arg, ice.OptionSilent()), time.Now()
}
func toastUpdate(m *ice.Message, h string, begin time.Time, arg ...string) string {
cost := kit.FmtDuration(time.Now().Sub(begin))
m.Cmd(TOAST, mdb.MODIFY, mdb.HASH, h, cli.COST, cost, arg, ice.OptionSilent())
return cost
}
var Icons = map[string]string{ice.PROCESS: "🕑", ice.FAILURE: "❌", ice.SUCCESS: "✅"}
func toastTitle(m *ice.Message) string {
return kit.GetValid(
func() string { return m.Option(ice.MSG_TITLE) },
func() string {
return kit.Keys(m.Option(ice.MSG_USERPOD0), m.Option(ice.MSG_USERPOD), ctx.ShortCmd(m.ShortKey()))
},
)
}
func toastContent(m *ice.Message, state string, arg ...ice.Any) string {
if len(arg) == 0 {
return kit.JoinWord(kit.Simple(Icons[state], m.Trans(kit.Select(ice.LIST, m.ActionKey()), ""), m.Trans(state, ""))...)
} else {
return kit.JoinWord(kit.Simple(Icons[state], arg)...)
}
}
func ToastSuccess(m *ice.Message, arg ...ice.Any) {
Toast(m, toastContent(m, ice.SUCCESS, arg...), "", cli.TIME_1s)
}
func ToastFailure(m *ice.Message, arg ...ice.Any) {
Toast(m, toastContent(m, ice.FAILURE, arg...), "", m.Option(ice.TOAST_DURATION, "-1")).Sleep(cli.TIME_3s)
}
func ToastProcess(m *ice.Message, arg ...ice.Any) func(...ice.Any) {
text := toastContent(m, ice.PROCESS, arg...)
h, begin := toastCreate(m, mdb.TEXT, text)
Toast(m, text, "", "-1", "", h)
Count(m, kit.FuncName(1), toastTitle(m), text)
return func(_arg ...ice.Any) {
if m.IsErr() {
return
}
kit.If(len(_arg) == 0, func() { _arg = arg })
text := toastContent(m, ice.SUCCESS, _arg...)
toastUpdate(m, h, begin, mdb.TEXT, text, mdb.STATUS, TOAST_DONE)
Toast(m, text, "", cli.TIME_3s, "", h)
}
}
func GoToastTable(m *ice.Message, key string, cb func(value ice.Maps)) *ice.Message {
if m.Length() == 0 {
return m
}
return GoToast(m, func(toast func(string, int, int)) []string {
m.Table(func(value ice.Maps, index, total int) { toast(value[key], index, total); cb(value) })
return nil
})
}
func GoToast(m *ice.Message, cb func(toast func(name string, count, total int)) []string) *ice.Message {
h, begin := toastCreate(m)
icon, _total := Icons[ice.PROCESS], 1
toast := func(name string, count, total int) {
kit.If(total == 0, func() { total = 1 })
text := kit.JoinWord(icon, kit.Select(ice.LIST, m.ActionKey()), name, strings.ReplaceAll(kit.FmtSize(count, total), "B", ""))
cost := toastUpdate(m, h, begin, mdb.TEXT, text, mdb.STATUS, kit.Select("", TOAST_DONE, count == total))
Toast(m, kit.JoinWord(text, cost), "", m.OptionDefault(ice.TOAST_DURATION, "-1"), count*100/total, h)
_total = total
}
if list := cb(toast); len(list) > 0 {
icon = Icons[ice.FAILURE]
m.Option(ice.TOAST_DURATION, cli.TIME_30s)
toast(kit.JoinWord(list...), len(list), _total)
m.Sleep(m.Option(ice.TOAST_DURATION))
} else {
icon = Icons[ice.SUCCESS]
m.Option(ice.TOAST_DURATION, cli.TIME_1s)
toast(ice.SUCCESS, _total, _total)
}
Count(m, kit.FuncName(1), toastTitle(m), kit.FmtDuration(time.Now().Sub(begin)))
return m
}
func Toast(m *ice.Message, text string, arg ...ice.Any) *ice.Message { // [title [duration [progress [hash]]]]
if len(arg) > 1 {
switch val := arg[1].(type) {
case string:
if value, err := time.ParseDuration(val); err == nil {
arg[1] = int(value / time.Millisecond)
}
}
}
kit.If(len(arg) == 0, func() { arg = append(arg, "") })
kit.If(len(arg) > 0 && arg[0] == "", func() { arg[0] = toastTitle(m) })
PushNoticeToast(m.Spawn("space.noecho", "true"), text, arg)
return m
}
func PushNoticeGrowXterm(m *ice.Message, title string, cmd ...ice.Any) {
PushCmdStream(m, title).Cmd(cli.SYSTEM, cmd)
}
func PushCmdStream(m *ice.Message, title string) *ice.Message {
m.Options(ctx.DISPLAY, html.PLUGIN_XTERM, cli.CMD_OUTPUT, nfs.NewWriteCloser(func(buf []byte) (int, error) {
PushNoticeGrow(m.Options(ice.MSG_TITLE, title, ice.MSG_COUNT, "0", ice.LOG_DEBUG, ice.FALSE, ice.LOG_DISABLE, ice.TRUE), strings.ReplaceAll(string(buf), lex.NL, "\r\n"))
return len(buf), nil
}, nil))
return m
}

View File

@ -2,47 +2,86 @@ package web
import ( import (
"net/http" "net/http"
"strings" "path"
ice "shylinux.com/x/icebergs" ice "shylinux.com/x/icebergs"
"shylinux.com/x/icebergs/base/lex" "shylinux.com/x/icebergs/base/cli"
"shylinux.com/x/icebergs/base/ctx"
"shylinux.com/x/icebergs/base/mdb" "shylinux.com/x/icebergs/base/mdb"
"shylinux.com/x/icebergs/base/nfs" "shylinux.com/x/icebergs/base/nfs"
"shylinux.com/x/icebergs/base/tcp" "shylinux.com/x/icebergs/base/web/html"
kit "shylinux.com/x/toolkits" kit "shylinux.com/x/toolkits"
) )
const TOKEN = "token" const TOKEN = "token"
func init() { func init() {
const (
GEN = "gen"
SET = "set"
CONFIRM = "confirm"
FILE = ".git-credentials"
LOCAL = "http://localhost:9020"
)
Index.MergeCommands(ice.Commands{ Index.MergeCommands(ice.Commands{
TOKEN: {Help: "令牌", Actions: ice.MergeActions(ice.Actions{ TOKEN: {Help: "令牌桶", Icon: "Keychain.png", Actions: ice.MergeActions(ice.Actions{
GEN: {Hand: func(m *ice.Message, arg ...string) { mdb.PRUNES: {Name: "prunes", Hand: func(m *ice.Message, arg ...string) {
m.Echo("请授权 %s 代码权限\n", m.Option(tcp.HOST)).EchoButton(CONFIRM) m.Cmds("").Table(func(value ice.Maps) {
if value[mdb.STATUS] != "valid" {
m.Cmd("", mdb.REMOVE, value)
}
})
}}, }},
CONFIRM: {Hand: func(m *ice.Message, arg ...string) { }, mdb.HashAction(mdb.SHORT, mdb.UNIQ, mdb.EXPIRE, mdb.MONTH, html.CHECKBOX, ice.TRUE)), Hand: func(m *ice.Message, arg ...string) {
if m.Warn(m.R.Method != http.MethodPost, ice.ErrNotAllow) { if mdb.HashSelect(m, arg...); len(arg) > 0 {
return m.EchoScript(kit.MergeURL2(m.Option(ice.MSG_USERWEB), nfs.PS, TOKEN, arg[0]))
} } else {
msg := m.Cmd("", mdb.CREATE, mdb.TYPE, Basic, mdb.NAME, m.Option(ice.MSG_USERNAME), mdb.TEXT, m.Option(tcp.HOST)) now := m.Time()
m.ProcessReplace(kit.MergeURL2(m.Option(tcp.HOST), ChatCmdPath(m, m.PrefixKey(), SET), list := map[string]bool{}
TOKEN, strings.Replace(UserHost(m), "://", kit.Format("://%s:%s@", m.Option(ice.MSG_USERNAME), msg.Result()), 1))) m.Table(func(value ice.Maps) {
}}, key := kit.Keys(value[mdb.TYPE], value[mdb.TEXT])
SET: {Hand: func(m *ice.Message, arg ...string) { if value[mdb.TIME] < now {
host, list := ice.Map{kit.ParseURL(m.Option(TOKEN)).Host: true}, []string{m.Option(TOKEN)} m.Push(mdb.STATUS, mdb.EXPIRED)
m.Cmd(nfs.CAT, kit.HomePath(FILE), func(line string) { } else if list[key] {
line = strings.ReplaceAll(line, "%3a", ":") m.Push(mdb.STATUS, mdb.INVALID)
kit.IfNoKey(host, kit.ParseURL(line).Host, func(p string) { list = append(list, line) }) } else {
}).Cmd(nfs.SAVE, kit.HomePath(FILE), strings.Join(list, lex.NL)+lex.NL) m.Push(mdb.STATUS, mdb.VALID)
m.ProcessClose() }
}}, list[key] = true
}, mdb.HashAction(mdb.SHORT, mdb.UNIQ, mdb.FIELD, "time,hash,type,name,text", mdb.EXPIRE, mdb.MONTH))}, })
m.Action(mdb.CREATE, mdb.PRUNES)
}
}},
}) })
} }
const (
DEV_REQUEST_TEXT = "devRequestText"
DEV_CREATE_TOKEN = "devCreateToken"
)
func DevTokenAction(name, origin string) ice.Actions {
return ice.Actions{
DEV_REQUEST_TEXT: {Hand: func(m *ice.Message, arg ...string) { m.Echo(UserHost(m)) }},
DEV_CREATE_TOKEN: {Hand: func(m *ice.Message, arg ...string) {}},
mdb.DEV_REQUEST: {Help: "请求", Icon: "bi bi-person-down", Hand: func(m *ice.Message, arg ...string) {
back := m.Options(ice.MSG_USERWEB, m.Option(ice.MSG_USERHOST)).MergePod("")
m.ProcessOpen(m.Options(ice.MSG_USERWEB, m.Option(origin), ice.MSG_USERPOD, "").MergePodCmd("", m.ShortKey(),
ctx.ACTION, mdb.DEV_CHOOSE, cli.BACK, back, cli.DAEMON, m.Option(ice.MSG_DAEMON),
m.OptionSimple(name), mdb.TEXT, m.Cmdx("", DEV_REQUEST_TEXT),
))
}},
mdb.DEV_CHOOSE: {Hand: func(m *ice.Message, arg ...string) {
m.EchoInfoButton(kit.JoinWord(m.ShortKey(), m.Cmdx(nfs.CAT, path.Join(nfs.SRC_TEMPLATE, "web.token", "saveto.html")), m.Option(cli.BACK)), mdb.DEV_RESPONSE)
}},
mdb.DEV_RESPONSE: {Help: "确认", Hand: func(m *ice.Message, arg ...string) {
if !m.WarnNotAllow(m.Option(ice.MSG_METHOD) != http.MethodPost) {
m.ProcessReplace(m.ParseLink(m.Option(cli.BACK)).MergePodCmd("", m.ShortKey(), ctx.ACTION, mdb.DEV_CONFIRM, m.OptionSimple(cli.DAEMON),
m.OptionSimple(name), TOKEN, m.Cmdx(TOKEN, mdb.CREATE, mdb.TYPE, m.CommandKey(), mdb.NAME, m.Option(ice.MSG_USERNAME), m.OptionSimple(mdb.TEXT))))
}
}},
mdb.DEV_CONFIRM: {Hand: func(m *ice.Message, arg ...string) {
m.EchoInfoButton(kit.JoinWord(m.ShortKey(), m.Cmdx(nfs.CAT, path.Join(nfs.SRC_TEMPLATE, "web.token", "savefrom.html")), m.Option(name)), mdb.DEV_CREATE)
}},
mdb.DEV_CREATE: {Help: "创建", Hand: func(m *ice.Message, arg ...string) {
if !m.WarnNotAllow(m.Option(ice.MSG_METHOD) != http.MethodPost) {
defer kit.If(m.Option(cli.DAEMON), func(p string) { m.Cmd(SPACE, p, html.REFRESH) })
mdb.HashModify(m, m.OptionSimple(name, TOKEN))
m.Cmdy("", DEV_CREATE_TOKEN).ProcessClose()
}
}},
}
}

View File

@ -29,6 +29,7 @@ func (f *Frame) Begin(m *ice.Message, arg ...string) {}
func (f *Frame) Start(m *ice.Message, arg ...string) { func (f *Frame) Start(m *ice.Message, arg ...string) {
f.Message, f.Server = m, &http.Server{Handler: f} f.Message, f.Server = m, &http.Server{Handler: f}
list := map[*ice.Context]string{} list := map[*ice.Context]string{}
m.Options(ice.MSG_LANGUAGE, "")
m.Travel(func(p *ice.Context, c *ice.Context) { m.Travel(func(p *ice.Context, c *ice.Context) {
f, ok := c.Server().(*Frame) f, ok := c.Server().(*Frame)
if !ok || f.ServeMux != nil { if !ok || f.ServeMux != nil {
@ -51,7 +52,7 @@ func (f *Frame) Start(m *ice.Message, arg ...string) {
f.HandleFunc(key, func(w http.ResponseWriter, r *http.Request) { f.HandleFunc(key, func(w http.ResponseWriter, r *http.Request) {
m.Spawn(key, cmd, c, w, r).TryCatch(true, func(msg *ice.Message) { _serve_handle(key, cmd, msg, w, r) }) m.Spawn(key, cmd, c, w, r).TryCatch(true, func(msg *ice.Message) { _serve_handle(key, cmd, msg, w, r) })
}) })
ice.Info.Route[path.Join(list[c], key)+kit.Select("", nfs.PS, strings.HasSuffix(key, nfs.PS))] = ctx.FileURI(cmd.FileLine()) ice.Info.Route[path.Join(list[c], key)+kit.Select("", nfs.PS, strings.HasSuffix(key, nfs.PS))] = m.FileURI(cmd.FileLine())
}(key, cmd) }(key, cmd)
} }
}) })
@ -61,8 +62,12 @@ func (f *Frame) Start(m *ice.Message, arg ...string) {
default: default:
m.Cmd(tcp.SERVER, tcp.LISTEN, mdb.TYPE, HTTP, mdb.NAME, logs.FileLine(1), m.OptionSimple(tcp.HOST, tcp.PORT), func(l net.Listener) { m.Cmd(tcp.SERVER, tcp.LISTEN, mdb.TYPE, HTTP, mdb.NAME, logs.FileLine(1), m.OptionSimple(tcp.HOST, tcp.PORT), func(l net.Listener) {
defer mdb.HashCreateDeferRemove(m, m.OptionSimple(mdb.NAME, tcp.PROTO), arg, cli.STATUS, tcp.START)() defer mdb.HashCreateDeferRemove(m, m.OptionSimple(mdb.NAME, tcp.PROTO), arg, cli.STATUS, tcp.START)()
gdb.Event(m, SERVE_START, arg) m.GoSleep("300ms", func() { gdb.Event(m.Spawn(), SERVE_START, arg) })
m.Warn(f.Server.Serve(l)) if m.Option(tcp.PORT) == tcp.PORT_443 {
m.WarnNotValid(f.Server.ServeTLS(l, nfs.ETC_CERT_PEM, nfs.ETC_CERT_KEY))
} else {
m.WarnNotValid(f.Server.Serve(l))
}
}) })
kit.If(m.IsErr(), func() { fmt.Println(); fmt.Println(m.Result()); m.Cmd(ice.QUIT) }) kit.If(m.IsErr(), func() { fmt.Println(); fmt.Println(m.Result()); m.Cmd(ice.QUIT) })
} }
@ -78,14 +83,16 @@ var Index = &ice.Context{Name: WEB, Help: "网络模块"}
func init() { func init() {
ice.Index.Register(Index, &Frame{}, ice.Index.Register(Index, &Frame{},
BROAD, SERVE, DREAM, ROUTE, SPACE, BROAD, SERVE, SPACE, DREAM, ROUTE,
TOKEN, SHARE, CACHE, SPIDE, COUNT, SHARE, TOKEN, STATS, COUNT, TOAST,
SPIDE, CACHE, STORE, ADMIN, MATRIX,
STREAM,
) )
} }
func ApiAction(arg ...string) ice.Actions { return ice.Actions{kit.Select(nfs.PS, arg, 0): {}} } func ApiAction(arg ...string) ice.Actions { return ice.Actions{kit.Select(nfs.PS, arg, 0): {}} }
func ApiWhiteAction() ice.Actions { func ApiWhiteAction() ice.Actions {
return ice.MergeActions(ApiAction(), aaa.WhiteAction()) return ice.MergeActions(ApiAction(), aaa.WhiteAction(""))
} }
func Prefix(arg ...string) string { func Prefix(arg ...string) string {
for i, k := range arg { for i, k := range arg {
@ -97,5 +104,8 @@ func Prefix(arg ...string) string {
return kit.Keys(WEB, arg) return kit.Keys(WEB, arg)
} }
func X(arg ...string) string { return "/x/" + path.Join(arg...) }
func S(arg ...string) string { return "/s/" + path.Join(arg...) }
func C(arg ...string) string { return "/c/" + ctx.ShortCmd(path.Join(arg...)) }
func P(arg ...string) string { return path.Join(nfs.PS, path.Join(arg...)) } func P(arg ...string) string { return path.Join(nfs.PS, path.Join(arg...)) }
func PP(arg ...string) string { return P(arg...) + nfs.PS } func PP(arg ...string) string { return P(arg...) + nfs.PS }

View File

@ -452,8 +452,6 @@ func (s *Stack) calls(m *ice.Message, obj Any, key string, cb func(*Frame, Funct
} }
m.Debug("calls %s %s %s %#v", Format(s), Format(obj), key, arg) m.Debug("calls %s %s %s %#v", Format(s), Format(obj), key, arg)
kit.For(arg, func(i int, v Any) { arg[i] = Trans(arg[i]) }) kit.For(arg, func(i int, v Any) { arg[i] = Trans(arg[i]) })
m.Debug("calls %s %s %s %s", Format(s), Format(obj), key, Format(arg...))
m.Debug("calls %s %s %s %#v", Format(s), Format(obj), key, arg)
return Wraps(obj(m, kit.Format(key), arg...)) return Wraps(obj(m, kit.Format(key), arg...))
case func(): case func():
obj() obj()
@ -610,7 +608,7 @@ func StackHandler(m *ice.Message, arg ...string) {
if len(script) > 0 { if len(script) > 0 {
p := ice.USR_SCRIPT + m.PrefixKey() + nfs.PS + "list.js" p := ice.USR_SCRIPT + m.PrefixKey() + nfs.PS + "list.js"
m.Cmd(nfs.SAVE, p, kit.Dict(nfs.CONTENT, strings.Join(script, lex.NL))) m.Cmd(nfs.SAVE, p, kit.Dict(nfs.CONTENT, strings.Join(script, lex.NL)))
s.value(m, "_script", "/require/"+p) s.value(m, "_script", nfs.P+p)
} }
cmd := m.Commands("") cmd := m.Commands("")
kit.For(s.peekf().value, func(k string, v Any) { kit.For(s.peekf().value, func(k string, v Any) {

Some files were not shown because too many files have changed in this diff Show More