mirror of
https://github.com/MickMake/GoSungrow.git
synced 2025-06-17 12:30:49 +02:00
Committed v2.3.0
This commit is contained in:
parent
0daafb1d6d
commit
d24e69975d
1127
.idea/workspace.xml
generated
1127
.idea/workspace.xml
generated
File diff suppressed because it is too large
Load Diff
341
EXAMPLES.md
341
EXAMPLES.md
@ -0,0 +1,341 @@
|
|||||||
|
# Examples of all known working commands
|
||||||
|
|
||||||
|
## Authentication
|
||||||
|
|
||||||
|
GoSungrow api login
|
||||||
|
|
||||||
|
|
||||||
|
## High-level info commands
|
||||||
|
|
||||||
|
```
|
||||||
|
Usage:
|
||||||
|
GoSungrow info [command]
|
||||||
|
|
||||||
|
Available Commands:
|
||||||
|
get Info - Get info from iSolarCloud (table)
|
||||||
|
raw Info - Get info from iSolarCloud (raw)
|
||||||
|
json Info - Get info from iSolarCloud (json)
|
||||||
|
csv Info - Get info from iSolarCloud (json)
|
||||||
|
put Info - Set info on iSolarCloud
|
||||||
|
```
|
||||||
|
|
||||||
|
```
|
||||||
|
Usage:
|
||||||
|
GoSungrow info get [command]
|
||||||
|
|
||||||
|
Available Commands:
|
||||||
|
point-names Info - Get iSolarCloud point names.
|
||||||
|
mqtt Info - Get iSolarCloud MQTT service login details.
|
||||||
|
search-point-names Info - Get iSolarCloud search point names.
|
||||||
|
devices Info - Get iSolarCloud devices.
|
||||||
|
models Info - Get ALL iSolarCloud models.
|
||||||
|
templates Info - Get all defined templates.
|
||||||
|
template-points Info - List data points used in report template.
|
||||||
|
device-points Info - List all available device data points.
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
## Get device details
|
||||||
|
|
||||||
|
GoSungrow info get device
|
||||||
|
GoSungrow info get search-point-names
|
||||||
|
GoSungrow info get models
|
||||||
|
|
||||||
|
|
||||||
|
## Templates
|
||||||
|
|
||||||
|
```
|
||||||
|
GoSungrow info get templates
|
||||||
|
┏━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━┓
|
||||||
|
┃ Template Id ┃ Template Name ┃ Update On ┃
|
||||||
|
┣━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━━┫
|
||||||
|
┃ 8042 │ Critical │ 2022-02-15 13:00:28 ┃
|
||||||
|
┃ 8041 │ extras │ 2022-02-15 09:40:04 ┃
|
||||||
|
┃ 8036 │ C │ 2022-02-15 09:31:35 ┃
|
||||||
|
┃ 8039 │ v │ 2022-02-15 09:31:10 ┃
|
||||||
|
┃ 8040 │ A │ 2022-02-15 09:30:56 ┃
|
||||||
|
┃ 8034 │ Percent │ 2022-02-15 09:30:41 ┃
|
||||||
|
┃ 8038 │ MWh │ 2022-02-15 09:09:22 ┃
|
||||||
|
┃ 8037 │ MW │ 2022-02-15 09:03:22 ┃
|
||||||
|
┃ 8033 │ kW │ 2022-02-15 09:01:19 ┃
|
||||||
|
┃ 8035 │ Hours │ 2022-02-15 08:55:56 ┃
|
||||||
|
┃ 8031 │ kWh │ 2022-02-15 07:57:36 ┃
|
||||||
|
┃ 7981 │ Power │ 2022-02-09 10:03:40 ┃
|
||||||
|
┗━━━━━━━━━━━━━┷━━━━━━━━━━━━━━━┷━━━━━━━━━━━━━━━━━━━━━┛
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
## High-level data commands
|
||||||
|
|
||||||
|
```
|
||||||
|
Usage:
|
||||||
|
GoSungrow data [command]
|
||||||
|
|
||||||
|
Available Commands:
|
||||||
|
get Data - Get high-level data from iSolarCloud (table)
|
||||||
|
raw Data - Get high-level data from iSolarCloud (raw)
|
||||||
|
json Data - Get high-level data from iSolarCloud (json)
|
||||||
|
csv Data - Get high-level data from iSolarCloud (json)
|
||||||
|
graph Data - Get high-level data from iSolarCloud (graph)
|
||||||
|
```
|
||||||
|
|
||||||
|
```
|
||||||
|
Usage:
|
||||||
|
GoSungrow data get [command]
|
||||||
|
|
||||||
|
Available Commands:
|
||||||
|
stats Data - Get current inverter stats, (last 5 minutes).
|
||||||
|
template Data - Get data from report template.
|
||||||
|
points Data - Get points data for a specific date.
|
||||||
|
real-time Data - Get iSolarCloud real-time data.
|
||||||
|
psdetails Data - Get iSolarCloud ps details.
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
## General
|
||||||
|
|
||||||
|
```
|
||||||
|
GoSungrow data get stats
|
||||||
|
┏━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━┳━━━━━━┓
|
||||||
|
┃ Date ┃ Point Id ┃ Point Name ┃ Value ┃ Unit ┃
|
||||||
|
┣━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━╇━━━━━━┫
|
||||||
|
┃ 2022-10-08 09:55:00 │ 1129147.0 │ Co2 Reduce │ 0 │ kg ┃
|
||||||
|
┃ 2022-10-08 09:55:00 │ 1129147.0 │ Co2 Reduce Total │ 5819 │ kg ┃
|
||||||
|
┃ 2022-10-08 09:55:00 │ 1129147.0 │ Curr Power │ 788 │ W ┃
|
||||||
|
┃ 2022-10-08 09:55:00 │ 1129147.0 │ Daily Irradiation │ -- │ ┃
|
||||||
|
┃ 2022-10-08 09:55:00 │ 1129147.0 │ Equivalent Hour │ 0.27 │ Hour ┃
|
||||||
|
|
||||||
|
...
|
||||||
|
|
||||||
|
┃ 2022-10-08 09:55:00 │ 1171348.0 │ Today Income │ 0.397 │ AUD ┃
|
||||||
|
┃ 2022-10-08 09:55:00 │ 1171348.0 │ Total Capacity │ │ ┃
|
||||||
|
┃ 2022-10-08 09:55:00 │ 1171348.0 │ Total Energy │ 176.5 │ kWh ┃
|
||||||
|
┃ 2022-10-08 09:55:00 │ 1171348.0 │ Total Income │ 35.806 │ AUD ┃
|
||||||
|
┃ 2022-10-08 09:55:00 │ 1171348.0 │ Use Energy │ 6.7 │ kWh ┃
|
||||||
|
┗━━━━━━━━━━━━━━━━━━━━━┷━━━━━━━━━━━┷━━━━━━━━━━━━━━━━━━━━━━━━━━━┷━━━━━━━━━┷━━━━━━┛
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
## Templates
|
||||||
|
|
||||||
|
```
|
||||||
|
GoSungrow info get template-points 7981
|
||||||
|
┏━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━┓
|
||||||
|
┃ PointStruct Id ┃ Description ┃ Unit ┃
|
||||||
|
┣━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━┫
|
||||||
|
┃ 1129147_11_0_0.p83032 │ Meter AC Power │ kW ┃
|
||||||
|
┃ 1129147_11_0_0.p83119 │ Daily Feed-in Energy (PV) │ kWh ┃
|
||||||
|
┃ 1129147_11_0_0.p83549 │ Grid active power │ kW ┃
|
||||||
|
┃ 1129147_11_0_0.p83002 │ Inverter AC Power │ kW ┃
|
||||||
|
┃ 1129147_11_0_0.p83011 │ Meter E-daily Consumption │ kWh ┃
|
||||||
|
┃ 1129147_11_0_0.p83022 │ Daily Yield of Plant │ kWh ┃
|
||||||
|
┃ 1129147_11_0_0.p83006 │ Meter Daily Yield │ kWh ┃
|
||||||
|
┃ 1129147_11_0_0.p83033 │ Plant Power │ kW ┃
|
||||||
|
┃ 1129147_11_0_0.p83072 │ Daily Feed-in Energy │ kWh ┃
|
||||||
|
┃ 1129147_11_0_0.p83097 │ Daily Load Energy Consumption from PV │ kWh ┃
|
||||||
|
┃ 1129147_11_0_0.p83102 │ Daily Purchased Energy │ kWh ┃
|
||||||
|
┃ 1129147_14_1_1.p13028 │ Daily Battery Charging Energy │ kWh ┃
|
||||||
|
┃ 1129147_14_1_1.p13112 │ Daily PV Yield │ kWh ┃
|
||||||
|
┃ 1129147_14_1_1.p13147 │ Daily Purchased Energy │ kWh ┃
|
||||||
|
┃ 1129147_14_1_1.p13173 │ Daily Feed-in Energy (PV) │ kWh ┃
|
||||||
|
┃ 1129147_14_1_1.p13174 │ Daily Battery Charging Energy from PV │ kWh ┃
|
||||||
|
┃ 1129147_14_1_1.p13199 │ Daily Load Energy Consumption │ kWh ┃
|
||||||
|
┃ 1129147_14_1_1.p13116 │ Daily Load Energy Consumption from PV │ kWh ┃
|
||||||
|
┃ 1129147_14_1_1.p13122 │ Daily Feed-in Energy │ kWh ┃
|
||||||
|
┗━━━━━━━━━━━━━━━━━━━━━━━┷━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┷━━━━━━┛
|
||||||
|
```
|
||||||
|
|
||||||
|
```
|
||||||
|
GoSungrow data get template 8042 20220212
|
||||||
|
┏━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━┳━━━━━━━┓
|
||||||
|
┃ Date/Time ┃ Point Id ┃ Point Name ┃ Value ┃ Units ┃
|
||||||
|
┣━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━╇━━━━━━━┫
|
||||||
|
┃ 2022-02-12 00:00:00 │ 1129147_11_0_0.p83106 │ Load Power │ 396 │ kW ┃
|
||||||
|
┃ 2022-02-12 00:05:00 │ 1129147_11_0_0.p83106 │ Load Power │ 480 │ kW ┃
|
||||||
|
┃ 2022-02-12 00:10:00 │ 1129147_11_0_0.p83106 │ Load Power │ 487 │ kW ┃
|
||||||
|
┃ 2022-02-12 00:15:00 │ 1129147_11_0_0.p83106 │ Load Power │ 497 │ kW ┃
|
||||||
|
┃ 2022-02-12 00:20:00 │ 1129147_11_0_0.p83106 │ Load Power │ 524 │ kW ┃
|
||||||
|
┃ 2022-02-12 00:25:00 │ 1129147_11_0_0.p83106 │ Load Power │ 541 │ kW ┃
|
||||||
|
┃ 2022-02-12 00:30:00 │ 1129147_11_0_0.p83106 │ Load Power │ 554 │ kW ┃
|
||||||
|
|
||||||
|
...
|
||||||
|
|
||||||
|
┃ 2022-02-12 23:55:00 │ 1129147_14_1_1.p13019 │ Internal Air Temperature │ 19.4 │ ℃ ┃
|
||||||
|
┃ 2022-02-13 00:00:00 │ 1129147_14_1_1.p13019 │ Internal Air Temperature │ 22.3 │ ℃ ┃
|
||||||
|
┗━━━━━━━━━━━━━━━━━━━━━┷━━━━━━━━━━━━━━━━━━━━━━━┷━━━━━━━━━━━━━━━━━━━━━━━━━━━━┷━━━━━━━━━━━━━┷━━━━━━━┛
|
||||||
|
```
|
||||||
|
|
||||||
|
GoSungrow data graph template 8042 20220212 '{"search_string":"p13019","min_left_axis":-6000,"max_left_axis":12000}'
|
||||||
|
GoSungrow data graph template 8042 20220212 '{"search_string":"p13019"}'
|
||||||
|
GoSungrow data graph template 8042 20220212 '{"search_string":"p83106","min_left_axis":-6000,"max_left_axis":12000}'
|
||||||
|
GoSungrow data graph template 8042 20220212 '{"search_string":"p83106"}'
|
||||||
|
GoSungrow data graph template 8042 20220212 '{"title":"Testing 1. 2. 3.","time_column":"1","value_column":"4","search_column":"3","search_string":"p83106","file_name":"foo.png"}'
|
||||||
|
GoSungrow data graph template 8042 20220212 '{"title":"Testing 1. 2. 3.","time_column":1,"value_column":4,"search_column":2,"search_string":"p13019","min_left_axis":0,"max_left_axis":0}'
|
||||||
|
GoSungrow data graph template 8042 20220212 '{"title":"Testing 1. 2. 3.","time_column":1,"value_column":4,"search_column":2,"search_string":"p13149","min_left_axis":0,"max_left_axis":0}'
|
||||||
|
GoSungrow data graph template 8042 20220212 '{"title":"Testing 1. 2. 3.","time_column":1,"value_column":4,"search_column":2,"search_string":"p83106","file_name":"foo.png"}'
|
||||||
|
GoSungrow data graph template 8042 20220212 '{"title":"Testing 1. 2. 3.","time_column":1,"value_column":4,"search_column":2,"search_string":"p83106","min_left_axis":-6000,"max_left_axis":1000}'
|
||||||
|
GoSungrow data graph template 8042 20220212 '{"title":"Testing 1. 2. 3.","time_column":1,"value_column":4,"search_column":2,"search_string":"p83106","min_left_axis":-6000,"max_left_axis":12000}'
|
||||||
|
GoSungrow data graph template 8042 20220212 '{"title":"Testing 1. 2. 3.","time_column":1,"value_column":4,"search_column":2,"search_string":"p83106","min_left_axis":-6000,"max_left_axis":42000}'
|
||||||
|
GoSungrow data graph template 8042 20220212 '{"title":"Testing 1. 2. 3.","time_column":1,"value_column":4,"search_column":2,"search_string":"p83106","min_left_axis":0,"max_left_axis":0}'
|
||||||
|
GoSungrow data graph template 8042 20220212 '{"title":"Testing 1. 2. 3.","time_column":1,"value_column":4,"search_column":3,"search_string":"p83106","file_name":"foo.png"}'
|
||||||
|
GoSungrow data raw template '' 20220201
|
||||||
|
GoSungrow data save template '' 20220201
|
||||||
|
GoSungrow data save template 8042 20220212
|
||||||
|
|
||||||
|
|
||||||
|
## Hacking
|
||||||
|
|
||||||
|
|
||||||
|
## Base API commands
|
||||||
|
|
||||||
|
```
|
||||||
|
Usage:
|
||||||
|
GoSungrow api [command]
|
||||||
|
|
||||||
|
Examples:
|
||||||
|
GoSungrow api login
|
||||||
|
GoSungrow api get <endpoint> <args>
|
||||||
|
GoSungrow api raw <endpoint> <args>
|
||||||
|
GoSungrow api save <endpoint> <args>
|
||||||
|
GoSungrow api put <endpoint> <args>
|
||||||
|
|
||||||
|
Available Commands:
|
||||||
|
ls List iSolarCloud api endpoints/areas
|
||||||
|
login Login to iSolarCloud
|
||||||
|
get Get details from iSolarCloud
|
||||||
|
raw Raw details from iSolarCloud
|
||||||
|
save Save details from iSolarCloud as JSON
|
||||||
|
put Put details onto iSolarCloud
|
||||||
|
```
|
||||||
|
|
||||||
|
## Get device details
|
||||||
|
|
||||||
|
GoSungrow api get getPsList
|
||||||
|
GoSungrow api get getPsListByName
|
||||||
|
GoSungrow api get getPsDataSupplementTaskList
|
||||||
|
GoSungrow api get getPsUser
|
||||||
|
GoSungrow api get queryPsIdList
|
||||||
|
GoSungrow api get getInstallInfoList
|
||||||
|
GoSungrow api get getPsListStaticData
|
||||||
|
GoSungrow api get queryAllPsIdAndName
|
||||||
|
GoSungrow api get getPsDetail '{"ps_id":"1171348"}'
|
||||||
|
GoSungrow api get getPsDetailWithPsType '{"ps_id":"1171348"}'
|
||||||
|
GoSungrow api get getPsHealthState '{"ps_id":"1171348"}'
|
||||||
|
GoSungrow api get getPsWeatherList '{"ps_id":"1171348"}'
|
||||||
|
GoSungrow api get queryDeviceList '{"ps_id":"1171348"}'
|
||||||
|
GoSungrow api get queryDeviceListByUserId '{"ps_id":"1171348"}'
|
||||||
|
GoSungrow api get queryDeviceListForApp '{"ps_id":"1171348"}'
|
||||||
|
GoSungrow api get findPsType '{"ps_id":"1171348"}'
|
||||||
|
GoSungrow api get getDeviceList '{"ps_id":"1171348"}'
|
||||||
|
GoSungrow api get getIncomeSettingInfos '{"ps_id":"1171348"}'
|
||||||
|
GoSungrow api get getPowerChargeSettingInfo '{"ps_id":"1171348"}'
|
||||||
|
GoSungrow api get getPowerStationInfo '{"ps_id":"1171348"}'
|
||||||
|
GoSungrow api get WebAppService.getDeviceUuid '{"ps_key":"1171348"}'
|
||||||
|
GoSungrow api get getPowerStationForHousehold '{"ps_id":"1171348"}'
|
||||||
|
|
||||||
|
|
||||||
|
## Get device data
|
||||||
|
|
||||||
|
GoSungrow api get energyTrend
|
||||||
|
GoSungrow api get getKpiInfo
|
||||||
|
GoSungrow api get queryPsProfit '{"date_id":"20221001","date_type":"1","ps_id":"1171348"}'
|
||||||
|
GoSungrow api get getPowerStationData '{"date_id":"20221001","date_type":"1","ps_id":"1171348"}'
|
||||||
|
GoSungrow api get getHouseholdStoragePsReport '{"date_id":"20221001","date_type":"1","ps_id":"1171348"}'
|
||||||
|
GoSungrow api get queryPsProfit '{"date_id":"202210","date_type":"2","ps_id":"1171348"}'
|
||||||
|
GoSungrow api get getPowerStationData '{"date_id":"202210","date_type":"2","ps_id":"1171348"}'
|
||||||
|
GoSungrow api get getHouseholdStoragePsReport '{"date_id":"202210","date_type":"2","ps_id":"1171348"}'
|
||||||
|
GoSungrow api get queryPsProfit '{"date_id":"2022","date_type":"3","ps_id":"1171348"}'
|
||||||
|
GoSungrow api get getPowerStationData '{"date_id":"2022","date_type":"3","ps_id":"1171348"}'
|
||||||
|
GoSungrow api get getHouseholdStoragePsReport '{"date_id":"2022","date_type":"3","ps_id":"1171348"}'
|
||||||
|
GoSungrow api get getPowerTrendDayData '{"BeginTime":"20221004"}'
|
||||||
|
GoSungrow api get getPowerStatistics '{"ps_id":"1171348"}'
|
||||||
|
GoSungrow api get WebAppService.showPSView '{"ps_id":"1171348"}'
|
||||||
|
|
||||||
|
|
||||||
|
## Reports
|
||||||
|
|
||||||
|
GoSungrow api get getPsReport '{"report_type":"1","date_id":"20220201","date_type":"1","ps_id":"1171348"}'
|
||||||
|
GoSungrow api get getPsReport '{"report_type":"1","date_id":"20220201","date_type":"2","ps_id":"1171348"}'
|
||||||
|
GoSungrow api get getPsReport '{"report_type":"1","date_id":"20220201","date_type":"3","ps_id":"1171348"}'
|
||||||
|
GoSungrow api get reportList '{"ps_id":"1171348","report_type":"1"}'
|
||||||
|
GoSungrow api get reportList '{"ps_id":"1171348","report_type":"2"}'
|
||||||
|
GoSungrow api get reportList '{"ps_id":"1171348","report_type":"3"}'
|
||||||
|
GoSungrow api get reportList '{"ps_id":"1171348","report_type":"4"}'
|
||||||
|
|
||||||
|
|
||||||
|
## Templates
|
||||||
|
|
||||||
|
GoSungrow api get template 20220202
|
||||||
|
GoSungrow api get template 8042 20220212
|
||||||
|
GoSungrow api get getTemplateList
|
||||||
|
GoSungrow api get WebAppService.queryUserCurveTemplateData '{"template_id":"8042","date_type":"1","start_time":"20220223000000","end_time":"20220223235900"}'
|
||||||
|
|
||||||
|
|
||||||
|
## User/installer/support info
|
||||||
|
|
||||||
|
GoSungrow api get getUserList
|
||||||
|
GoSungrow api get getUserPsOrderList
|
||||||
|
GoSungrow api get getPhotoInfo
|
||||||
|
GoSungrow api get getOrgListByName
|
||||||
|
GoSungrow api get getOrgListByUserId
|
||||||
|
GoSungrow api get getOrgListForUser
|
||||||
|
GoSungrow api get queryUserList
|
||||||
|
GoSungrow api get getInstallerInfoByDealerOrgCodeOrId '{"dealer_org_code":"AUSCEKK7"}'
|
||||||
|
GoSungrow api get getInstallerInfoByDealerOrgCodeOrId '{"org_id":"362245"}'
|
||||||
|
GoSungrow api get getInstallerInfoByDealerOrgCodeOrId '{"org_id":"80384"}'
|
||||||
|
GoSungrow api get getInstallerInfoByDealerOrgCodeOrId '{"org_id":"80393"}'
|
||||||
|
GoSungrow api get getInstallerInfoByDealerOrgCodeOrId '{"org_id":"300977"}'
|
||||||
|
|
||||||
|
|
||||||
|
## Meta-data
|
||||||
|
|
||||||
|
GoSungrow api get getDeviceTypeInfoList
|
||||||
|
GoSungrow api get getDeviceTypeList
|
||||||
|
GoSungrow api get getInvertDataList
|
||||||
|
GoSungrow api get getModuleLogTaskList
|
||||||
|
GoSungrow api get powerDevicePointList
|
||||||
|
GoSungrow api get getPowerDevicePointNames '{"device_type":"1"}'
|
||||||
|
GoSungrow api get getPowerDevicePointNames '{"device_type":"2"}'
|
||||||
|
GoSungrow api get getPowerDevicePointNames '{"device_type":"7"}'
|
||||||
|
GoSungrow api get getDeviceModelInfoList
|
||||||
|
GoSungrow api get queryUnitList
|
||||||
|
GoSungrow api get getPowerSettingCharges
|
||||||
|
GoSungrow api get getPowerDevicePointNames '{"device_type":"1"}'
|
||||||
|
GoSungrow api get getPowerDeviceModelTechList '{"device_type":"1"}'
|
||||||
|
GoSungrow api get getPowerDevicePointInfo '{"id":"1"}'
|
||||||
|
|
||||||
|
|
||||||
|
## Task commands
|
||||||
|
|
||||||
|
GoSungrow api get queryBatchCreatePsTaskList
|
||||||
|
GoSungrow api get getPowerDeviceSetTaskDetailList '{"query_type":"2","task_id":"1","uuid":"844763"}'
|
||||||
|
GoSungrow api get getPowerDeviceSetTaskDetailList '{"query_type":"7","task_id":"1","uuid":"844763"}'
|
||||||
|
GoSungrow api get getPowerDeviceSetTaskDetailList '{"size":0,"curPage":0}'
|
||||||
|
GoSungrow api get getPowerDeviceSetTaskList '{"size":0,"curPage":0}'
|
||||||
|
GoSungrow api get getPowerDeviceSetTaskList '{"size":0,"curPage":1}'
|
||||||
|
GoSungrow api get getRemoteUpgradeSubTasksList '{"query_type":"1","task_id":"1577700"}'
|
||||||
|
GoSungrow api get getRemoteUpgradeTaskList '{"ps_id_list":"1171348"}'
|
||||||
|
|
||||||
|
|
||||||
|
## Misc commands
|
||||||
|
|
||||||
|
GoSungrow api get getDevicePoints '{"point_id":"13003"}'
|
||||||
|
GoSungrow api get getPowerPictureList
|
||||||
|
|
||||||
|
|
||||||
|
## Hacking
|
||||||
|
|
||||||
|
GoSungrow api get checkUnitStatus
|
||||||
|
GoSungrow api get getAllPowerDeviceSetName
|
||||||
|
GoSungrow api get getAreaList
|
||||||
|
GoSungrow api get getCloudList
|
||||||
|
GoSungrow api get getConfigList
|
||||||
|
GoSungrow api get getDeviceInfo
|
||||||
|
GoSungrow api get getOSSConfig
|
||||||
|
GoSungrow api get getOssObjectStream
|
||||||
|
GoSungrow api get getEncryptPublicKey
|
||||||
|
GoSungrow api get getFaultCount
|
||||||
|
GoSungrow api get getFaultDetail '{"fault_code":"34"}'
|
||||||
|
GoSungrow api get getFaultMsgByFaultCode '{"fault_code":"703"}'
|
||||||
|
GoSungrow api get getFaultMsgListWithYYYYMM
|
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"appkey": "93D72E60331ABDCDC7B39ADC2D1F32B3",
|
"appkey": "93D72E60331ABDCDC7B39ADC2D1F32B3",
|
||||||
"config": "/Users/mick/.GoSungrow/config.json",
|
"config": "",
|
||||||
"debug": false,
|
"debug": false,
|
||||||
"host": "https://augateway.isolarcloud.com",
|
"host": "https://augateway.isolarcloud.com",
|
||||||
"password": "",
|
"password": "",
|
||||||
|
@ -0,0 +1,341 @@
|
|||||||
|
# Examples of all known working commands
|
||||||
|
|
||||||
|
## Authentication
|
||||||
|
|
||||||
|
GoSungrow api login
|
||||||
|
|
||||||
|
|
||||||
|
## High-level info commands
|
||||||
|
|
||||||
|
```
|
||||||
|
Usage:
|
||||||
|
GoSungrow info [command]
|
||||||
|
|
||||||
|
Available Commands:
|
||||||
|
get Info - Get info from iSolarCloud (table)
|
||||||
|
raw Info - Get info from iSolarCloud (raw)
|
||||||
|
json Info - Get info from iSolarCloud (json)
|
||||||
|
csv Info - Get info from iSolarCloud (json)
|
||||||
|
put Info - Set info on iSolarCloud
|
||||||
|
```
|
||||||
|
|
||||||
|
```
|
||||||
|
Usage:
|
||||||
|
GoSungrow info get [command]
|
||||||
|
|
||||||
|
Available Commands:
|
||||||
|
point-names Info - Get iSolarCloud point names.
|
||||||
|
mqtt Info - Get iSolarCloud MQTT service login details.
|
||||||
|
search-point-names Info - Get iSolarCloud search point names.
|
||||||
|
devices Info - Get iSolarCloud devices.
|
||||||
|
models Info - Get ALL iSolarCloud models.
|
||||||
|
templates Info - Get all defined templates.
|
||||||
|
template-points Info - List data points used in report template.
|
||||||
|
device-points Info - List all available device data points.
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
## Get device details
|
||||||
|
|
||||||
|
GoSungrow info get device
|
||||||
|
GoSungrow info get search-point-names
|
||||||
|
GoSungrow info get models
|
||||||
|
|
||||||
|
|
||||||
|
## Templates
|
||||||
|
|
||||||
|
```
|
||||||
|
GoSungrow info get templates
|
||||||
|
┏━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━┓
|
||||||
|
┃ Template Id ┃ Template Name ┃ Update On ┃
|
||||||
|
┣━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━━┫
|
||||||
|
┃ 8042 │ Critical │ 2022-02-15 13:00:28 ┃
|
||||||
|
┃ 8041 │ extras │ 2022-02-15 09:40:04 ┃
|
||||||
|
┃ 8036 │ C │ 2022-02-15 09:31:35 ┃
|
||||||
|
┃ 8039 │ v │ 2022-02-15 09:31:10 ┃
|
||||||
|
┃ 8040 │ A │ 2022-02-15 09:30:56 ┃
|
||||||
|
┃ 8034 │ Percent │ 2022-02-15 09:30:41 ┃
|
||||||
|
┃ 8038 │ MWh │ 2022-02-15 09:09:22 ┃
|
||||||
|
┃ 8037 │ MW │ 2022-02-15 09:03:22 ┃
|
||||||
|
┃ 8033 │ kW │ 2022-02-15 09:01:19 ┃
|
||||||
|
┃ 8035 │ Hours │ 2022-02-15 08:55:56 ┃
|
||||||
|
┃ 8031 │ kWh │ 2022-02-15 07:57:36 ┃
|
||||||
|
┃ 7981 │ Power │ 2022-02-09 10:03:40 ┃
|
||||||
|
┗━━━━━━━━━━━━━┷━━━━━━━━━━━━━━━┷━━━━━━━━━━━━━━━━━━━━━┛
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
## High-level data commands
|
||||||
|
|
||||||
|
```
|
||||||
|
Usage:
|
||||||
|
GoSungrow data [command]
|
||||||
|
|
||||||
|
Available Commands:
|
||||||
|
get Data - Get high-level data from iSolarCloud (table)
|
||||||
|
raw Data - Get high-level data from iSolarCloud (raw)
|
||||||
|
json Data - Get high-level data from iSolarCloud (json)
|
||||||
|
csv Data - Get high-level data from iSolarCloud (json)
|
||||||
|
graph Data - Get high-level data from iSolarCloud (graph)
|
||||||
|
```
|
||||||
|
|
||||||
|
```
|
||||||
|
Usage:
|
||||||
|
GoSungrow data get [command]
|
||||||
|
|
||||||
|
Available Commands:
|
||||||
|
stats Data - Get current inverter stats, (last 5 minutes).
|
||||||
|
template Data - Get data from report template.
|
||||||
|
points Data - Get points data for a specific date.
|
||||||
|
real-time Data - Get iSolarCloud real-time data.
|
||||||
|
psdetails Data - Get iSolarCloud ps details.
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
## General
|
||||||
|
|
||||||
|
```
|
||||||
|
GoSungrow data get stats
|
||||||
|
┏━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━┳━━━━━━┓
|
||||||
|
┃ Date ┃ Point Id ┃ Point Name ┃ Value ┃ Unit ┃
|
||||||
|
┣━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━╇━━━━━━┫
|
||||||
|
┃ 2022-10-08 09:55:00 │ 1129147.0 │ Co2 Reduce │ 0 │ kg ┃
|
||||||
|
┃ 2022-10-08 09:55:00 │ 1129147.0 │ Co2 Reduce Total │ 5819 │ kg ┃
|
||||||
|
┃ 2022-10-08 09:55:00 │ 1129147.0 │ Curr Power │ 788 │ W ┃
|
||||||
|
┃ 2022-10-08 09:55:00 │ 1129147.0 │ Daily Irradiation │ -- │ ┃
|
||||||
|
┃ 2022-10-08 09:55:00 │ 1129147.0 │ Equivalent Hour │ 0.27 │ Hour ┃
|
||||||
|
|
||||||
|
...
|
||||||
|
|
||||||
|
┃ 2022-10-08 09:55:00 │ 1171348.0 │ Today Income │ 0.397 │ AUD ┃
|
||||||
|
┃ 2022-10-08 09:55:00 │ 1171348.0 │ Total Capacity │ │ ┃
|
||||||
|
┃ 2022-10-08 09:55:00 │ 1171348.0 │ Total Energy │ 176.5 │ kWh ┃
|
||||||
|
┃ 2022-10-08 09:55:00 │ 1171348.0 │ Total Income │ 35.806 │ AUD ┃
|
||||||
|
┃ 2022-10-08 09:55:00 │ 1171348.0 │ Use Energy │ 6.7 │ kWh ┃
|
||||||
|
┗━━━━━━━━━━━━━━━━━━━━━┷━━━━━━━━━━━┷━━━━━━━━━━━━━━━━━━━━━━━━━━━┷━━━━━━━━━┷━━━━━━┛
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
## Templates
|
||||||
|
|
||||||
|
```
|
||||||
|
GoSungrow info get template-points 7981
|
||||||
|
┏━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━┓
|
||||||
|
┃ PointStruct Id ┃ Description ┃ Unit ┃
|
||||||
|
┣━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━┫
|
||||||
|
┃ 1129147_11_0_0.p83032 │ Meter AC Power │ kW ┃
|
||||||
|
┃ 1129147_11_0_0.p83119 │ Daily Feed-in Energy (PV) │ kWh ┃
|
||||||
|
┃ 1129147_11_0_0.p83549 │ Grid active power │ kW ┃
|
||||||
|
┃ 1129147_11_0_0.p83002 │ Inverter AC Power │ kW ┃
|
||||||
|
┃ 1129147_11_0_0.p83011 │ Meter E-daily Consumption │ kWh ┃
|
||||||
|
┃ 1129147_11_0_0.p83022 │ Daily Yield of Plant │ kWh ┃
|
||||||
|
┃ 1129147_11_0_0.p83006 │ Meter Daily Yield │ kWh ┃
|
||||||
|
┃ 1129147_11_0_0.p83033 │ Plant Power │ kW ┃
|
||||||
|
┃ 1129147_11_0_0.p83072 │ Daily Feed-in Energy │ kWh ┃
|
||||||
|
┃ 1129147_11_0_0.p83097 │ Daily Load Energy Consumption from PV │ kWh ┃
|
||||||
|
┃ 1129147_11_0_0.p83102 │ Daily Purchased Energy │ kWh ┃
|
||||||
|
┃ 1129147_14_1_1.p13028 │ Daily Battery Charging Energy │ kWh ┃
|
||||||
|
┃ 1129147_14_1_1.p13112 │ Daily PV Yield │ kWh ┃
|
||||||
|
┃ 1129147_14_1_1.p13147 │ Daily Purchased Energy │ kWh ┃
|
||||||
|
┃ 1129147_14_1_1.p13173 │ Daily Feed-in Energy (PV) │ kWh ┃
|
||||||
|
┃ 1129147_14_1_1.p13174 │ Daily Battery Charging Energy from PV │ kWh ┃
|
||||||
|
┃ 1129147_14_1_1.p13199 │ Daily Load Energy Consumption │ kWh ┃
|
||||||
|
┃ 1129147_14_1_1.p13116 │ Daily Load Energy Consumption from PV │ kWh ┃
|
||||||
|
┃ 1129147_14_1_1.p13122 │ Daily Feed-in Energy │ kWh ┃
|
||||||
|
┗━━━━━━━━━━━━━━━━━━━━━━━┷━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┷━━━━━━┛
|
||||||
|
```
|
||||||
|
|
||||||
|
```
|
||||||
|
GoSungrow data get template 8042 20220212
|
||||||
|
┏━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━┳━━━━━━━┓
|
||||||
|
┃ Date/Time ┃ Point Id ┃ Point Name ┃ Value ┃ Units ┃
|
||||||
|
┣━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━╇━━━━━━━┫
|
||||||
|
┃ 2022-02-12 00:00:00 │ 1129147_11_0_0.p83106 │ Load Power │ 396 │ kW ┃
|
||||||
|
┃ 2022-02-12 00:05:00 │ 1129147_11_0_0.p83106 │ Load Power │ 480 │ kW ┃
|
||||||
|
┃ 2022-02-12 00:10:00 │ 1129147_11_0_0.p83106 │ Load Power │ 487 │ kW ┃
|
||||||
|
┃ 2022-02-12 00:15:00 │ 1129147_11_0_0.p83106 │ Load Power │ 497 │ kW ┃
|
||||||
|
┃ 2022-02-12 00:20:00 │ 1129147_11_0_0.p83106 │ Load Power │ 524 │ kW ┃
|
||||||
|
┃ 2022-02-12 00:25:00 │ 1129147_11_0_0.p83106 │ Load Power │ 541 │ kW ┃
|
||||||
|
┃ 2022-02-12 00:30:00 │ 1129147_11_0_0.p83106 │ Load Power │ 554 │ kW ┃
|
||||||
|
|
||||||
|
...
|
||||||
|
|
||||||
|
┃ 2022-02-12 23:55:00 │ 1129147_14_1_1.p13019 │ Internal Air Temperature │ 19.4 │ ℃ ┃
|
||||||
|
┃ 2022-02-13 00:00:00 │ 1129147_14_1_1.p13019 │ Internal Air Temperature │ 22.3 │ ℃ ┃
|
||||||
|
┗━━━━━━━━━━━━━━━━━━━━━┷━━━━━━━━━━━━━━━━━━━━━━━┷━━━━━━━━━━━━━━━━━━━━━━━━━━━━┷━━━━━━━━━━━━━┷━━━━━━━┛
|
||||||
|
```
|
||||||
|
|
||||||
|
GoSungrow data graph template 8042 20220212 '{"search_string":"p13019","min_left_axis":-6000,"max_left_axis":12000}'
|
||||||
|
GoSungrow data graph template 8042 20220212 '{"search_string":"p13019"}'
|
||||||
|
GoSungrow data graph template 8042 20220212 '{"search_string":"p83106","min_left_axis":-6000,"max_left_axis":12000}'
|
||||||
|
GoSungrow data graph template 8042 20220212 '{"search_string":"p83106"}'
|
||||||
|
GoSungrow data graph template 8042 20220212 '{"title":"Testing 1. 2. 3.","time_column":"1","value_column":"4","search_column":"3","search_string":"p83106","file_name":"foo.png"}'
|
||||||
|
GoSungrow data graph template 8042 20220212 '{"title":"Testing 1. 2. 3.","time_column":1,"value_column":4,"search_column":2,"search_string":"p13019","min_left_axis":0,"max_left_axis":0}'
|
||||||
|
GoSungrow data graph template 8042 20220212 '{"title":"Testing 1. 2. 3.","time_column":1,"value_column":4,"search_column":2,"search_string":"p13149","min_left_axis":0,"max_left_axis":0}'
|
||||||
|
GoSungrow data graph template 8042 20220212 '{"title":"Testing 1. 2. 3.","time_column":1,"value_column":4,"search_column":2,"search_string":"p83106","file_name":"foo.png"}'
|
||||||
|
GoSungrow data graph template 8042 20220212 '{"title":"Testing 1. 2. 3.","time_column":1,"value_column":4,"search_column":2,"search_string":"p83106","min_left_axis":-6000,"max_left_axis":1000}'
|
||||||
|
GoSungrow data graph template 8042 20220212 '{"title":"Testing 1. 2. 3.","time_column":1,"value_column":4,"search_column":2,"search_string":"p83106","min_left_axis":-6000,"max_left_axis":12000}'
|
||||||
|
GoSungrow data graph template 8042 20220212 '{"title":"Testing 1. 2. 3.","time_column":1,"value_column":4,"search_column":2,"search_string":"p83106","min_left_axis":-6000,"max_left_axis":42000}'
|
||||||
|
GoSungrow data graph template 8042 20220212 '{"title":"Testing 1. 2. 3.","time_column":1,"value_column":4,"search_column":2,"search_string":"p83106","min_left_axis":0,"max_left_axis":0}'
|
||||||
|
GoSungrow data graph template 8042 20220212 '{"title":"Testing 1. 2. 3.","time_column":1,"value_column":4,"search_column":3,"search_string":"p83106","file_name":"foo.png"}'
|
||||||
|
GoSungrow data raw template '' 20220201
|
||||||
|
GoSungrow data save template '' 20220201
|
||||||
|
GoSungrow data save template 8042 20220212
|
||||||
|
|
||||||
|
|
||||||
|
## Hacking
|
||||||
|
|
||||||
|
|
||||||
|
## Base API commands
|
||||||
|
|
||||||
|
```
|
||||||
|
Usage:
|
||||||
|
GoSungrow api [command]
|
||||||
|
|
||||||
|
Examples:
|
||||||
|
GoSungrow api login
|
||||||
|
GoSungrow api get <endpoint> <args>
|
||||||
|
GoSungrow api raw <endpoint> <args>
|
||||||
|
GoSungrow api save <endpoint> <args>
|
||||||
|
GoSungrow api put <endpoint> <args>
|
||||||
|
|
||||||
|
Available Commands:
|
||||||
|
ls List iSolarCloud api endpoints/areas
|
||||||
|
login Login to iSolarCloud
|
||||||
|
get Get details from iSolarCloud
|
||||||
|
raw Raw details from iSolarCloud
|
||||||
|
save Save details from iSolarCloud as JSON
|
||||||
|
put Put details onto iSolarCloud
|
||||||
|
```
|
||||||
|
|
||||||
|
## Get device details
|
||||||
|
|
||||||
|
GoSungrow api get getPsList
|
||||||
|
GoSungrow api get getPsListByName
|
||||||
|
GoSungrow api get getPsDataSupplementTaskList
|
||||||
|
GoSungrow api get getPsUser
|
||||||
|
GoSungrow api get queryPsIdList
|
||||||
|
GoSungrow api get getInstallInfoList
|
||||||
|
GoSungrow api get getPsListStaticData
|
||||||
|
GoSungrow api get queryAllPsIdAndName
|
||||||
|
GoSungrow api get getPsDetail '{"ps_id":"1171348"}'
|
||||||
|
GoSungrow api get getPsDetailWithPsType '{"ps_id":"1171348"}'
|
||||||
|
GoSungrow api get getPsHealthState '{"ps_id":"1171348"}'
|
||||||
|
GoSungrow api get getPsWeatherList '{"ps_id":"1171348"}'
|
||||||
|
GoSungrow api get queryDeviceList '{"ps_id":"1171348"}'
|
||||||
|
GoSungrow api get queryDeviceListByUserId '{"ps_id":"1171348"}'
|
||||||
|
GoSungrow api get queryDeviceListForApp '{"ps_id":"1171348"}'
|
||||||
|
GoSungrow api get findPsType '{"ps_id":"1171348"}'
|
||||||
|
GoSungrow api get getDeviceList '{"ps_id":"1171348"}'
|
||||||
|
GoSungrow api get getIncomeSettingInfos '{"ps_id":"1171348"}'
|
||||||
|
GoSungrow api get getPowerChargeSettingInfo '{"ps_id":"1171348"}'
|
||||||
|
GoSungrow api get getPowerStationInfo '{"ps_id":"1171348"}'
|
||||||
|
GoSungrow api get WebAppService.getDeviceUuid '{"ps_key":"1171348"}'
|
||||||
|
GoSungrow api get getPowerStationForHousehold '{"ps_id":"1171348"}'
|
||||||
|
|
||||||
|
|
||||||
|
## Get device data
|
||||||
|
|
||||||
|
GoSungrow api get energyTrend
|
||||||
|
GoSungrow api get getKpiInfo
|
||||||
|
GoSungrow api get queryPsProfit '{"date_id":"20221001","date_type":"1","ps_id":"1171348"}'
|
||||||
|
GoSungrow api get getPowerStationData '{"date_id":"20221001","date_type":"1","ps_id":"1171348"}'
|
||||||
|
GoSungrow api get getHouseholdStoragePsReport '{"date_id":"20221001","date_type":"1","ps_id":"1171348"}'
|
||||||
|
GoSungrow api get queryPsProfit '{"date_id":"202210","date_type":"2","ps_id":"1171348"}'
|
||||||
|
GoSungrow api get getPowerStationData '{"date_id":"202210","date_type":"2","ps_id":"1171348"}'
|
||||||
|
GoSungrow api get getHouseholdStoragePsReport '{"date_id":"202210","date_type":"2","ps_id":"1171348"}'
|
||||||
|
GoSungrow api get queryPsProfit '{"date_id":"2022","date_type":"3","ps_id":"1171348"}'
|
||||||
|
GoSungrow api get getPowerStationData '{"date_id":"2022","date_type":"3","ps_id":"1171348"}'
|
||||||
|
GoSungrow api get getHouseholdStoragePsReport '{"date_id":"2022","date_type":"3","ps_id":"1171348"}'
|
||||||
|
GoSungrow api get getPowerTrendDayData '{"BeginTime":"20221004"}'
|
||||||
|
GoSungrow api get getPowerStatistics '{"ps_id":"1171348"}'
|
||||||
|
GoSungrow api get WebAppService.showPSView '{"ps_id":"1171348"}'
|
||||||
|
|
||||||
|
|
||||||
|
## Reports
|
||||||
|
|
||||||
|
GoSungrow api get getPsReport '{"report_type":"1","date_id":"20220201","date_type":"1","ps_id":"1171348"}'
|
||||||
|
GoSungrow api get getPsReport '{"report_type":"1","date_id":"20220201","date_type":"2","ps_id":"1171348"}'
|
||||||
|
GoSungrow api get getPsReport '{"report_type":"1","date_id":"20220201","date_type":"3","ps_id":"1171348"}'
|
||||||
|
GoSungrow api get reportList '{"ps_id":"1171348","report_type":"1"}'
|
||||||
|
GoSungrow api get reportList '{"ps_id":"1171348","report_type":"2"}'
|
||||||
|
GoSungrow api get reportList '{"ps_id":"1171348","report_type":"3"}'
|
||||||
|
GoSungrow api get reportList '{"ps_id":"1171348","report_type":"4"}'
|
||||||
|
|
||||||
|
|
||||||
|
## Templates
|
||||||
|
|
||||||
|
GoSungrow api get template 20220202
|
||||||
|
GoSungrow api get template 8042 20220212
|
||||||
|
GoSungrow api get getTemplateList
|
||||||
|
GoSungrow api get WebAppService.queryUserCurveTemplateData '{"template_id":"8042","date_type":"1","start_time":"20220223000000","end_time":"20220223235900"}'
|
||||||
|
|
||||||
|
|
||||||
|
## User/installer/support info
|
||||||
|
|
||||||
|
GoSungrow api get getUserList
|
||||||
|
GoSungrow api get getUserPsOrderList
|
||||||
|
GoSungrow api get getPhotoInfo
|
||||||
|
GoSungrow api get getOrgListByName
|
||||||
|
GoSungrow api get getOrgListByUserId
|
||||||
|
GoSungrow api get getOrgListForUser
|
||||||
|
GoSungrow api get queryUserList
|
||||||
|
GoSungrow api get getInstallerInfoByDealerOrgCodeOrId '{"dealer_org_code":"AUSCEKK7"}'
|
||||||
|
GoSungrow api get getInstallerInfoByDealerOrgCodeOrId '{"org_id":"362245"}'
|
||||||
|
GoSungrow api get getInstallerInfoByDealerOrgCodeOrId '{"org_id":"80384"}'
|
||||||
|
GoSungrow api get getInstallerInfoByDealerOrgCodeOrId '{"org_id":"80393"}'
|
||||||
|
GoSungrow api get getInstallerInfoByDealerOrgCodeOrId '{"org_id":"300977"}'
|
||||||
|
|
||||||
|
|
||||||
|
## Meta-data
|
||||||
|
|
||||||
|
GoSungrow api get getDeviceTypeInfoList
|
||||||
|
GoSungrow api get getDeviceTypeList
|
||||||
|
GoSungrow api get getInvertDataList
|
||||||
|
GoSungrow api get getModuleLogTaskList
|
||||||
|
GoSungrow api get powerDevicePointList
|
||||||
|
GoSungrow api get getPowerDevicePointNames '{"device_type":"1"}'
|
||||||
|
GoSungrow api get getPowerDevicePointNames '{"device_type":"2"}'
|
||||||
|
GoSungrow api get getPowerDevicePointNames '{"device_type":"7"}'
|
||||||
|
GoSungrow api get getDeviceModelInfoList
|
||||||
|
GoSungrow api get queryUnitList
|
||||||
|
GoSungrow api get getPowerSettingCharges
|
||||||
|
GoSungrow api get getPowerDevicePointNames '{"device_type":"1"}'
|
||||||
|
GoSungrow api get getPowerDeviceModelTechList '{"device_type":"1"}'
|
||||||
|
GoSungrow api get getPowerDevicePointInfo '{"id":"1"}'
|
||||||
|
|
||||||
|
|
||||||
|
## Task commands
|
||||||
|
|
||||||
|
GoSungrow api get queryBatchCreatePsTaskList
|
||||||
|
GoSungrow api get getPowerDeviceSetTaskDetailList '{"query_type":"2","task_id":"1","uuid":"844763"}'
|
||||||
|
GoSungrow api get getPowerDeviceSetTaskDetailList '{"query_type":"7","task_id":"1","uuid":"844763"}'
|
||||||
|
GoSungrow api get getPowerDeviceSetTaskDetailList '{"size":0,"curPage":0}'
|
||||||
|
GoSungrow api get getPowerDeviceSetTaskList '{"size":0,"curPage":0}'
|
||||||
|
GoSungrow api get getPowerDeviceSetTaskList '{"size":0,"curPage":1}'
|
||||||
|
GoSungrow api get getRemoteUpgradeSubTasksList '{"query_type":"1","task_id":"1577700"}'
|
||||||
|
GoSungrow api get getRemoteUpgradeTaskList '{"ps_id_list":"1171348"}'
|
||||||
|
|
||||||
|
|
||||||
|
## Misc commands
|
||||||
|
|
||||||
|
GoSungrow api get getDevicePoints '{"point_id":"13003"}'
|
||||||
|
GoSungrow api get getPowerPictureList
|
||||||
|
|
||||||
|
|
||||||
|
## Hacking
|
||||||
|
|
||||||
|
GoSungrow api get checkUnitStatus
|
||||||
|
GoSungrow api get getAllPowerDeviceSetName
|
||||||
|
GoSungrow api get getAreaList
|
||||||
|
GoSungrow api get getCloudList
|
||||||
|
GoSungrow api get getConfigList
|
||||||
|
GoSungrow api get getDeviceInfo
|
||||||
|
GoSungrow api get getOSSConfig
|
||||||
|
GoSungrow api get getOssObjectStream
|
||||||
|
GoSungrow api get getEncryptPublicKey
|
||||||
|
GoSungrow api get getFaultCount
|
||||||
|
GoSungrow api get getFaultDetail '{"fault_code":"34"}'
|
||||||
|
GoSungrow api get getFaultMsgByFaultCode '{"fault_code":"703"}'
|
||||||
|
GoSungrow api get getFaultMsgListWithYYYYMM
|
@ -15,7 +15,7 @@ var Examples string
|
|||||||
const (
|
const (
|
||||||
Description = "GoSungrow - GoLang implementation to access the iSolarCloud API updated by SunGrow inverters"
|
Description = "GoSungrow - GoLang implementation to access the iSolarCloud API updated by SunGrow inverters"
|
||||||
BinaryName = "GoSungrow"
|
BinaryName = "GoSungrow"
|
||||||
BinaryVersion = "2.2.1"
|
BinaryVersion = "2.3.0"
|
||||||
SourceRepo = "github.com/MickMake/" + BinaryName
|
SourceRepo = "github.com/MickMake/" + BinaryName
|
||||||
BinaryRepo = "github.com/MickMake/" + BinaryName
|
BinaryRepo = "github.com/MickMake/" + BinaryName
|
||||||
|
|
||||||
|
31
examples.txt
31
examples.txt
@ -1,3 +1,6 @@
|
|||||||
|
GoSungrow api login
|
||||||
|
GoSungrow api ls areas
|
||||||
|
|
||||||
GoSungrow api get WebAppService.getDeviceUuid '{"ps_key":"1171348"}'
|
GoSungrow api get WebAppService.getDeviceUuid '{"ps_key":"1171348"}'
|
||||||
GoSungrow api get WebAppService.showPSView '{"ps_id":"1171348"}'
|
GoSungrow api get WebAppService.showPSView '{"ps_id":"1171348"}'
|
||||||
GoSungrow api get checkUnitStatus
|
GoSungrow api get checkUnitStatus
|
||||||
@ -53,8 +56,6 @@ GoSungrow api get reportList '{"ps_id":"1171348","report_type":"1"}'
|
|||||||
GoSungrow api get reportList '{"ps_id":"1171348","report_type":"2"}'
|
GoSungrow api get reportList '{"ps_id":"1171348","report_type":"2"}'
|
||||||
GoSungrow api get reportList '{"ps_id":"1171348","report_type":"3"}'
|
GoSungrow api get reportList '{"ps_id":"1171348","report_type":"3"}'
|
||||||
GoSungrow api get reportList '{"ps_id":"1171348","report_type":"4"}'
|
GoSungrow api get reportList '{"ps_id":"1171348","report_type":"4"}'
|
||||||
GoSungrow api login
|
|
||||||
GoSungrow api ls areas
|
|
||||||
GoSungrow api raw queryDeviceList '{"ps_id":"1171348"}'
|
GoSungrow api raw queryDeviceList '{"ps_id":"1171348"}'
|
||||||
GoSungrow api save WebAppService.queryUserCurveTemplateData '{"template_id":"8042","date_type":"1","start_time":"20220223000000","end_time":"20220223235900"}'
|
GoSungrow api save WebAppService.queryUserCurveTemplateData '{"template_id":"8042","date_type":"1","start_time":"20220223000000","end_time":"20220223235900"}'
|
||||||
GoSungrow api save getPsDetail '{"ps_id":""}'
|
GoSungrow api save getPsDetail '{"ps_id":""}'
|
||||||
@ -72,6 +73,7 @@ GoSungrow data get template 8042 20220227
|
|||||||
GoSungrow data get template-points 8040
|
GoSungrow data get template-points 8040
|
||||||
GoSungrow data get template-points 8041
|
GoSungrow data get template-points 8041
|
||||||
GoSungrow data get template-points 8042
|
GoSungrow data get template-points 8042
|
||||||
|
|
||||||
GoSungrow data graph template 8042 20220212 '{"search_string":"p13019","min_left_axis":-6000,"max_left_axis":12000}'
|
GoSungrow data graph template 8042 20220212 '{"search_string":"p13019","min_left_axis":-6000,"max_left_axis":12000}'
|
||||||
GoSungrow data graph template 8042 20220212 '{"search_string":"p13019"}'
|
GoSungrow data graph template 8042 20220212 '{"search_string":"p13019"}'
|
||||||
GoSungrow data graph template 8042 20220212 '{"search_string":"p83106","min_left_axis":-6000,"max_left_axis":12000}'
|
GoSungrow data graph template 8042 20220212 '{"search_string":"p83106","min_left_axis":-6000,"max_left_axis":12000}'
|
||||||
@ -90,21 +92,17 @@ GoSungrow data save template '' 20220201
|
|||||||
GoSungrow data save template 8042 20220212
|
GoSungrow data save template 8042 20220212
|
||||||
GoSungrow get raw template 20220202
|
GoSungrow get raw template 20220202
|
||||||
GoSungrow get template 8042 20220212
|
GoSungrow get template 8042 20220212
|
||||||
|
|
||||||
GoSungrow data get stats
|
GoSungrow data get stats
|
||||||
GoSungrow data get search-point-names
|
GoSungrow data get search-point-names
|
||||||
GoSungrow data get device
|
GoSungrow data get device
|
||||||
GoSungrow data get model
|
GoSungrow data get model
|
||||||
|
|
||||||
GoSungrow api raw getPowerStationForHousehold '{"ps_id":"1171348"}'
|
GoSungrow api raw getPowerStationForHousehold '{"ps_id":"1171348"}'
|
||||||
> "org_index_code":"|80384|80393|300977|",
|
> "org_index_code":"|80384|80393|300977|",
|
||||||
|
|
||||||
GoSungrow api raw getInstallerInfoByDealerOrgCodeOrId '{"dealer_org_code":"AUSCEKK7"}'
|
GoSungrow api raw getInstallerInfoByDealerOrgCodeOrId '{"dealer_org_code":"AUSCEKK7"}'
|
||||||
GoSungrow api raw getInstallerInfoByDealerOrgCodeOrId '{"org_id":"362245"}'
|
GoSungrow api raw getInstallerInfoByDealerOrgCodeOrId '{"org_id":"362245"}'
|
||||||
GoSungrow api raw getInstallerInfoByDealerOrgCodeOrId '{"org_id":"80384"}'
|
GoSungrow api raw getInstallerInfoByDealerOrgCodeOrId '{"org_id":"80384"}'
|
||||||
GoSungrow api raw getInstallerInfoByDealerOrgCodeOrId '{"org_id":"80393"}'
|
GoSungrow api raw getInstallerInfoByDealerOrgCodeOrId '{"org_id":"80393"}'
|
||||||
GoSungrow api raw getInstallerInfoByDealerOrgCodeOrId '{"org_id":"300977"}'
|
GoSungrow api raw getInstallerInfoByDealerOrgCodeOrId '{"org_id":"300977"}'
|
||||||
|
|
||||||
GoSungrow api raw getKpiInfo
|
GoSungrow api raw getKpiInfo
|
||||||
GoSungrow api raw getInstallInfoList
|
GoSungrow api raw getInstallInfoList
|
||||||
GoSungrow api raw getIncomeSettingInfos '{"ps_id":"1171348"}'
|
GoSungrow api raw getIncomeSettingInfos '{"ps_id":"1171348"}'
|
||||||
@ -118,43 +116,22 @@ GoSungrow api raw getOrgListForUser
|
|||||||
GoSungrow api raw getPowerDevicePointNames '{"device_type":"1"}'
|
GoSungrow api raw getPowerDevicePointNames '{"device_type":"1"}'
|
||||||
GoSungrow api raw getPowerDeviceModelTechList '{"device_type":"1"}'
|
GoSungrow api raw getPowerDeviceModelTechList '{"device_type":"1"}'
|
||||||
GoSungrow api raw getPowerDevicePointInfo '{"id":"1"}'
|
GoSungrow api raw getPowerDevicePointInfo '{"id":"1"}'
|
||||||
GoSungrow api raw getPowerStationForHousehold '{"ps_id":"1171348"}'
|
|
||||||
|
|
||||||
GoSungrow api raw queryPsProfit '{"date_id":"20221001","date_type":"1","ps_id":"1171348"}'
|
GoSungrow api raw queryPsProfit '{"date_id":"20221001","date_type":"1","ps_id":"1171348"}'
|
||||||
GoSungrow api raw getPowerStationData '{"date_id":"20221001","date_type":"1","ps_id":"1171348"}'
|
GoSungrow api raw getPowerStationData '{"date_id":"20221001","date_type":"1","ps_id":"1171348"}'
|
||||||
GoSungrow api get getHouseholdStoragePsReport '{"date_id":"20221001","date_type":"1","ps_id":"1171348"}'
|
GoSungrow api get getHouseholdStoragePsReport '{"date_id":"20221001","date_type":"1","ps_id":"1171348"}'
|
||||||
|
|
||||||
GoSungrow api raw queryPsProfit '{"date_id":"202210","date_type":"2","ps_id":"1171348"}'
|
GoSungrow api raw queryPsProfit '{"date_id":"202210","date_type":"2","ps_id":"1171348"}'
|
||||||
GoSungrow api raw getPowerStationData '{"date_id":"202210","date_type":"2","ps_id":"1171348"}'
|
GoSungrow api raw getPowerStationData '{"date_id":"202210","date_type":"2","ps_id":"1171348"}'
|
||||||
GoSungrow api get getHouseholdStoragePsReport '{"date_id":"202210","date_type":"2","ps_id":"1171348"}'
|
GoSungrow api get getHouseholdStoragePsReport '{"date_id":"202210","date_type":"2","ps_id":"1171348"}'
|
||||||
|
|
||||||
GoSungrow api raw queryPsProfit '{"date_id":"2022","date_type":"3","ps_id":"1171348"}'
|
GoSungrow api raw queryPsProfit '{"date_id":"2022","date_type":"3","ps_id":"1171348"}'
|
||||||
GoSungrow api raw getPowerStationData '{"date_id":"2022","date_type":"3","ps_id":"1171348"}'
|
GoSungrow api raw getPowerStationData '{"date_id":"2022","date_type":"3","ps_id":"1171348"}'
|
||||||
GoSungrow api get getHouseholdStoragePsReport '{"date_id":"2022","date_type":"3","ps_id":"1171348"}'
|
GoSungrow api get getHouseholdStoragePsReport '{"date_id":"2022","date_type":"3","ps_id":"1171348"}'
|
||||||
|
|
||||||
GoSungrow api raw getPowerStationInfo '{"ps_id":"1171348"}'
|
GoSungrow api raw getPowerStationInfo '{"ps_id":"1171348"}'
|
||||||
GoSungrow api raw getPowerTrendDayData '{"BeginTime":"20221004"}'
|
GoSungrow api raw getPowerTrendDayData '{"BeginTime":"20221004"}'
|
||||||
GoSungrow api raw getPowerSettingCharges
|
GoSungrow api raw getPowerSettingCharges
|
||||||
GoSungrow api raw queryUnitList
|
GoSungrow api raw queryUnitList
|
||||||
GoSungrow api raw queryPsIdList
|
GoSungrow api raw queryPsIdList
|
||||||
GoSungrow api get getEncryptPublicKey
|
GoSungrow api get getEncryptPublicKey
|
||||||
|
|
||||||
GoSungrow api raw getFaultCount
|
GoSungrow api raw getFaultCount
|
||||||
GoSungrow api raw getFaultDetail '{"fault_code":"34"}'
|
GoSungrow api raw getFaultDetail '{"fault_code":"34"}'
|
||||||
GoSungrow api raw getFaultMsgByFaultCode '{"fault_code":"703"}'
|
GoSungrow api raw getFaultMsgByFaultCode '{"fault_code":"703"}'
|
||||||
GoSungrow api get getFaultMsgListWithYYYYMM
|
GoSungrow api get getFaultMsgListWithYYYYMM
|
||||||
|
|
||||||
|
|
||||||
################################################################################
|
|
||||||
|
|
||||||
"energy_flow"
|
|
||||||
1 / 3 - PV2Load && PV2Battery
|
|
||||||
|
|
||||||
|
|
||||||
"1" - PV to Load
|
|
||||||
"3" - Battery to Load
|
|
||||||
"5" - PV to Battery
|
|
||||||
|
|
||||||
https://augateway.isolarcloud.com/v1/commonService/getMqttConfigInfoByAppkey
|
|
||||||
sensor.sungrow_total_load_active_power == sensor.sungrow_total_active_power
|
|
||||||
|
|
||||||
|
@ -1,9 +0,0 @@
|
|||||||
package google
|
|
||||||
|
|
||||||
const (
|
|
||||||
DefaultGoogleClientId = "424242424242-42424242424242424242424242424242.apps.googleusercontent.com"
|
|
||||||
DefaultGoogleClientSecret = "424242424242424242424242"
|
|
||||||
DefaultGoogleCredentials = `{"installed":{"client_id":"424242424242-42424242424242424242424242424242.apps.googleusercontent.com","project_id":"isolarcloud","auth_uri":"https://accounts.google.com/o/oauth2/auth","token_uri":"https://oauth2.googleapis.com/token","auth_provider_x509_cert_url":"https://www.googleapis.com/oauth2/v1/certs","client_secret":"424242424242424242424242","redirect_uris":["urn:ietf:wg:oauth:2.0:oob","http://localhost"]}}
|
|
||||||
`
|
|
||||||
DefaultAuthTokenFile = "GoogleSheetsAuthToken.json"
|
|
||||||
)
|
|
111
google/sheet.go
111
google/sheet.go
@ -1,111 +0,0 @@
|
|||||||
package google
|
|
||||||
|
|
||||||
import (
|
|
||||||
"GoSungrow/Only"
|
|
||||||
"context"
|
|
||||||
"encoding/json"
|
|
||||||
"errors"
|
|
||||||
"fmt"
|
|
||||||
"golang.org/x/oauth2"
|
|
||||||
"net/http"
|
|
||||||
"os"
|
|
||||||
)
|
|
||||||
|
|
||||||
// Retrieve a token, saves the token, then returns the generated client.
|
|
||||||
func (s *Sheet) getClient() (*http.Client, error) {
|
|
||||||
var ret *http.Client
|
|
||||||
var err error
|
|
||||||
|
|
||||||
for range Only.Once {
|
|
||||||
// The file token.json stores the user's access and refresh tokens, and is
|
|
||||||
// created automatically when the authorization flow completes for the first
|
|
||||||
// time.
|
|
||||||
|
|
||||||
var err error
|
|
||||||
err = s.tokenFromFile()
|
|
||||||
if err != nil {
|
|
||||||
err = s.getTokenFromWeb()
|
|
||||||
if err != nil {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
err = s.saveToken()
|
|
||||||
if err != nil {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ret = s.oAuthConfig.Client(context.Background(), s.token)
|
|
||||||
}
|
|
||||||
|
|
||||||
return ret, err
|
|
||||||
}
|
|
||||||
|
|
||||||
// RequestCommon a token from the web, then returns the retrieved token.
|
|
||||||
func (s *Sheet) getTokenFromWeb() error {
|
|
||||||
var err error
|
|
||||||
|
|
||||||
for range Only.Once {
|
|
||||||
authURL := s.oAuthConfig.AuthCodeURL("state-token", oauth2.AccessTypeOffline)
|
|
||||||
fmt.Printf("Allow access to this application by going to this URL:\n%v\n", authURL)
|
|
||||||
fmt.Printf("\nThen copy-paste the authorization code here: ")
|
|
||||||
|
|
||||||
var authCode string
|
|
||||||
_, err = fmt.Scan(&authCode)
|
|
||||||
if err != nil {
|
|
||||||
err = errors.New(fmt.Sprintf("Unable to read authorization code: %v", err))
|
|
||||||
break
|
|
||||||
}
|
|
||||||
|
|
||||||
s.token, err = s.oAuthConfig.Exchange(context.TODO(), authCode)
|
|
||||||
if err != nil {
|
|
||||||
err = errors.New(fmt.Sprintf("Unable to retrieve token from web: %v", err))
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
// Retrieves a token from a local file.
|
|
||||||
func (s *Sheet) tokenFromFile() error {
|
|
||||||
var err error
|
|
||||||
|
|
||||||
for range Only.Once {
|
|
||||||
if s.TokenFile == "" {
|
|
||||||
err = errors.New("Empty token filename")
|
|
||||||
break
|
|
||||||
}
|
|
||||||
|
|
||||||
var f *os.File
|
|
||||||
f, err = os.Open(s.TokenFile)
|
|
||||||
if err != nil {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
|
|
||||||
defer f.Close()
|
|
||||||
//ret = &oauth2.token{}
|
|
||||||
err = json.NewDecoder(f).Decode(s.token)
|
|
||||||
}
|
|
||||||
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
// Saves a token to a file path.
|
|
||||||
func (s *Sheet) saveToken() error {
|
|
||||||
var err error
|
|
||||||
|
|
||||||
for range Only.Once {
|
|
||||||
fmt.Printf("Saving token file to: %s\n", s.TokenFile)
|
|
||||||
var f *os.File
|
|
||||||
f, err = os.OpenFile(s.TokenFile, os.O_RDWR|os.O_CREATE|os.O_TRUNC, 0600)
|
|
||||||
if err != nil {
|
|
||||||
err = errors.New(fmt.Sprintf("Unable to cache oauth token: %v", err))
|
|
||||||
break
|
|
||||||
}
|
|
||||||
|
|
||||||
defer f.Close()
|
|
||||||
err = json.NewEncoder(f).Encode(s.token)
|
|
||||||
}
|
|
||||||
|
|
||||||
return err
|
|
||||||
}
|
|
193
google/struct.go
193
google/struct.go
@ -1,193 +0,0 @@
|
|||||||
package google
|
|
||||||
|
|
||||||
import (
|
|
||||||
"GoSungrow/Only"
|
|
||||||
"context"
|
|
||||||
"errors"
|
|
||||||
"fmt"
|
|
||||||
"golang.org/x/oauth2"
|
|
||||||
"golang.org/x/oauth2/google"
|
|
||||||
"google.golang.org/api/googleapi"
|
|
||||||
"google.golang.org/api/option"
|
|
||||||
"google.golang.org/api/sheets/v4"
|
|
||||||
"net/http"
|
|
||||||
"os"
|
|
||||||
"path/filepath"
|
|
||||||
)
|
|
||||||
|
|
||||||
const DefaultId = "SUPERSECRETKEY"
|
|
||||||
|
|
||||||
type Sheet struct {
|
|
||||||
Id string
|
|
||||||
SheetName string
|
|
||||||
Range string
|
|
||||||
Credentials []byte
|
|
||||||
TokenFile string
|
|
||||||
token *oauth2.Token
|
|
||||||
oAuthConfig *oauth2.Config
|
|
||||||
|
|
||||||
Data SheetData
|
|
||||||
}
|
|
||||||
type SheetData [][]interface{}
|
|
||||||
|
|
||||||
func (s *Sheet) Set(cfg Sheet) {
|
|
||||||
for range Only.Once {
|
|
||||||
s.Id = cfg.Id
|
|
||||||
s.SheetName = cfg.SheetName
|
|
||||||
s.Range = cfg.Range
|
|
||||||
|
|
||||||
s.Credentials = cfg.Credentials
|
|
||||||
s.TokenFile = cfg.TokenFile
|
|
||||||
s.token = cfg.token
|
|
||||||
|
|
||||||
s.Verify()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *Sheet) Verify() bool {
|
|
||||||
var ok bool
|
|
||||||
for range Only.Once {
|
|
||||||
if s.Id == "" {
|
|
||||||
s.Id = DefaultId
|
|
||||||
}
|
|
||||||
if s.SheetName == "" {
|
|
||||||
s.SheetName = ""
|
|
||||||
}
|
|
||||||
if s.Range == "" {
|
|
||||||
s.Range = "A1"
|
|
||||||
}
|
|
||||||
if len(s.Credentials) == 0 {
|
|
||||||
s.Credentials = []byte(DefaultGoogleCredentials)
|
|
||||||
}
|
|
||||||
|
|
||||||
// token *oauth2.token
|
|
||||||
// oAuthConfig *oauth2.Config
|
|
||||||
|
|
||||||
if s.oAuthConfig == nil {
|
|
||||||
s.oAuthConfig = &oauth2.Config{}
|
|
||||||
}
|
|
||||||
if s.token == nil {
|
|
||||||
s.token = &oauth2.Token{}
|
|
||||||
}
|
|
||||||
|
|
||||||
if len(s.TokenFile) == 0 {
|
|
||||||
var err error
|
|
||||||
s.TokenFile, err = os.UserHomeDir()
|
|
||||||
if err != nil {
|
|
||||||
s.TokenFile = ""
|
|
||||||
break
|
|
||||||
}
|
|
||||||
s.TokenFile = filepath.Join(s.TokenFile, ".GoSungrow", DefaultAuthTokenFile)
|
|
||||||
}
|
|
||||||
|
|
||||||
ok = true
|
|
||||||
}
|
|
||||||
|
|
||||||
return ok
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *Sheet) ReadSheet() (SheetData, error) {
|
|
||||||
var err error
|
|
||||||
var csv SheetData
|
|
||||||
|
|
||||||
for range Only.Once {
|
|
||||||
if !s.Verify() {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
|
|
||||||
// If modifying these scopes, delete your previously saved token.json.
|
|
||||||
s.oAuthConfig, err = google.ConfigFromJSON(s.Credentials, sheets.SpreadsheetsReadonlyScope)
|
|
||||||
if err != nil {
|
|
||||||
err = errors.New(fmt.Sprintf("Unable to parse client secret file to config: %v", err))
|
|
||||||
break
|
|
||||||
}
|
|
||||||
|
|
||||||
var client *http.Client
|
|
||||||
client, err = s.getClient()
|
|
||||||
|
|
||||||
ctx := context.Background()
|
|
||||||
var srv *sheets.Service
|
|
||||||
srv, err = sheets.NewService(ctx, option.WithHTTPClient(client))
|
|
||||||
if err != nil {
|
|
||||||
err = errors.New(fmt.Sprintf("Unable to retrieve Sheets client: %v", err))
|
|
||||||
break
|
|
||||||
}
|
|
||||||
|
|
||||||
readRange := fmt.Sprintf("%s!%s", s.SheetName, s.Range)
|
|
||||||
var resp *sheets.ValueRange
|
|
||||||
resp, err = srv.Spreadsheets.Values.Get(s.Id, readRange).Do()
|
|
||||||
if err != nil {
|
|
||||||
err = errors.New(fmt.Sprintf("Unable to retrieve data from sheet: %v", err))
|
|
||||||
break
|
|
||||||
}
|
|
||||||
|
|
||||||
if len(resp.Values) == 0 {
|
|
||||||
fmt.Println("No data found.")
|
|
||||||
break
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, row := range resp.Values {
|
|
||||||
// Print columns A and E, which correspond to indices 0 and 4.
|
|
||||||
fmt.Printf("%v\n", row)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return csv, err
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *Sheet) WriteSheet() error {
|
|
||||||
var err error
|
|
||||||
|
|
||||||
for range Only.Once {
|
|
||||||
if !s.Verify() {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
|
|
||||||
// If modifying these scopes, delete your previously saved token.json.
|
|
||||||
s.oAuthConfig, err = google.ConfigFromJSON(s.Credentials, sheets.SpreadsheetsScope)
|
|
||||||
if err != nil {
|
|
||||||
err = errors.New(fmt.Sprintf("Unable to parse client secret file to config: %v", err))
|
|
||||||
break
|
|
||||||
}
|
|
||||||
|
|
||||||
var client *http.Client
|
|
||||||
client, err = s.getClient()
|
|
||||||
//client = getClient(s.oAuthConfig)
|
|
||||||
|
|
||||||
ctx := context.Background()
|
|
||||||
var srv *sheets.Service
|
|
||||||
srv, err = sheets.NewService(ctx, option.WithHTTPClient(client))
|
|
||||||
if err != nil {
|
|
||||||
err = errors.New(fmt.Sprintf("Unable to retrieve Sheets client: %v", err))
|
|
||||||
break
|
|
||||||
}
|
|
||||||
|
|
||||||
//var itt = srv.Spreadsheets.getSheetByName('_EmailList');
|
|
||||||
//if (!itt) {
|
|
||||||
// ss.insertSheet('_EmailList');
|
|
||||||
//}
|
|
||||||
|
|
||||||
vr := sheets.ValueRange{
|
|
||||||
MajorDimension: "",
|
|
||||||
Range: s.SheetName + "!" + s.Range,
|
|
||||||
Values: s.Data,
|
|
||||||
ServerResponse: googleapi.ServerResponse{},
|
|
||||||
ForceSendFields: nil,
|
|
||||||
NullFields: nil,
|
|
||||||
}
|
|
||||||
|
|
||||||
writeRange := fmt.Sprintf("%s!%s", s.SheetName, s.Range)
|
|
||||||
fmt.Printf("Updating Google sheet '%s'.\n\tWorksheet: %s\n\tStarting from: %s\n",
|
|
||||||
s.Id,
|
|
||||||
s.SheetName,
|
|
||||||
s.Range,
|
|
||||||
)
|
|
||||||
_, err = srv.Spreadsheets.Values.Update(s.Id, writeRange, &vr).ValueInputOption("USER_ENTERED").Do() // or "RAW"
|
|
||||||
if err != nil {
|
|
||||||
err = errors.New(fmt.Sprintf("Unable to retrieve data from sheet. %v", err))
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return err
|
|
||||||
}
|
|
@ -11,7 +11,7 @@ const Url = "/v1/devService/getDeviceList"
|
|||||||
const Disabled = false
|
const Disabled = false
|
||||||
|
|
||||||
type RequestData struct {
|
type RequestData struct {
|
||||||
PsId int64 `json:"ps_id" required:"true"`
|
PsId string `json:"ps_id" required:"true"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (rd RequestData) IsValid() error {
|
func (rd RequestData) IsValid() error {
|
||||||
@ -26,7 +26,7 @@ func (rd RequestData) Help() string {
|
|||||||
type ResultData struct {
|
type ResultData struct {
|
||||||
PageList []struct {
|
PageList []struct {
|
||||||
AttrID int64 `json:"attr_id"`
|
AttrID int64 `json:"attr_id"`
|
||||||
ChnnlID int64 `json:"chnnl_id"`
|
ChannelId int64 `json:"chnnl_id"`
|
||||||
CommandStatus int64 `json:"command_status"`
|
CommandStatus int64 `json:"command_status"`
|
||||||
ConnectState int64 `json:"connect_state"`
|
ConnectState int64 `json:"connect_state"`
|
||||||
DataFlag int64 `json:"data_flag"`
|
DataFlag int64 `json:"data_flag"`
|
||||||
@ -132,7 +132,7 @@ func (e *EndPoint) GetDataTable() output.Table {
|
|||||||
d.PsID,
|
d.PsID,
|
||||||
d.DeviceType,
|
d.DeviceType,
|
||||||
d.DeviceCode,
|
d.DeviceCode,
|
||||||
d.ChnnlID,
|
d.ChannelId,
|
||||||
d.TypeName,
|
d.TypeName,
|
||||||
d.DeviceProSn,
|
d.DeviceProSn,
|
||||||
d.DeviceModel,
|
d.DeviceModel,
|
||||||
|
@ -41,15 +41,15 @@ type ResultData struct {
|
|||||||
CuspPowerQuantity interface{} `json:"cusp_power_quantity"`
|
CuspPowerQuantity interface{} `json:"cusp_power_quantity"`
|
||||||
CuspUsePowerQuantity interface{} `json:"cusp_use_power_quantity"`
|
CuspUsePowerQuantity interface{} `json:"cusp_use_power_quantity"`
|
||||||
DateID int64 `json:"date_id"`
|
DateID int64 `json:"date_id"`
|
||||||
FlatNetPowerQuantity int64 `json:"flat_net_power_quantity"`
|
FlatNetPowerQuantity float64 `json:"flat_net_power_quantity"`
|
||||||
FlatPowerQuantity int64 `json:"flat_power_quantity"`
|
FlatPowerQuantity float64 `json:"flat_power_quantity"`
|
||||||
FlatUsePowerQuantity float64 `json:"flat_use_power_quantity"`
|
FlatUsePowerQuantity float64 `json:"flat_use_power_quantity"`
|
||||||
NetPowerProfit float64 `json:"net_power_profit"`
|
NetPowerProfit float64 `json:"net_power_profit"`
|
||||||
NetPowerQuantityTotal int64 `json:"net_power_quantity_total"`
|
NetPowerQuantityTotal float64 `json:"net_power_quantity_total"`
|
||||||
PeakNetPowerQuantity interface{} `json:"peak_net_power_quantity"`
|
PeakNetPowerQuantity interface{} `json:"peak_net_power_quantity"`
|
||||||
PeakPowerQuantity interface{} `json:"peak_power_quantity"`
|
PeakPowerQuantity interface{} `json:"peak_power_quantity"`
|
||||||
PeakUsePowerQuantity interface{} `json:"peak_use_power_quantity"`
|
PeakUsePowerQuantity interface{} `json:"peak_use_power_quantity"`
|
||||||
PowerQuantityTotal int64 `json:"power_quantity_total"`
|
PowerQuantityTotal float64 `json:"power_quantity_total"`
|
||||||
SubsidyProfit interface{} `json:"subsidy_profit"`
|
SubsidyProfit interface{} `json:"subsidy_profit"`
|
||||||
TotalProfit float64 `json:"total_profit"`
|
TotalProfit float64 `json:"total_profit"`
|
||||||
UpdateTime string `json:"update_time"`
|
UpdateTime string `json:"update_time"`
|
||||||
|
@ -97,7 +97,7 @@ type ResultData struct {
|
|||||||
SubsidyProfitOriginalUnit string `json:"subsidy_profit_original_unit"`
|
SubsidyProfitOriginalUnit string `json:"subsidy_profit_original_unit"`
|
||||||
SubsidyProfitTran string `json:"subsidy_profit_tran"`
|
SubsidyProfitTran string `json:"subsidy_profit_tran"`
|
||||||
SubsidyProfitUnit string `json:"subsidy_profit_unit"`
|
SubsidyProfitUnit string `json:"subsidy_profit_unit"`
|
||||||
TimeStamp string `json:"time_stamp"`
|
TimeStamp interface{} `json:"time_stamp"` // Sad that this alternates between string and int64.
|
||||||
TotalProfit string `json:"total_profit"`
|
TotalProfit string `json:"total_profit"`
|
||||||
TotalProfitOriginalUnit string `json:"total_profit_original_unit"`
|
TotalProfitOriginalUnit string `json:"total_profit_original_unit"`
|
||||||
TotalProfitTran string `json:"total_profit_tran"`
|
TotalProfitTran string `json:"total_profit_tran"`
|
||||||
|
@ -113,8 +113,8 @@ func (sg *SunGrow) GetTemplateData(template string, date string, filter string)
|
|||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
|
||||||
table.SetTitle("Template %s on %s for %s", template, when.String(), psId)
|
table.SetTitle("Template %s on %s for %d", template, when.String(), psId)
|
||||||
table.SetFilePrefix(data.SetFilenamePrefix("%s-%s-%s", when.String(), template, psId))
|
table.SetFilePrefix(data.SetFilenamePrefix("%s-%s-%d", when.String(), template, psId))
|
||||||
table.SetGraphFilter(filter)
|
table.SetGraphFilter(filter)
|
||||||
table.SetSaveFile(sg.SaveAsFile)
|
table.SetSaveFile(sg.SaveAsFile)
|
||||||
table.OutputType = sg.OutputType
|
table.OutputType = sg.OutputType
|
||||||
@ -694,7 +694,7 @@ func (sg *SunGrow) GetDevices(psIds ...int64) error {
|
|||||||
for _, psId := range psIds {
|
for _, psId := range psIds {
|
||||||
ep := sg.GetByStruct(
|
ep := sg.GetByStruct(
|
||||||
"AppService.getDeviceList",
|
"AppService.getDeviceList",
|
||||||
getDeviceList.RequestData{PsId: psId},
|
getDeviceList.RequestData{PsId: strconv.FormatInt(psId, 10)},
|
||||||
DefaultCacheTimeout,
|
DefaultCacheTimeout,
|
||||||
)
|
)
|
||||||
if sg.Error != nil {
|
if sg.Error != nil {
|
||||||
|
@ -1,72 +0,0 @@
|
|||||||
package lsgo
|
|
||||||
|
|
||||||
import (
|
|
||||||
"log"
|
|
||||||
|
|
||||||
kingpin "gopkg.in/alecthomas/kingpin.v2"
|
|
||||||
)
|
|
||||||
|
|
||||||
// declare the struct that holds all the arguments
|
|
||||||
type arguments struct {
|
|
||||||
paths *[]string
|
|
||||||
all *bool
|
|
||||||
bytes *bool
|
|
||||||
mdate *bool
|
|
||||||
owner *bool
|
|
||||||
nogroup *bool
|
|
||||||
perms *bool
|
|
||||||
long *bool
|
|
||||||
dirs *bool
|
|
||||||
files *bool
|
|
||||||
links *bool
|
|
||||||
linkRel *bool
|
|
||||||
sortSize *bool
|
|
||||||
sortTime *bool
|
|
||||||
sortKind *bool
|
|
||||||
backwards *bool
|
|
||||||
stats *bool
|
|
||||||
icons *bool
|
|
||||||
nerdfont *bool
|
|
||||||
recurse *bool
|
|
||||||
find *string
|
|
||||||
}
|
|
||||||
|
|
||||||
var args = arguments{
|
|
||||||
kingpin.Arg("paths", "the files(s) and/or folder(s) to display").Default(".").Strings(),
|
|
||||||
kingpin.Flag("all", "show hidden files").Short('a').Bool(),
|
|
||||||
kingpin.Flag("bytes", "include size").Short('b').Bool(),
|
|
||||||
kingpin.Flag("mdate", "include modification date").Short('m').Bool(),
|
|
||||||
kingpin.Flag("owner", "include owner and group").Short('o').Bool(),
|
|
||||||
kingpin.Flag("nogroup", "hide group").Short('N').Bool(),
|
|
||||||
kingpin.Flag("perms", "include permissions for owner, group, and other").Short('p').Bool(),
|
|
||||||
kingpin.Flag("long", "include size, date, owner, and permissions").Short('l').Bool(),
|
|
||||||
kingpin.Flag("dirs", "only show directories").Short('d').Bool(),
|
|
||||||
kingpin.Flag("files", "only show files").Short('f').Bool(),
|
|
||||||
kingpin.Flag("links", "show paths for symlinks").Short('L').Bool(),
|
|
||||||
kingpin.Flag("link-rel", "show symlinks as relative paths if shorter than absolute path").Short('R').Bool(),
|
|
||||||
kingpin.Flag("size", "sort items by size").Short('s').Bool(),
|
|
||||||
kingpin.Flag("time", "sort items by time").Short('t').Bool(),
|
|
||||||
kingpin.Flag("kind", "sort items by extension").Short('k').Bool(),
|
|
||||||
kingpin.Flag("backwards", "reverse the sort order of --size, --time, or --kind").Short('B').Bool(),
|
|
||||||
kingpin.Flag("stats", "show statistics").Short('S').Bool(),
|
|
||||||
kingpin.Flag("icons", "show folder icon before dirs").Short('i').Bool(),
|
|
||||||
kingpin.Flag("nerd-font", "show nerd font glyphs before file names").Short('n').Bool(),
|
|
||||||
kingpin.Flag("recurse", "traverse all dirs recursively").Short('r').Bool(),
|
|
||||||
kingpin.Flag("find", "filter items with a regexp").Short('F').String(),
|
|
||||||
}
|
|
||||||
|
|
||||||
func argsPostParse() {
|
|
||||||
if *args.long {
|
|
||||||
args.bytes = &True
|
|
||||||
args.mdate = &True
|
|
||||||
args.owner = &True
|
|
||||||
args.perms = &True
|
|
||||||
args.links = &True
|
|
||||||
}
|
|
||||||
if *args.dirs && *args.files {
|
|
||||||
log.Fatal("--dirs and --files cannot both be set")
|
|
||||||
}
|
|
||||||
if *args.nerdfont && *args.icons {
|
|
||||||
log.Fatal("--nerd-font and --icons cannot both be set")
|
|
||||||
}
|
|
||||||
}
|
|
351
lsgo/colors.go
351
lsgo/colors.go
@ -1,351 +0,0 @@
|
|||||||
package lsgo
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
"strconv"
|
|
||||||
"strings"
|
|
||||||
)
|
|
||||||
|
|
||||||
// see the color codes
|
|
||||||
// http://i.stack.imgur.com/UQVe5.png
|
|
||||||
|
|
||||||
// Fg wraps an 8-bit foreground color code in the ANSI escape sequence
|
|
||||||
func Fg(code int) string {
|
|
||||||
colored := []string{"\x1b[38;5;", strconv.Itoa(code), "m"}
|
|
||||||
return strings.Join(colored, "")
|
|
||||||
}
|
|
||||||
|
|
||||||
// Bg wraps an 8-bit background color code in the ANSI escape sequence
|
|
||||||
func Bg(code int) string {
|
|
||||||
colored := []string{"\x1b[48;5;", strconv.Itoa(code), "m"}
|
|
||||||
return strings.Join(colored, "")
|
|
||||||
}
|
|
||||||
|
|
||||||
// Rgb2code converts RGB values (up to 5) to an 8-bit color code
|
|
||||||
func Rgb2code(r int, g int, b int) int {
|
|
||||||
code := 36*r + 6*g + b + 16
|
|
||||||
if code < 16 || 231 < code {
|
|
||||||
panic(fmt.Errorf("Invalid RGB values (%d, %d, %d)", r, g, b))
|
|
||||||
}
|
|
||||||
return code
|
|
||||||
}
|
|
||||||
|
|
||||||
// Gray2code converts a scalar of "grayness" to an 8-bit color code
|
|
||||||
func Gray2code(lightness int) int {
|
|
||||||
code := lightness + 232
|
|
||||||
if code < 232 || 255 < code {
|
|
||||||
panic(fmt.Errorf("Invalid lightness value (%d) for gray", lightness))
|
|
||||||
}
|
|
||||||
return code
|
|
||||||
}
|
|
||||||
|
|
||||||
// FgRGB converts RGB values (up to 5) to an ANSI-escaped foreground 8-bit color code
|
|
||||||
func FgRGB(r int, g int, b int) string {
|
|
||||||
return Fg(Rgb2code(r, g, b))
|
|
||||||
}
|
|
||||||
|
|
||||||
// BgRGB converts RGB values (up to 5) to an ANSI-escaped background 8-bit color code
|
|
||||||
func BgRGB(r int, g int, b int) string {
|
|
||||||
return Bg(Rgb2code(r, g, b))
|
|
||||||
}
|
|
||||||
|
|
||||||
// FgGray converts a scalar of "grayness" to an ANSI-escaped foreground 8-bit color code
|
|
||||||
func FgGray(lightness int) string {
|
|
||||||
return Fg(Gray2code(lightness))
|
|
||||||
}
|
|
||||||
|
|
||||||
// BgGray converts a scalar of "grayness" to an ANSI-escaped background 8-bit color code
|
|
||||||
func BgGray(lightness int) string {
|
|
||||||
return Bg(Gray2code(lightness))
|
|
||||||
}
|
|
||||||
|
|
||||||
const (
|
|
||||||
// Reset undoes ANSI color codes
|
|
||||||
Reset = "\x1b[0m"
|
|
||||||
// Bold makes text bold
|
|
||||||
Bold = "\x1b[1m"
|
|
||||||
)
|
|
||||||
|
|
||||||
var (
|
|
||||||
// FileColor is a mapping of filetypes to colors
|
|
||||||
FileColor = map[string][2]string{
|
|
||||||
"as": [2]string{Fg(196), Fg(124)},
|
|
||||||
"asm": [2]string{Fg(223), Fg(215)},
|
|
||||||
"bf": [2]string{Fg(223), Fg(215)},
|
|
||||||
"c": [2]string{Fg(39), Fg(27)},
|
|
||||||
"clj": [2]string{Fg(204), Fg(162)},
|
|
||||||
"coffee": [2]string{Fg(136), Fg(94)},
|
|
||||||
"cr": [2]string{Fg(82), Fg(70)},
|
|
||||||
"cson": [2]string{Fg(136), Fg(94)},
|
|
||||||
"css": [2]string{Fg(219), Fg(207)},
|
|
||||||
"dart": [2]string{Fg(43), Fg(31)},
|
|
||||||
"diff": [2]string{Fg(10), Fg(9)},
|
|
||||||
"elm": [2]string{Fg(51), Fg(39)},
|
|
||||||
"erl": [2]string{Fg(161), Fg(89)},
|
|
||||||
"ex": [2]string{Fg(99), Fg(57)},
|
|
||||||
"f": [2]string{Fg(208), Fg(94)},
|
|
||||||
"fs": [2]string{Fg(45), Fg(32)},
|
|
||||||
"gb": [2]string{Fg(43), Fg(29)},
|
|
||||||
"go": [2]string{Fg(121), Fg(109)},
|
|
||||||
"graphql": [2]string{Fg(219), Fg(207)},
|
|
||||||
"groovy": [2]string{Fg(223), Fg(215)},
|
|
||||||
"gv": [2]string{Fg(141), Fg(99)},
|
|
||||||
"hs": [2]string{Fg(99), Fg(57)},
|
|
||||||
"html": [2]string{Fg(87), Fg(73)},
|
|
||||||
"ino": [2]string{Fg(43), Fg(29)},
|
|
||||||
"java": [2]string{Fg(136), Fg(94)},
|
|
||||||
"jl": [2]string{Fg(141), Fg(99)},
|
|
||||||
"js": [2]string{FgRGB(4, 4, 0), FgRGB(2, 2, 0)},
|
|
||||||
"jsx": [2]string{Fg(87), Fg(73)},
|
|
||||||
"lock": [2]string{FgGray(8), FgGray(5)},
|
|
||||||
"log": [2]string{FgGray(8), FgGray(5)},
|
|
||||||
"lua": [2]string{Fg(39), Fg(27)},
|
|
||||||
"m": [2]string{Fg(208), Fg(196)},
|
|
||||||
"md": [2]string{Fg(87), Fg(73)},
|
|
||||||
"ml": [2]string{Fg(208), Fg(94)},
|
|
||||||
"php": [2]string{Fg(30), Fg(22)},
|
|
||||||
"pl": [2]string{Fg(99), Fg(57)},
|
|
||||||
"py": [2]string{Fg(34), Fg(28)},
|
|
||||||
"r": [2]string{Fg(51), Fg(39)},
|
|
||||||
"rb": [2]string{FgRGB(5, 1, 0), FgRGB(3, 1, 1)},
|
|
||||||
"rs": [2]string{Fg(208), Fg(94)},
|
|
||||||
"scala": [2]string{Fg(196), Fg(124)},
|
|
||||||
"sh": [2]string{FgRGB(4, 0, 4), FgRGB(2, 0, 2)},
|
|
||||||
"sol": [2]string{Fg(39), Fg(27)},
|
|
||||||
"sql": [2]string{Fg(193), Fg(148)},
|
|
||||||
"svelte": [2]string{Fg(208), Fg(196)},
|
|
||||||
"swift": [2]string{Fg(223), Fg(215)},
|
|
||||||
"vim": [2]string{Fg(34), Fg(28)},
|
|
||||||
"vue": [2]string{Fg(43), Fg(29)},
|
|
||||||
"xml": [2]string{Fg(87), Fg(73)},
|
|
||||||
|
|
||||||
"compiled": [2]string{FgGray(8), FgGray(5)},
|
|
||||||
"compress": [2]string{FgRGB(5, 0, 0), FgRGB(3, 0, 0)},
|
|
||||||
"document": [2]string{FgRGB(5, 0, 0), FgRGB(3, 0, 0)},
|
|
||||||
"media": [2]string{Fg(141), Fg(99)},
|
|
||||||
"_default": [2]string{FgGray(23), FgGray(12)},
|
|
||||||
}
|
|
||||||
// FileAliases converts alternative extensions to their canonical mapping in FileColor
|
|
||||||
FileAliases = map[string]string{
|
|
||||||
"s": "asm",
|
|
||||||
"b": "bf",
|
|
||||||
"c++": "c",
|
|
||||||
"cc": "c",
|
|
||||||
"cpp": "c",
|
|
||||||
"cs": "c",
|
|
||||||
"cxx": "c",
|
|
||||||
"d": "c",
|
|
||||||
"h": "c",
|
|
||||||
"h++": "c",
|
|
||||||
"hh": "c",
|
|
||||||
"hpp": "c",
|
|
||||||
"hxx": "c",
|
|
||||||
"pxd": "c",
|
|
||||||
"cljc": "clj",
|
|
||||||
"cljs": "clj",
|
|
||||||
"class": "compiled",
|
|
||||||
"elc": "compiled",
|
|
||||||
"hi": "compiled",
|
|
||||||
"o": "compiled",
|
|
||||||
"pyc": "compiled",
|
|
||||||
"7z": "compress",
|
|
||||||
"Z": "compress",
|
|
||||||
"bz2": "compress",
|
|
||||||
"deb": "compress",
|
|
||||||
"dmg": "compress",
|
|
||||||
"dpkg": "compress",
|
|
||||||
"gz": "compress",
|
|
||||||
"iso": "compress",
|
|
||||||
"jar": "compress",
|
|
||||||
"lzma": "compress",
|
|
||||||
"par": "compress",
|
|
||||||
"rar": "compress",
|
|
||||||
"rpm": "compress",
|
|
||||||
"tar": "compress",
|
|
||||||
"tc": "compress",
|
|
||||||
"tgz": "compress",
|
|
||||||
"txz": "compress",
|
|
||||||
"whl": "compress",
|
|
||||||
"xz": "compress",
|
|
||||||
"z": "compress",
|
|
||||||
"zip": "compress",
|
|
||||||
"less": "css",
|
|
||||||
"sass": "css",
|
|
||||||
"scss": "css",
|
|
||||||
"styl": "css",
|
|
||||||
"djvu": "document",
|
|
||||||
"doc": "document",
|
|
||||||
"docx": "document",
|
|
||||||
"dvi": "document",
|
|
||||||
"eml": "document",
|
|
||||||
"fotd": "document",
|
|
||||||
"odp": "document",
|
|
||||||
"odt": "document",
|
|
||||||
"pdf": "document",
|
|
||||||
"ppt": "document",
|
|
||||||
"pptx": "document",
|
|
||||||
"rtf": "document",
|
|
||||||
"xls": "document",
|
|
||||||
"xlsx": "document",
|
|
||||||
"f03": "f",
|
|
||||||
"f77": "f",
|
|
||||||
"f90": "f",
|
|
||||||
"f95": "f",
|
|
||||||
"for": "f",
|
|
||||||
"fpp": "f",
|
|
||||||
"ftn": "f",
|
|
||||||
"fsi": "fs",
|
|
||||||
"fsscript": "fs",
|
|
||||||
"fsx": "fs",
|
|
||||||
"dna": "gb",
|
|
||||||
"gsh": "groovy",
|
|
||||||
"gvy": "groovy",
|
|
||||||
"gy": "groovy",
|
|
||||||
"htm": "html",
|
|
||||||
"xhtml": "html",
|
|
||||||
"bson": "js",
|
|
||||||
"json": "js",
|
|
||||||
"mjs": "js",
|
|
||||||
"ts": "js",
|
|
||||||
"tsx": "jsx",
|
|
||||||
"cjsx": "jsx",
|
|
||||||
"mat": "m",
|
|
||||||
"markdown": "md",
|
|
||||||
"mkd": "md",
|
|
||||||
"rst": "md",
|
|
||||||
"sml": "ml",
|
|
||||||
"mli": "ml",
|
|
||||||
"aac": "media",
|
|
||||||
"alac": "media",
|
|
||||||
"audio": "media",
|
|
||||||
"avi": "media",
|
|
||||||
"bmp": "media",
|
|
||||||
"cbr": "media",
|
|
||||||
"cbz": "media",
|
|
||||||
"eps": "media",
|
|
||||||
"flac": "media",
|
|
||||||
"flv": "media",
|
|
||||||
"gif": "media",
|
|
||||||
"ico": "media",
|
|
||||||
"image": "media",
|
|
||||||
"jpeg": "media",
|
|
||||||
"jpg": "media",
|
|
||||||
"m2v": "media",
|
|
||||||
"m4a": "media",
|
|
||||||
"mka": "media",
|
|
||||||
"mkv": "media",
|
|
||||||
"mov": "media",
|
|
||||||
"mp3": "media",
|
|
||||||
"mp4": "media",
|
|
||||||
"mpeg": "media",
|
|
||||||
"mpg": "media",
|
|
||||||
"nef": "media",
|
|
||||||
"ogg": "media",
|
|
||||||
"ogm": "media",
|
|
||||||
"ogv": "media",
|
|
||||||
"opus": "media",
|
|
||||||
"orf": "media",
|
|
||||||
"pbm": "media",
|
|
||||||
"pgm": "media",
|
|
||||||
"png": "media",
|
|
||||||
"pnm": "media",
|
|
||||||
"ppm": "media",
|
|
||||||
"pxm": "media",
|
|
||||||
"stl": "media",
|
|
||||||
"svg": "media",
|
|
||||||
"tif": "media",
|
|
||||||
"tiff": "media",
|
|
||||||
"video": "media",
|
|
||||||
"vob": "media",
|
|
||||||
"wav": "media",
|
|
||||||
"webm": "media",
|
|
||||||
"webp": "media",
|
|
||||||
"wma": "media",
|
|
||||||
"wmv": "media",
|
|
||||||
"xpm": "media",
|
|
||||||
"php3": "php",
|
|
||||||
"php4": "php",
|
|
||||||
"php5": "php",
|
|
||||||
"phpt": "php",
|
|
||||||
"phtml": "php",
|
|
||||||
"ipynb": "py",
|
|
||||||
"pickle": "py",
|
|
||||||
"pkl": "py",
|
|
||||||
"pyx": "py",
|
|
||||||
"bash": "sh",
|
|
||||||
"csh": "sh",
|
|
||||||
"fish": "sh",
|
|
||||||
"ksh": "sh",
|
|
||||||
"zsh": "sh",
|
|
||||||
"plpgsql": "sql",
|
|
||||||
"plsql": "sql",
|
|
||||||
"psql": "sql",
|
|
||||||
"tsql": "sql",
|
|
||||||
"vimrc": "vim",
|
|
||||||
}
|
|
||||||
// SizeColor has the color mappings for ranges of file sizes
|
|
||||||
SizeColor = map[string]string{
|
|
||||||
"B": Fg(27),
|
|
||||||
"K": Fg(33),
|
|
||||||
"M": Fg(81),
|
|
||||||
"G": Fg(123),
|
|
||||||
"T": Fg(159),
|
|
||||||
}
|
|
||||||
// ConfigColor holds mappings for other various colors
|
|
||||||
ConfigColor = map[string]map[string]string{
|
|
||||||
"dir": map[string]string{
|
|
||||||
"name": Bold + BgRGB(0, 0, 2) + FgGray(23),
|
|
||||||
"ext": FgRGB(2, 2, 5),
|
|
||||||
},
|
|
||||||
".dir": map[string]string{
|
|
||||||
"name": Bold + BgRGB(0, 0, 1) + FgGray(23),
|
|
||||||
"ext": FgRGB(2, 2, 5),
|
|
||||||
},
|
|
||||||
"folderHeader": map[string]string{
|
|
||||||
"arrow": FgRGB(3, 2, 0),
|
|
||||||
"main": BgGray(2) + FgRGB(3, 2, 0),
|
|
||||||
"slash": FgGray(5),
|
|
||||||
"lastFolder": Bold + FgRGB(5, 5, 0),
|
|
||||||
"error": BgRGB(5, 0, 0) + FgRGB(5, 5, 0),
|
|
||||||
},
|
|
||||||
"link": map[string]string{
|
|
||||||
"name": Bold + FgRGB(0, 5, 0),
|
|
||||||
"nameDir": Bold + BgRGB(0, 0, 2) + FgRGB(0, 5, 5),
|
|
||||||
"arrow": FgRGB(1, 0, 1),
|
|
||||||
"path": FgRGB(4, 0, 4),
|
|
||||||
"broken": FgRGB(5, 0, 0),
|
|
||||||
},
|
|
||||||
"device": map[string]string{
|
|
||||||
"name": Bold + BgGray(3) + Fg(220),
|
|
||||||
},
|
|
||||||
"socket": map[string]string{
|
|
||||||
"name": Bold + Bg(53) + Fg(15),
|
|
||||||
},
|
|
||||||
"pipe": map[string]string{
|
|
||||||
"name": Bold + Bg(94) + Fg(15),
|
|
||||||
},
|
|
||||||
"stats": map[string]string{
|
|
||||||
"text": BgGray(2) + FgGray(15),
|
|
||||||
"number": Fg(24),
|
|
||||||
"ms": Fg(39),
|
|
||||||
},
|
|
||||||
}
|
|
||||||
// PermsColor holds color mappings for users and groups
|
|
||||||
PermsColor = map[string]map[string]string{
|
|
||||||
"user": map[string]string{
|
|
||||||
"root": FgRGB(5, 0, 2),
|
|
||||||
"daemon": FgRGB(4, 2, 1),
|
|
||||||
"_self": FgRGB(0, 4, 0),
|
|
||||||
"_default": FgRGB(0, 3, 3),
|
|
||||||
},
|
|
||||||
"group": map[string]string{
|
|
||||||
"wheel": FgRGB(3, 0, 0),
|
|
||||||
"staff": FgRGB(0, 2, 0),
|
|
||||||
"admin": FgRGB(2, 2, 0),
|
|
||||||
"_default": FgRGB(2, 0, 2),
|
|
||||||
},
|
|
||||||
"other": map[string]string{
|
|
||||||
"_default": BgGray(2) + FgGray(15),
|
|
||||||
},
|
|
||||||
}
|
|
||||||
)
|
|
@ -1,402 +0,0 @@
|
|||||||
package lsgo
|
|
||||||
|
|
||||||
import (
|
|
||||||
"strings"
|
|
||||||
)
|
|
||||||
|
|
||||||
func getIconForFile(name, ext string) string {
|
|
||||||
// default icon for all files. try to find a better one though...
|
|
||||||
icon := icons["file"]
|
|
||||||
|
|
||||||
// resolve aliased extensions
|
|
||||||
extKey := strings.ToLower(ext)
|
|
||||||
alias, hasAlias := aliases[extKey]
|
|
||||||
if hasAlias {
|
|
||||||
extKey = alias
|
|
||||||
}
|
|
||||||
|
|
||||||
// see if we can find a better icon based on extension alone
|
|
||||||
betterIcon, hasBetterIcon := icons[extKey]
|
|
||||||
if hasBetterIcon {
|
|
||||||
icon = betterIcon
|
|
||||||
}
|
|
||||||
|
|
||||||
// now look for icons based on full names
|
|
||||||
fullName := name
|
|
||||||
if ext != "" {
|
|
||||||
fullName += "." + ext
|
|
||||||
}
|
|
||||||
|
|
||||||
fullName = strings.ToLower(fullName)
|
|
||||||
fullAlias, hasFullAlias := aliases[fullName]
|
|
||||||
if hasFullAlias {
|
|
||||||
fullName = fullAlias
|
|
||||||
}
|
|
||||||
bestIcon, hasBestIcon := icons[fullName]
|
|
||||||
if hasBestIcon {
|
|
||||||
icon = bestIcon
|
|
||||||
}
|
|
||||||
return icon
|
|
||||||
}
|
|
||||||
|
|
||||||
func getIconForFolder(name string) string {
|
|
||||||
icon := folders["folder"]
|
|
||||||
betterIcon, hasBetterIcon := folders[name]
|
|
||||||
if hasBetterIcon {
|
|
||||||
icon = betterIcon
|
|
||||||
}
|
|
||||||
return icon
|
|
||||||
}
|
|
||||||
|
|
||||||
var icons = map[string]string{
|
|
||||||
"ai": "\ue7b4",
|
|
||||||
"android": "\ue70e",
|
|
||||||
"apple": "\uf179",
|
|
||||||
"as": "\ue60b",
|
|
||||||
"asm": "\ufb19",
|
|
||||||
"audio": "\uf1c7",
|
|
||||||
"avro": "\ue60b",
|
|
||||||
"bf": "\uf067",
|
|
||||||
"binary": "\uf471",
|
|
||||||
"c": "\ue61e",
|
|
||||||
"cargo.lock": "\uf487",
|
|
||||||
"cargo.toml": "\uf487",
|
|
||||||
"cfg": "\uf423",
|
|
||||||
"clj": "\ue768",
|
|
||||||
"coffee": "\ue751",
|
|
||||||
"conf": "\ue615",
|
|
||||||
"cpp": "\ue61d",
|
|
||||||
"cr": "\ue23e",
|
|
||||||
"cs": "\uf81a",
|
|
||||||
"cson": "\ue601",
|
|
||||||
"css": "\ue749",
|
|
||||||
"d": "\ue7af",
|
|
||||||
"dart": "\ue798",
|
|
||||||
"db": "\uf1c0",
|
|
||||||
"deb": "\uf306",
|
|
||||||
"diff": "\uf440",
|
|
||||||
"doc": "\uf1c2",
|
|
||||||
"dockerfile": "\ue7b0",
|
|
||||||
"dpkg": "\uf17c",
|
|
||||||
"ebook": "\uf02d",
|
|
||||||
"elm": "\ue62c",
|
|
||||||
"env": "\uf462",
|
|
||||||
"erl": "\ue7b1",
|
|
||||||
"ex": "\ue62d",
|
|
||||||
"f": "\uf794",
|
|
||||||
"file": "\uf15b",
|
|
||||||
"font": "\uf031",
|
|
||||||
"fs": "\ue7a7",
|
|
||||||
"gb": "\ue272",
|
|
||||||
"gform": "\uf298",
|
|
||||||
"git": "\ue702",
|
|
||||||
"go": "\ue724",
|
|
||||||
"graphql": "\ue284",
|
|
||||||
"groovy": "\ue775",
|
|
||||||
"gruntfile.js": "\ue74c",
|
|
||||||
"gulpfile.js": "\ue610",
|
|
||||||
"gv": "\ue225",
|
|
||||||
"h": "\uf0fd",
|
|
||||||
"hs": "\ue777",
|
|
||||||
"html": "\uf13b",
|
|
||||||
"ics": "\uf073",
|
|
||||||
"image": "\uf1c5",
|
|
||||||
"iml": "\ue7b5",
|
|
||||||
"ini": "\uf669",
|
|
||||||
"ino": "\ue255",
|
|
||||||
"iso": "\uf7c9",
|
|
||||||
"java": "\ue738",
|
|
||||||
"jenkinsfile": "\ue767",
|
|
||||||
"jl": "\ue624",
|
|
||||||
"js": "\ue781",
|
|
||||||
"json": "\ue60b",
|
|
||||||
"jsx": "\ue7ba",
|
|
||||||
"key": "\uf43d",
|
|
||||||
"less": "\ue758",
|
|
||||||
"lock": "\uf720",
|
|
||||||
"log": "\uf18d",
|
|
||||||
"lua": "\ue620",
|
|
||||||
"m": "\ufb27",
|
|
||||||
"maintainers": "\uf0c0",
|
|
||||||
"makefile": "\ue20f",
|
|
||||||
"md": "\uf48a",
|
|
||||||
"mjs": "\ue718",
|
|
||||||
"ml": "\ufb26",
|
|
||||||
"mustache": "\ue60f",
|
|
||||||
"nc": "\uf7c0",
|
|
||||||
"npmignore": "\ue71e",
|
|
||||||
"passwd": "\uf023",
|
|
||||||
"patch": "\uf440",
|
|
||||||
"pdf": "\uf1c1",
|
|
||||||
"php": "\ue608",
|
|
||||||
"pl": "\ue7a1",
|
|
||||||
"ppt": "\uf1c4",
|
|
||||||
"psd": "\ue7b8",
|
|
||||||
"py": "\ue606",
|
|
||||||
"r": "\ufcd2",
|
|
||||||
"rb": "\ue21e",
|
|
||||||
"rdb": "\ue76d",
|
|
||||||
"rpm": "\uf17c",
|
|
||||||
"rs": "\ue7a8",
|
|
||||||
"rss": "\uf09e",
|
|
||||||
"rst": "\uf66a",
|
|
||||||
"rubydoc": "\ue73b",
|
|
||||||
"sass": "\ue603",
|
|
||||||
"scala": "\ue737",
|
|
||||||
"shell": "\uf489",
|
|
||||||
"shp": "\ufa5f",
|
|
||||||
"sol": "\ufcb9",
|
|
||||||
"sql": "\ue706",
|
|
||||||
"sqlite3": "\ue7c4",
|
|
||||||
"styl": "\ue600",
|
|
||||||
"swift": "\ue755",
|
|
||||||
"tex": "\u222b",
|
|
||||||
"tfrecord": "\ufb27",
|
|
||||||
"toml": "\uf669",
|
|
||||||
"ts": "\ufbe4",
|
|
||||||
"twig": "\ue61c",
|
|
||||||
"txt": "\uf15c",
|
|
||||||
"vagrantfile": "\ue21e",
|
|
||||||
"video": "\uf03d",
|
|
||||||
"vim": "\ue62b",
|
|
||||||
"vue": "\ufd42",
|
|
||||||
"windows": "\uf17a",
|
|
||||||
"xls": "\uf1c3",
|
|
||||||
"xml": "\ue796",
|
|
||||||
"yml": "\ue601",
|
|
||||||
"zip": "\uf410",
|
|
||||||
}
|
|
||||||
|
|
||||||
var aliases = map[string]string{
|
|
||||||
"apk": "android",
|
|
||||||
"gradle": "android",
|
|
||||||
"ds_store": "apple",
|
|
||||||
"localized": "apple",
|
|
||||||
"s": "asm",
|
|
||||||
"aac": "audio",
|
|
||||||
"alac": "audio",
|
|
||||||
"flac": "audio",
|
|
||||||
"m4a": "audio",
|
|
||||||
"mka": "audio",
|
|
||||||
"mp3": "audio",
|
|
||||||
"ogg": "audio",
|
|
||||||
"opus": "audio",
|
|
||||||
"wav": "audio",
|
|
||||||
"wma": "audio",
|
|
||||||
"b": "bf",
|
|
||||||
"bson": "binary",
|
|
||||||
"feather": "binary",
|
|
||||||
"mat": "binary",
|
|
||||||
"o": "binary",
|
|
||||||
"pb": "binary",
|
|
||||||
"pickle": "binary",
|
|
||||||
"pkl": "binary",
|
|
||||||
"conf": "cfg",
|
|
||||||
"config": "cfg",
|
|
||||||
"cljc": "clj",
|
|
||||||
"cljs": "clj",
|
|
||||||
"editorconfig": "conf",
|
|
||||||
"rc": "conf",
|
|
||||||
"c++": "cpp",
|
|
||||||
"cc": "cpp",
|
|
||||||
"cxx": "cpp",
|
|
||||||
"scss": "css",
|
|
||||||
"docx": "doc",
|
|
||||||
"gdoc": "doc",
|
|
||||||
"epub": "ebook",
|
|
||||||
"ipynb": "ebook",
|
|
||||||
"mobi": "ebook",
|
|
||||||
"f03": "f",
|
|
||||||
"f77": "f",
|
|
||||||
"f90": "f",
|
|
||||||
"f95": "f",
|
|
||||||
"for": "f",
|
|
||||||
"fpp": "f",
|
|
||||||
"ftn": "f",
|
|
||||||
"eot": "font",
|
|
||||||
"otf": "font",
|
|
||||||
"ttf": "font",
|
|
||||||
"woff": "font",
|
|
||||||
"woff2": "font",
|
|
||||||
"fsi": "fs",
|
|
||||||
"fsscript": "fs",
|
|
||||||
"fsx": "fs",
|
|
||||||
"dna": "gb",
|
|
||||||
"gitattributes": "git",
|
|
||||||
"gitconfig": "git",
|
|
||||||
"gitignore": "git",
|
|
||||||
"gitignore_global": "git",
|
|
||||||
"gitmirrorall": "git",
|
|
||||||
"gitmodules": "git",
|
|
||||||
"gsh": "groovy",
|
|
||||||
"gvy": "groovy",
|
|
||||||
"gy": "groovy",
|
|
||||||
"h++": "h",
|
|
||||||
"hh": "h",
|
|
||||||
"hpp": "h",
|
|
||||||
"hxx": "h",
|
|
||||||
"lhs": "hs",
|
|
||||||
"htm": "html",
|
|
||||||
"xhtml": "html",
|
|
||||||
"bmp": "image",
|
|
||||||
"cbr": "image",
|
|
||||||
"cbz": "image",
|
|
||||||
"dvi": "image",
|
|
||||||
"eps": "image",
|
|
||||||
"gif": "image",
|
|
||||||
"ico": "image",
|
|
||||||
"jpeg": "image",
|
|
||||||
"jpg": "image",
|
|
||||||
"nef": "image",
|
|
||||||
"orf": "image",
|
|
||||||
"pbm": "image",
|
|
||||||
"pgm": "image",
|
|
||||||
"png": "image",
|
|
||||||
"pnm": "image",
|
|
||||||
"ppm": "image",
|
|
||||||
"pxm": "image",
|
|
||||||
"stl": "image",
|
|
||||||
"svg": "image",
|
|
||||||
"tif": "image",
|
|
||||||
"tiff": "image",
|
|
||||||
"webp": "image",
|
|
||||||
"xpm": "image",
|
|
||||||
"disk": "iso",
|
|
||||||
"dmg": "iso",
|
|
||||||
"smi": "iso",
|
|
||||||
"img": "iso",
|
|
||||||
"vhd": "iso",
|
|
||||||
"vhdx": "iso",
|
|
||||||
"vmdk": "iso",
|
|
||||||
"jar": "java",
|
|
||||||
"properties": "json",
|
|
||||||
"webmanifest": "json",
|
|
||||||
"tsx": "jsx",
|
|
||||||
"cjsx": "jsx",
|
|
||||||
"cer": "key",
|
|
||||||
"crt": "key",
|
|
||||||
"der": "key",
|
|
||||||
"gpg": "key",
|
|
||||||
"p7b": "key",
|
|
||||||
"pem": "key",
|
|
||||||
"pfx": "key",
|
|
||||||
"pgp": "key",
|
|
||||||
"license": "key",
|
|
||||||
"codeowners": "maintainers",
|
|
||||||
"credits": "maintainers",
|
|
||||||
"cmake": "makefile",
|
|
||||||
"markdown": "md",
|
|
||||||
"mkd": "md",
|
|
||||||
"rdoc": "md",
|
|
||||||
"readme": "md",
|
|
||||||
"mli": "ml",
|
|
||||||
"sml": "ml",
|
|
||||||
"netcdf": "nc",
|
|
||||||
"php3": "php",
|
|
||||||
"php4": "php",
|
|
||||||
"php5": "php",
|
|
||||||
"phpt": "php",
|
|
||||||
"phtml": "php",
|
|
||||||
"gslides": "ppt",
|
|
||||||
"pptx": "ppt",
|
|
||||||
"pxd": "py",
|
|
||||||
"pyc": "py",
|
|
||||||
"pyx": "py",
|
|
||||||
"whl": "py",
|
|
||||||
"rdata": "r",
|
|
||||||
"rds": "r",
|
|
||||||
"rmd": "r",
|
|
||||||
"gemfile": "rb",
|
|
||||||
"gemspec": "rb",
|
|
||||||
"guardfile": "rb",
|
|
||||||
"procfile": "rb",
|
|
||||||
"rakefile": "rb",
|
|
||||||
"rspec": "rb",
|
|
||||||
"rspec_parallel": "rb",
|
|
||||||
"rspec_status": "rb",
|
|
||||||
"ru": "rb",
|
|
||||||
"erb": "rubydoc",
|
|
||||||
"slim": "rubydoc",
|
|
||||||
"awk": "shell",
|
|
||||||
"bash": "shell",
|
|
||||||
"bash_history": "shell",
|
|
||||||
"bash_profile": "shell",
|
|
||||||
"bashrc": "shell",
|
|
||||||
"csh": "shell",
|
|
||||||
"fish": "shell",
|
|
||||||
"ksh": "shell",
|
|
||||||
"sh": "shell",
|
|
||||||
"zsh": "shell",
|
|
||||||
"zsh-theme": "shell",
|
|
||||||
"zshrc": "shell",
|
|
||||||
"plpgsql": "sql",
|
|
||||||
"plsql": "sql",
|
|
||||||
"psql": "sql",
|
|
||||||
"tsql": "sql",
|
|
||||||
"sl3": "sqlite3",
|
|
||||||
"stylus": "styl",
|
|
||||||
"cls": "tex",
|
|
||||||
"avi": "video",
|
|
||||||
"flv": "video",
|
|
||||||
"m2v": "video",
|
|
||||||
"mkv": "video",
|
|
||||||
"mov": "video",
|
|
||||||
"mp4": "video",
|
|
||||||
"mpeg": "video",
|
|
||||||
"mpg": "video",
|
|
||||||
"ogm": "video",
|
|
||||||
"ogv": "video",
|
|
||||||
"vob": "video",
|
|
||||||
"webm": "video",
|
|
||||||
"vimrc": "vim",
|
|
||||||
"bat": "windows",
|
|
||||||
"cmd": "windows",
|
|
||||||
"exe": "windows",
|
|
||||||
"csv": "xls",
|
|
||||||
"gsheet": "xls",
|
|
||||||
"xlsx": "xls",
|
|
||||||
"svelte": "xml",
|
|
||||||
"plist": "xml",
|
|
||||||
"xul": "xml",
|
|
||||||
"yaml": "yml",
|
|
||||||
"7z": "zip",
|
|
||||||
"Z": "zip",
|
|
||||||
"bz2": "zip",
|
|
||||||
"gz": "zip",
|
|
||||||
"lzma": "zip",
|
|
||||||
"par": "zip",
|
|
||||||
"rar": "zip",
|
|
||||||
"tar": "zip",
|
|
||||||
"tc": "zip",
|
|
||||||
"tgz": "zip",
|
|
||||||
"txz": "zip",
|
|
||||||
"xz": "zip",
|
|
||||||
"z": "zip",
|
|
||||||
}
|
|
||||||
|
|
||||||
var folders = map[string]string{
|
|
||||||
".atom": "\ue764",
|
|
||||||
".aws": "\ue7ad",
|
|
||||||
".docker": "\ue7b0",
|
|
||||||
".gem": "\ue21e",
|
|
||||||
".git": "\ue5fb",
|
|
||||||
".git-credential-cache": "\ue5fb",
|
|
||||||
".github": "\ue5fd",
|
|
||||||
".npm": "\ue5fa",
|
|
||||||
".nvm": "\ue718",
|
|
||||||
".rvm": "\ue21e",
|
|
||||||
".Trash": "\uf1f8",
|
|
||||||
".vscode": "\ue70c",
|
|
||||||
".vim": "\ue62b",
|
|
||||||
"config": "\ue5fc",
|
|
||||||
"folder": "\uf07c",
|
|
||||||
"hidden": "\uf023",
|
|
||||||
"node_modules": "\ue5fa",
|
|
||||||
}
|
|
||||||
|
|
||||||
var otherIcons = map[string]string{
|
|
||||||
"link": "\uf0c1",
|
|
||||||
"linkDir": "\uf0c1",
|
|
||||||
"brokenLink": "\uf127",
|
|
||||||
"device": "\uf0a0",
|
|
||||||
}
|
|
Binary file not shown.
Before Width: | Height: | Size: 20 KiB |
Binary file not shown.
Before Width: | Height: | Size: 135 KiB |
Binary file not shown.
Before Width: | Height: | Size: 135 KiB |
Binary file not shown.
Before Width: | Height: | Size: 100 KiB |
Binary file not shown.
Before Width: | Height: | Size: 28 KiB |
Binary file not shown.
Before Width: | Height: | Size: 57 KiB |
@ -1,46 +0,0 @@
|
|||||||
// +build !windows
|
|
||||||
|
|
||||||
package lsgo
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
"os"
|
|
||||||
"os/user"
|
|
||||||
"strconv"
|
|
||||||
"strings"
|
|
||||||
"syscall"
|
|
||||||
|
|
||||||
"github.com/willf/pad"
|
|
||||||
"golang.org/x/sys/unix"
|
|
||||||
)
|
|
||||||
|
|
||||||
func getOwnerAndGroup(fileInfo *os.FileInfo) (string, string) {
|
|
||||||
statT := (*fileInfo).Sys().(*syscall.Stat_t)
|
|
||||||
uid := fmt.Sprint(statT.Uid)
|
|
||||||
gid := fmt.Sprint(statT.Gid)
|
|
||||||
owner, err := user.LookupId(uid)
|
|
||||||
var ownerName string
|
|
||||||
if err == nil {
|
|
||||||
ownerName = owner.Username
|
|
||||||
} else {
|
|
||||||
ownerName = uid
|
|
||||||
}
|
|
||||||
|
|
||||||
group, err := user.LookupGroupId(gid)
|
|
||||||
var groupName string
|
|
||||||
if err == nil {
|
|
||||||
groupName = group.Name
|
|
||||||
} else {
|
|
||||||
groupName = gid
|
|
||||||
}
|
|
||||||
return ownerName, groupName
|
|
||||||
}
|
|
||||||
|
|
||||||
func deviceNumbers(absPath string) string {
|
|
||||||
stat := syscall.Stat_t{}
|
|
||||||
err := syscall.Stat(absPath, &stat)
|
|
||||||
check(err)
|
|
||||||
major := strconv.FormatInt(int64(unix.Major(uint64(stat.Rdev))), 10)
|
|
||||||
minor := strconv.FormatInt(int64(unix.Minor(uint64(stat.Rdev))), 10)
|
|
||||||
return pad.Left(strings.Join([]string{major, minor}, ","), 7, " ") + " " + Reset
|
|
||||||
}
|
|
@ -1,65 +0,0 @@
|
|||||||
// +build windows
|
|
||||||
|
|
||||||
package lsgo
|
|
||||||
|
|
||||||
import (
|
|
||||||
"os"
|
|
||||||
"strconv"
|
|
||||||
"strings"
|
|
||||||
"syscall"
|
|
||||||
"unsafe"
|
|
||||||
|
|
||||||
"github.com/willf/pad"
|
|
||||||
"golang.org/x/sys/windows"
|
|
||||||
)
|
|
||||||
|
|
||||||
var (
|
|
||||||
libadvapi32 = syscall.NewLazyDLL("advapi32.dll")
|
|
||||||
procGetFileSecurity = libadvapi32.NewProc("GetFileSecurityW")
|
|
||||||
procGetSecurityDescriptorOwner = libadvapi32.NewProc("GetSecurityDescriptorOwner")
|
|
||||||
)
|
|
||||||
|
|
||||||
func getOwnerAndGroup(fileInfo *os.FileInfo) (string, string) {
|
|
||||||
path := (*fileInfo).Name()
|
|
||||||
|
|
||||||
var needed uint32
|
|
||||||
procGetFileSecurity.Call(
|
|
||||||
uintptr(unsafe.Pointer(syscall.StringToUTF16Ptr(path))),
|
|
||||||
0x00000001, /* OWNER_SECURITY_INFORMATION */
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
uintptr(unsafe.Pointer(&needed)))
|
|
||||||
buf := make([]byte, needed)
|
|
||||||
r1, _, err := procGetFileSecurity.Call(
|
|
||||||
uintptr(unsafe.Pointer(syscall.StringToUTF16Ptr(path))),
|
|
||||||
0x00000001, /* OWNER_SECURITY_INFORMATION */
|
|
||||||
uintptr(unsafe.Pointer(&buf[0])),
|
|
||||||
uintptr(needed),
|
|
||||||
uintptr(unsafe.Pointer(&needed)))
|
|
||||||
if r1 == 0 && err != nil {
|
|
||||||
return "", ""
|
|
||||||
}
|
|
||||||
var ownerDefaulted uint32
|
|
||||||
var sid *syscall.SID
|
|
||||||
r1, _, err = procGetSecurityDescriptorOwner.Call(
|
|
||||||
uintptr(unsafe.Pointer(&buf[0])),
|
|
||||||
uintptr(unsafe.Pointer(&sid)),
|
|
||||||
uintptr(unsafe.Pointer(&ownerDefaulted)))
|
|
||||||
if r1 == 0 && err != nil {
|
|
||||||
return "", ""
|
|
||||||
}
|
|
||||||
uid, gid, _, err := sid.LookupAccount("")
|
|
||||||
if r1 == 0 && err != nil {
|
|
||||||
return "", ""
|
|
||||||
}
|
|
||||||
return uid, gid
|
|
||||||
}
|
|
||||||
|
|
||||||
func deviceNumbers(absPath string) string {
|
|
||||||
stat := syscall.Stat_t{}
|
|
||||||
err := syscall.Stat(absPath, &stat)
|
|
||||||
check(err)
|
|
||||||
major := strconv.FormatInt(int64(windows.Major(uint64(stat.Rdev))), 10)
|
|
||||||
minor := strconv.FormatInt(int64(windows.Minor(uint64(stat.Rdev))), 10)
|
|
||||||
return pad.Left(strings.Join([]string{major, minor}, ","), 7, " ") + " " + Reset
|
|
||||||
}
|
|
650
lsgo/lsgo.go
650
lsgo/lsgo.go
@ -1,650 +0,0 @@
|
|||||||
package lsgo
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
"io/ioutil"
|
|
||||||
"math"
|
|
||||||
"os"
|
|
||||||
"path"
|
|
||||||
"path/filepath"
|
|
||||||
"regexp"
|
|
||||||
"sort"
|
|
||||||
"strconv"
|
|
||||||
"strings"
|
|
||||||
"time"
|
|
||||||
|
|
||||||
"github.com/acarl005/textcol"
|
|
||||||
colorable "github.com/mattn/go-colorable"
|
|
||||||
"github.com/willf/pad"
|
|
||||||
kingpin "gopkg.in/alecthomas/kingpin.v2"
|
|
||||||
)
|
|
||||||
|
|
||||||
// DisplayItem wraps the file stat info and string to be printed
|
|
||||||
type DisplayItem struct {
|
|
||||||
display string
|
|
||||||
info os.FileInfo
|
|
||||||
basename string
|
|
||||||
ext string
|
|
||||||
link *LinkInfo
|
|
||||||
}
|
|
||||||
|
|
||||||
// LinkInfo wraps link stat info and whether the link points to valid file
|
|
||||||
type LinkInfo struct {
|
|
||||||
path string
|
|
||||||
info os.FileInfo
|
|
||||||
broken bool
|
|
||||||
}
|
|
||||||
|
|
||||||
var (
|
|
||||||
// True is a helper varable to help make pointers to `true`
|
|
||||||
True = true
|
|
||||||
sizeUnits = []string{"B", "K", "M", "G", "T"}
|
|
||||||
dateFormat = "02.Jan'06" // uses the "reference time" https://golang.org/pkg/time/#Time.Format
|
|
||||||
timeFormat = "15:04"
|
|
||||||
start int64 // keep track of execution time
|
|
||||||
stdout = colorable.NewColorableStdout() // write to this to allow ANSI color codes to be compatible on Windows
|
|
||||||
)
|
|
||||||
|
|
||||||
// func LsGo(cmd *cobra.Command, args []string) {
|
|
||||||
func LsGo() error {
|
|
||||||
var err error
|
|
||||||
|
|
||||||
textcol.Output = stdout
|
|
||||||
|
|
||||||
start = time.Now().UnixNano()
|
|
||||||
// auto-generate help text for the command with -h
|
|
||||||
kingpin.CommandLine.HelpFlag.Short('h')
|
|
||||||
|
|
||||||
// parse the arguments and populate the struct
|
|
||||||
kingpin.Parse()
|
|
||||||
argsPostParse()
|
|
||||||
|
|
||||||
// separate the directories from the regular files
|
|
||||||
dirs := []string{}
|
|
||||||
files := []os.FileInfo{}
|
|
||||||
for _, pathStr := range *args.paths {
|
|
||||||
var fileStat os.FileInfo
|
|
||||||
fileStat, err = os.Stat(pathStr)
|
|
||||||
if err != nil && strings.Contains(err.Error(), "no such file or directory") {
|
|
||||||
printErrorHeader(err, prettifyPath(pathStr))
|
|
||||||
continue
|
|
||||||
} else {
|
|
||||||
check(err)
|
|
||||||
}
|
|
||||||
if fileStat.IsDir() {
|
|
||||||
dirs = append(dirs, pathStr)
|
|
||||||
} else {
|
|
||||||
files = append(files, fileStat)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// list files first
|
|
||||||
if len(files) > 0 {
|
|
||||||
pwd := os.Getenv("PWD")
|
|
||||||
listFiles(pwd, &files, true)
|
|
||||||
}
|
|
||||||
|
|
||||||
// then list the contents of each directory
|
|
||||||
for i, dir := range dirs {
|
|
||||||
// print a blank line between directories, but not before the first one
|
|
||||||
if i > 0 {
|
|
||||||
fmt.Fprintln(stdout, "")
|
|
||||||
}
|
|
||||||
listDir(dir)
|
|
||||||
}
|
|
||||||
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
func listDir(pathStr string) {
|
|
||||||
items, err := ioutil.ReadDir(pathStr)
|
|
||||||
// if we couldn't read the folder, print a "header" with error message and use error-looking colors
|
|
||||||
if err != nil {
|
|
||||||
if strings.Contains(err.Error(), "no such file or directory") || strings.Contains(err.Error(), "permission denied") {
|
|
||||||
printErrorHeader(err, prettifyPath(pathStr))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
check(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
// filter by the regexp if one was passed
|
|
||||||
if len(*args.find) > 0 {
|
|
||||||
filteredItems := []os.FileInfo{}
|
|
||||||
for _, fileInfo := range items {
|
|
||||||
re, err := regexp.Compile(*args.find)
|
|
||||||
check(err)
|
|
||||||
if re.MatchString(fileInfo.Name()) {
|
|
||||||
filteredItems = append(filteredItems, fileInfo)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
items = filteredItems
|
|
||||||
}
|
|
||||||
|
|
||||||
if !(len(*args.find) > 0 && len(items) == 0) &&
|
|
||||||
!(len(*args.paths) == 1 && (*args.paths)[0] == "." && !*args.recurse) {
|
|
||||||
printFolderHeader(pathStr)
|
|
||||||
}
|
|
||||||
|
|
||||||
if len(items) > 0 {
|
|
||||||
listFiles(pathStr, &items, false)
|
|
||||||
}
|
|
||||||
|
|
||||||
if *args.recurse {
|
|
||||||
for _, item := range items {
|
|
||||||
if item.IsDir() && (item.Name()[0] != '.' || *args.all) {
|
|
||||||
fmt.Fprintln(stdout, "") // put a blank line between directories
|
|
||||||
listDir(path.Join(pathStr, item.Name()))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func listFiles(parentDir string, items *[]os.FileInfo, forceDotfiles bool) {
|
|
||||||
absPath, err := filepath.Abs(parentDir)
|
|
||||||
check(err)
|
|
||||||
|
|
||||||
// collect all the contents here
|
|
||||||
files := []*DisplayItem{}
|
|
||||||
dirs := []*DisplayItem{}
|
|
||||||
|
|
||||||
// to help with formatting, we need to know the length of the longest name to add appropriate padding
|
|
||||||
longestOwnerName := 0
|
|
||||||
longestGroupName := 0
|
|
||||||
if *args.owner {
|
|
||||||
for _, fileInfo := range *items {
|
|
||||||
owner, group := getOwnerAndGroup(&fileInfo)
|
|
||||||
longestOwnerName = max(longestOwnerName, len(owner))
|
|
||||||
longestGroupName = max(longestGroupName, len(group))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, fileInfo := range *items {
|
|
||||||
// if this is a dotfile (hidden file)
|
|
||||||
if fileInfo.Name()[0] == '.' {
|
|
||||||
// we can skip everything with this file if we aren't using the `all` option
|
|
||||||
if !*args.all && !forceDotfiles {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
basename, ext := splitExt(fileInfo.Name())
|
|
||||||
|
|
||||||
displayItem := DisplayItem{
|
|
||||||
info: fileInfo,
|
|
||||||
ext: ext,
|
|
||||||
basename: basename,
|
|
||||||
}
|
|
||||||
|
|
||||||
// read some info about linked file if this item is a symlink
|
|
||||||
if fileInfo.Mode()&os.ModeSymlink != 0 {
|
|
||||||
getLinkInfo(&displayItem, absPath)
|
|
||||||
}
|
|
||||||
|
|
||||||
if fileInfo.IsDir() || (fileInfo.Mode()&os.ModeSymlink != 0 &&
|
|
||||||
displayItem.link.info != nil &&
|
|
||||||
displayItem.link.info.IsDir()) {
|
|
||||||
if *args.files {
|
|
||||||
continue
|
|
||||||
} else {
|
|
||||||
dirs = append(dirs, &displayItem)
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if *args.dirs {
|
|
||||||
continue
|
|
||||||
} else {
|
|
||||||
files = append(files, &displayItem)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
owner, group := getOwnerAndGroup(&fileInfo)
|
|
||||||
ownerColor, groupColor := getOwnerAndGroupColors(owner, group)
|
|
||||||
|
|
||||||
if *args.perms {
|
|
||||||
displayItem.display += permString(fileInfo, ownerColor, groupColor)
|
|
||||||
}
|
|
||||||
|
|
||||||
if *args.owner {
|
|
||||||
paddedOwner := pad.Right(owner, longestOwnerName, " ")
|
|
||||||
ownerInfo := []string{Reset + ownerColor + paddedOwner}
|
|
||||||
if !*args.nogroup {
|
|
||||||
paddedGroup := pad.Right(group, longestGroupName, " ")
|
|
||||||
ownerInfo = append(ownerInfo, groupColor+paddedGroup)
|
|
||||||
}
|
|
||||||
ownerInfo = append(ownerInfo, Reset)
|
|
||||||
displayItem.display += strings.Join(ownerInfo, " ")
|
|
||||||
}
|
|
||||||
|
|
||||||
if *args.bytes {
|
|
||||||
if fileInfo.Mode()&os.ModeDevice != 0 {
|
|
||||||
displayItem.display += deviceNumbers(path.Join(absPath, fileInfo.Name()))
|
|
||||||
} else {
|
|
||||||
displayItem.display += sizeString(fileInfo.Size())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if *args.mdate {
|
|
||||||
displayItem.display += timeString(fileInfo.ModTime())
|
|
||||||
}
|
|
||||||
|
|
||||||
displayItem.display += nameString(&displayItem)
|
|
||||||
|
|
||||||
if *args.links && fileInfo.Mode()&os.ModeSymlink != 0 {
|
|
||||||
displayItem.display += linkString(&displayItem, absPath)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if *args.sortTime {
|
|
||||||
sort.Sort(ByTime(dirs))
|
|
||||||
sort.Sort(ByTime(files))
|
|
||||||
if *args.backwards {
|
|
||||||
reverse(dirs)
|
|
||||||
reverse(files)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if *args.sortSize {
|
|
||||||
sort.Sort(BySize(files))
|
|
||||||
if *args.backwards {
|
|
||||||
reverse(files)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if *args.sortKind {
|
|
||||||
sort.Sort(ByKind(files))
|
|
||||||
if *args.backwards {
|
|
||||||
reverse(files)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// combine the items together again after sorting
|
|
||||||
allItems := append(dirs, files...)
|
|
||||||
|
|
||||||
// if using "long" display, just print one item per line
|
|
||||||
if *args.bytes || *args.mdate || *args.owner || *args.perms || *args.long {
|
|
||||||
for _, item := range allItems {
|
|
||||||
fmt.Fprintln(stdout, item.display)
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// but if not, try to format in columns, link `ls` would
|
|
||||||
strs := []string{}
|
|
||||||
for _, item := range allItems {
|
|
||||||
strs = append(strs, item.display)
|
|
||||||
}
|
|
||||||
textcol.PrintColumns(&strs, 2)
|
|
||||||
}
|
|
||||||
|
|
||||||
if *args.stats {
|
|
||||||
printStats(len(files), len(dirs))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func getLinkInfo(item *DisplayItem, absPath string) {
|
|
||||||
fullPath := path.Join(absPath, item.info.Name())
|
|
||||||
linkPath, err1 := os.Readlink(fullPath)
|
|
||||||
check(err1)
|
|
||||||
|
|
||||||
linkFullPath := linkPath
|
|
||||||
if linkPath[0] != '/' {
|
|
||||||
linkFullPath = path.Join(absPath, linkPath)
|
|
||||||
}
|
|
||||||
|
|
||||||
linkInfo, err2 := os.Stat(linkFullPath)
|
|
||||||
if *args.linkRel {
|
|
||||||
linkRel, _ := filepath.Rel(absPath, linkPath)
|
|
||||||
if linkRel != "" && len(linkRel) <= len(linkPath) {
|
|
||||||
// i prefer the look of these relative paths prepended with ./
|
|
||||||
if linkRel[0] != '.' {
|
|
||||||
linkPath = "./" + linkRel
|
|
||||||
} else {
|
|
||||||
linkPath = linkRel
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
link := LinkInfo{
|
|
||||||
path: linkPath,
|
|
||||||
}
|
|
||||||
item.link = &link
|
|
||||||
if linkInfo != nil {
|
|
||||||
link.info = linkInfo
|
|
||||||
} else if strings.Contains(err2.Error(), "no such file or directory") {
|
|
||||||
link.broken = true
|
|
||||||
} else if !strings.Contains(err2.Error(), "permission denied") {
|
|
||||||
check(err2)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func nameString(item *DisplayItem) string {
|
|
||||||
mode := item.info.Mode()
|
|
||||||
name := item.info.Name()
|
|
||||||
if mode&os.ModeDir != 0 {
|
|
||||||
return dirString(item)
|
|
||||||
} else if mode&os.ModeSymlink != 0 {
|
|
||||||
if !item.link.broken && item.link.info.IsDir() {
|
|
||||||
color := ConfigColor["link"]["nameDir"]
|
|
||||||
if *args.nerdfont {
|
|
||||||
var linkIcon string
|
|
||||||
if item.link.broken {
|
|
||||||
linkIcon = otherIcons["brokenLink"]
|
|
||||||
} else {
|
|
||||||
linkIcon = otherIcons["linkDir"]
|
|
||||||
}
|
|
||||||
return color + linkIcon + " " + name + " " + Reset
|
|
||||||
} else if *args.icons {
|
|
||||||
return color + "🔗 " + name + " " + Reset
|
|
||||||
} else {
|
|
||||||
return color + " " + name + " " + Reset
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
color := ConfigColor["link"]["name"]
|
|
||||||
if *args.nerdfont {
|
|
||||||
var linkIcon string
|
|
||||||
if item.link.broken {
|
|
||||||
linkIcon = otherIcons["brokenLink"]
|
|
||||||
} else {
|
|
||||||
linkIcon = otherIcons["link"]
|
|
||||||
}
|
|
||||||
return color + linkIcon + " " + name + " " + Reset
|
|
||||||
} else if *args.icons {
|
|
||||||
return color + "🔗 " + name + " " + Reset
|
|
||||||
} else {
|
|
||||||
return color + name + " " + Reset
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else if mode&os.ModeDevice != 0 {
|
|
||||||
color := ConfigColor["device"]["name"]
|
|
||||||
if *args.nerdfont {
|
|
||||||
return color + otherIcons["device"] + " " + name + " " + Reset
|
|
||||||
} else if *args.icons {
|
|
||||||
return color + "💽 " + name + " " + Reset
|
|
||||||
} else {
|
|
||||||
return color + " " + name + " " + Reset
|
|
||||||
}
|
|
||||||
} else if mode&os.ModeNamedPipe != 0 {
|
|
||||||
return ConfigColor["pipe"]["name"] + " " + name + " " + Reset
|
|
||||||
} else if mode&os.ModeSocket != 0 {
|
|
||||||
return ConfigColor["socket"]["name"] + " " + name + " " + Reset
|
|
||||||
}
|
|
||||||
return fileString(item)
|
|
||||||
}
|
|
||||||
|
|
||||||
func linkString(item *DisplayItem, absPath string) string {
|
|
||||||
colors := ConfigColor["link"]
|
|
||||||
displayStrings := []string{colors["arrow"] + "►"}
|
|
||||||
if item.link.info == nil && item.link.broken {
|
|
||||||
displayStrings = append(displayStrings, colors["broken"]+item.link.path+Reset)
|
|
||||||
} else if item.link.info != nil {
|
|
||||||
linkname, linkext := splitExt(item.link.path)
|
|
||||||
displayItem := DisplayItem{
|
|
||||||
info: item.link.info,
|
|
||||||
basename: linkname,
|
|
||||||
ext: linkext,
|
|
||||||
}
|
|
||||||
displayStrings = append(displayStrings, nameString(&displayItem))
|
|
||||||
} else {
|
|
||||||
displayStrings = append(displayStrings, item.link.path)
|
|
||||||
}
|
|
||||||
return strings.Join(displayStrings, " ")
|
|
||||||
}
|
|
||||||
|
|
||||||
func fileString(item *DisplayItem) string {
|
|
||||||
key := strings.ToLower(item.ext)
|
|
||||||
// figure out which color to choose
|
|
||||||
colors := FileColor["_default"]
|
|
||||||
alias, hasAlias := FileAliases[key]
|
|
||||||
if hasAlias {
|
|
||||||
key = alias
|
|
||||||
}
|
|
||||||
betterColor, hasBetterColor := FileColor[key]
|
|
||||||
if hasBetterColor {
|
|
||||||
colors = betterColor
|
|
||||||
}
|
|
||||||
|
|
||||||
ext := item.ext
|
|
||||||
if ext != "" {
|
|
||||||
ext = "." + ext
|
|
||||||
}
|
|
||||||
|
|
||||||
// in some cases files have icons if front
|
|
||||||
// if nerd font enabled, then it'll be a file-specific icon, or if its an executable script, a little shell icon
|
|
||||||
// if the regular --icons flag is used instead, then it will show a ">_" only if the file is executable
|
|
||||||
icon := ""
|
|
||||||
executable := isExecutableScript(item)
|
|
||||||
if *args.nerdfont {
|
|
||||||
if executable {
|
|
||||||
icon = colors[0] + getIconForFile("", "shell") + " "
|
|
||||||
} else {
|
|
||||||
icon = colors[0] + getIconForFile(item.basename, item.ext) + " "
|
|
||||||
}
|
|
||||||
} else if *args.icons {
|
|
||||||
if executable {
|
|
||||||
icon = BgGray(1) + FgRGB(0, 5, 0) + ">_" + Reset + " "
|
|
||||||
}
|
|
||||||
}
|
|
||||||
displayStrings := []string{icon, colors[0], item.basename, colors[1], ext, Reset}
|
|
||||||
return strings.Join(displayStrings, "")
|
|
||||||
}
|
|
||||||
|
|
||||||
// check for executable permissions
|
|
||||||
func isExecutableScript(item *DisplayItem) bool {
|
|
||||||
if item.info.Mode()&0111 != 0 && item.info.Mode().IsRegular() {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
func dirString(item *DisplayItem) string {
|
|
||||||
colors := ConfigColor["dir"]
|
|
||||||
if item.basename == "" {
|
|
||||||
colors = ConfigColor[".dir"]
|
|
||||||
}
|
|
||||||
displayStrings := []string{colors["name"]}
|
|
||||||
icon := ""
|
|
||||||
if *args.icons {
|
|
||||||
displayStrings = append(displayStrings, "📂 ")
|
|
||||||
} else if *args.nerdfont {
|
|
||||||
icon = getIconForFolder(item.info.Name()) + " "
|
|
||||||
displayStrings = append(displayStrings, icon)
|
|
||||||
} else {
|
|
||||||
displayStrings = append(displayStrings, " ")
|
|
||||||
}
|
|
||||||
ext := item.ext
|
|
||||||
if ext != "" {
|
|
||||||
ext = "." + ext
|
|
||||||
}
|
|
||||||
displayStrings = append(displayStrings, item.basename, colors["ext"], ext, " ", Reset)
|
|
||||||
return strings.Join(displayStrings, "")
|
|
||||||
}
|
|
||||||
|
|
||||||
func rwxString(mode os.FileMode, i uint, color string) string {
|
|
||||||
bits := mode >> (i * 3)
|
|
||||||
coloredStrings := []string{color}
|
|
||||||
if bits&4 != 0 {
|
|
||||||
coloredStrings = append(coloredStrings, "r")
|
|
||||||
} else {
|
|
||||||
coloredStrings = append(coloredStrings, "-")
|
|
||||||
}
|
|
||||||
if bits&2 != 0 {
|
|
||||||
coloredStrings = append(coloredStrings, "w")
|
|
||||||
} else {
|
|
||||||
coloredStrings = append(coloredStrings, "-")
|
|
||||||
}
|
|
||||||
if i == 0 && mode&os.ModeSticky != 0 {
|
|
||||||
if bits&1 != 0 {
|
|
||||||
coloredStrings = append(coloredStrings, "t")
|
|
||||||
} else {
|
|
||||||
coloredStrings = append(coloredStrings, "T")
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if bits&1 != 0 {
|
|
||||||
coloredStrings = append(coloredStrings, "x")
|
|
||||||
} else {
|
|
||||||
coloredStrings = append(coloredStrings, "-")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return strings.Join(coloredStrings, "")
|
|
||||||
}
|
|
||||||
|
|
||||||
// generates the permissions string, ya know like "drwxr-xr-x" and stuff like that
|
|
||||||
func permString(info os.FileInfo, ownerColor string, groupColor string) string {
|
|
||||||
defaultColor := PermsColor["other"]["_default"]
|
|
||||||
|
|
||||||
// info.Mode().String() does not produce the same output as `ls`, so we must build that string manually
|
|
||||||
mode := info.Mode()
|
|
||||||
// this "type" is not the file extension, but type as far as the OS is concerned
|
|
||||||
filetype := "-"
|
|
||||||
if mode&os.ModeDir != 0 {
|
|
||||||
filetype = "d"
|
|
||||||
} else if mode&os.ModeSymlink != 0 {
|
|
||||||
filetype = "l"
|
|
||||||
} else if mode&os.ModeDevice != 0 {
|
|
||||||
if mode&os.ModeCharDevice == 0 {
|
|
||||||
filetype = "b" // block device
|
|
||||||
} else {
|
|
||||||
filetype = "c" // character device
|
|
||||||
}
|
|
||||||
} else if mode&os.ModeNamedPipe != 0 {
|
|
||||||
filetype = "p"
|
|
||||||
} else if mode&os.ModeSocket != 0 {
|
|
||||||
filetype = "s"
|
|
||||||
}
|
|
||||||
coloredStrings := []string{defaultColor, filetype}
|
|
||||||
coloredStrings = append(coloredStrings, rwxString(mode, 2, ownerColor))
|
|
||||||
coloredStrings = append(coloredStrings, rwxString(mode, 1, groupColor))
|
|
||||||
coloredStrings = append(coloredStrings, rwxString(mode, 0, defaultColor), Reset, Reset)
|
|
||||||
return strings.Join(coloredStrings, " ")
|
|
||||||
}
|
|
||||||
|
|
||||||
func sizeString(size int64) string {
|
|
||||||
sizeFloat := float64(size)
|
|
||||||
for i, unit := range sizeUnits {
|
|
||||||
base := math.Pow(1024, float64(i))
|
|
||||||
if sizeFloat < base*1024 {
|
|
||||||
var sizeStr string
|
|
||||||
if i == 0 {
|
|
||||||
sizeStr = strconv.FormatInt(size, 10)
|
|
||||||
} else {
|
|
||||||
sizeStr = fmt.Sprintf("%.2f", sizeFloat/base)
|
|
||||||
}
|
|
||||||
return SizeColor[unit] + pad.Left(sizeStr, 6, " ") + unit + " " + Reset
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return strconv.Itoa(int(size))
|
|
||||||
}
|
|
||||||
|
|
||||||
func timeString(modtime time.Time) string {
|
|
||||||
dateStr := modtime.Format(dateFormat)
|
|
||||||
timeStr := modtime.Format(timeFormat)
|
|
||||||
hour, err := strconv.Atoi(timeStr[0:2])
|
|
||||||
check(err)
|
|
||||||
// generate a color based on the hour of the day. darkest around midnight and whitest around noon
|
|
||||||
timeColor := 14 - int(8*math.Cos(math.Pi*float64(hour)/12))
|
|
||||||
colored := []string{FgGray(22) + dateStr, FgGray(timeColor) + timeStr, Reset}
|
|
||||||
return strings.Join(colored, " ")
|
|
||||||
}
|
|
||||||
|
|
||||||
// when we list out any subdirectories, print those paths conspicuously above the contents
|
|
||||||
// this helps with visual separation
|
|
||||||
func printFolderHeader(pathStr string) {
|
|
||||||
colors := ConfigColor["folderHeader"]
|
|
||||||
headerString := colors["arrow"] + "►" + colors["main"] + " "
|
|
||||||
prettyPath := prettifyPath(pathStr)
|
|
||||||
|
|
||||||
if prettyPath == "/" {
|
|
||||||
headerString += "/"
|
|
||||||
} else {
|
|
||||||
folders := strings.Split(prettyPath, "/")
|
|
||||||
coloredFolders := make([]string, 0, len(folders))
|
|
||||||
for i, folder := range folders {
|
|
||||||
if i == len(folders)-1 { // different color for the last folder in the path
|
|
||||||
coloredFolders = append(coloredFolders, colors["lastFolder"]+folder)
|
|
||||||
} else {
|
|
||||||
coloredFolders = append(coloredFolders, colors["main"]+folder)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
headerString += strings.Join(coloredFolders, colors["slash"]+"/")
|
|
||||||
}
|
|
||||||
|
|
||||||
fmt.Fprintln(stdout, headerString+" "+Reset)
|
|
||||||
}
|
|
||||||
|
|
||||||
func printErrorHeader(err error, pathStr string) {
|
|
||||||
fmt.Fprintln(stdout, ConfigColor["folderHeader"]["error"]+"► "+pathStr+Reset)
|
|
||||||
fmt.Fprintln(stdout, err.Error())
|
|
||||||
}
|
|
||||||
|
|
||||||
func prettifyPath(pathStr string) string {
|
|
||||||
prettyPath, err := filepath.Abs(pathStr)
|
|
||||||
check(err)
|
|
||||||
pwd := os.Getenv("PWD")
|
|
||||||
home := os.Getenv("HOME")
|
|
||||||
|
|
||||||
if strings.HasPrefix(prettyPath, pwd) {
|
|
||||||
prettyPath = "." + prettyPath[len(pwd):]
|
|
||||||
} else if strings.HasPrefix(prettyPath, home) {
|
|
||||||
prettyPath = "~" + prettyPath[len(home):]
|
|
||||||
}
|
|
||||||
return prettyPath
|
|
||||||
}
|
|
||||||
|
|
||||||
func getOwnerAndGroupColors(owner string, group string) (string, string) {
|
|
||||||
if owner == os.Getenv("USER") {
|
|
||||||
owner = "_self"
|
|
||||||
}
|
|
||||||
ownerColor := PermsColor["user"][owner]
|
|
||||||
if ownerColor == "" {
|
|
||||||
ownerColor = PermsColor["user"]["_default"]
|
|
||||||
}
|
|
||||||
groupColor := PermsColor["group"][group]
|
|
||||||
if groupColor == "" {
|
|
||||||
groupColor = PermsColor["group"]["_default"]
|
|
||||||
}
|
|
||||||
return ownerColor, groupColor
|
|
||||||
}
|
|
||||||
|
|
||||||
func printStats(numFiles, numDirs int) {
|
|
||||||
colors := ConfigColor["stats"]
|
|
||||||
end := time.Now().UnixNano()
|
|
||||||
microSeconds := (end - start) / int64(time.Microsecond)
|
|
||||||
milliSeconds := float64(microSeconds) / 1000
|
|
||||||
statStrings := []string{
|
|
||||||
colors["text"],
|
|
||||||
colors["number"] + strconv.Itoa(numDirs),
|
|
||||||
colors["text"] + "dirs",
|
|
||||||
colors["number"] + strconv.Itoa(numFiles),
|
|
||||||
colors["text"] + "files",
|
|
||||||
colors["ms"] + fmt.Sprintf("%.2f", milliSeconds),
|
|
||||||
colors["text"] + "ms",
|
|
||||||
Reset,
|
|
||||||
}
|
|
||||||
fmt.Fprintln(stdout, strings.Join(statStrings, " "))
|
|
||||||
}
|
|
||||||
|
|
||||||
func splitExt(filename string) (basepath, ext string) {
|
|
||||||
basename := filepath.Base(filename)
|
|
||||||
if basename[0] == '.' {
|
|
||||||
ext = basename[1:]
|
|
||||||
basepath = filename[:len(filename)-len(ext)-1]
|
|
||||||
} else {
|
|
||||||
ext = filepath.Ext(filename)
|
|
||||||
basepath = filename[:len(filename)-len(ext)]
|
|
||||||
if ext != "" {
|
|
||||||
ext = ext[1:]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// Go doesn't provide a `Max` function for ints like it does for floats (wtf?)
|
|
||||||
func max(a int, b int) int {
|
|
||||||
if a > b {
|
|
||||||
return a
|
|
||||||
}
|
|
||||||
return b
|
|
||||||
}
|
|
||||||
|
|
||||||
func check(err error) {
|
|
||||||
if err != nil {
|
|
||||||
panic(err)
|
|
||||||
}
|
|
||||||
}
|
|
67
lsgo/sort.go
67
lsgo/sort.go
@ -1,67 +0,0 @@
|
|||||||
package lsgo
|
|
||||||
|
|
||||||
// BySize tells `sort.Sort` how to sort by file size
|
|
||||||
type BySize []*DisplayItem
|
|
||||||
|
|
||||||
func (s BySize) Less(i, j int) bool {
|
|
||||||
return s[i].info.Size() < s[j].info.Size()
|
|
||||||
}
|
|
||||||
func (s BySize) Len() int {
|
|
||||||
return len(s)
|
|
||||||
}
|
|
||||||
func (s BySize) Swap(i, j int) {
|
|
||||||
s[i], s[j] = s[j], s[i]
|
|
||||||
}
|
|
||||||
|
|
||||||
// ByTime tells `sort.Sort` how to sort by last modified time
|
|
||||||
type ByTime []*DisplayItem
|
|
||||||
|
|
||||||
func (s ByTime) Less(i, j int) bool {
|
|
||||||
return s[i].info.ModTime().Unix() < s[j].info.ModTime().Unix()
|
|
||||||
}
|
|
||||||
func (s ByTime) Len() int {
|
|
||||||
return len(s)
|
|
||||||
}
|
|
||||||
func (s ByTime) Swap(i, j int) {
|
|
||||||
s[i], s[j] = s[j], s[i]
|
|
||||||
}
|
|
||||||
|
|
||||||
// ByKind tells `sort.Sort` how to sort by file extension
|
|
||||||
type ByKind []*DisplayItem
|
|
||||||
|
|
||||||
func (s ByKind) Less(i, j int) bool {
|
|
||||||
var kindi, kindj string
|
|
||||||
if s[i].basename == "" {
|
|
||||||
kindi = "."
|
|
||||||
} else if s[i].ext == "" {
|
|
||||||
kindi = "0"
|
|
||||||
} else {
|
|
||||||
kindi = s[i].ext
|
|
||||||
}
|
|
||||||
if s[j].basename == "" {
|
|
||||||
kindj = "."
|
|
||||||
} else if s[j].ext == "" {
|
|
||||||
kindj = "0"
|
|
||||||
} else {
|
|
||||||
kindj = s[j].ext
|
|
||||||
}
|
|
||||||
if kindi == kindj {
|
|
||||||
if kindi == "." {
|
|
||||||
return s[i].ext < s[j].ext
|
|
||||||
}
|
|
||||||
return s[i].basename < s[j].basename
|
|
||||||
}
|
|
||||||
return kindi < kindj
|
|
||||||
}
|
|
||||||
func (s ByKind) Len() int {
|
|
||||||
return len(s)
|
|
||||||
}
|
|
||||||
func (s ByKind) Swap(i, j int) {
|
|
||||||
s[i], s[j] = s[j], s[i]
|
|
||||||
}
|
|
||||||
|
|
||||||
func reverse(s []*DisplayItem) {
|
|
||||||
for i, j := 0, len(s)-1; i < j; i, j = i+1, j-1 {
|
|
||||||
s[i], s[j] = s[j], s[i]
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,692 +0,0 @@
|
|||||||
package mmGit
|
|
||||||
|
|
||||||
import (
|
|
||||||
"GoSungrow/Only"
|
|
||||||
"bufio"
|
|
||||||
"context"
|
|
||||||
"errors"
|
|
||||||
"fmt"
|
|
||||||
"github.com/go-git/go-git/v5"
|
|
||||||
"github.com/go-git/go-git/v5/plumbing"
|
|
||||||
"github.com/go-git/go-git/v5/plumbing/object"
|
|
||||||
"github.com/go-git/go-git/v5/plumbing/transport/ssh"
|
|
||||||
"os"
|
|
||||||
"os/exec"
|
|
||||||
"os/signal"
|
|
||||||
"os/user"
|
|
||||||
"path/filepath"
|
|
||||||
"strings"
|
|
||||||
"syscall"
|
|
||||||
"time"
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
func (z *Git) Connect() error {
|
|
||||||
|
|
||||||
for range Only.Once {
|
|
||||||
if z.IsNotOk() {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
|
|
||||||
var ok bool
|
|
||||||
ok, z.Error = IsDirExists(z.RepoDir)
|
|
||||||
if z.Error != nil {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
if ok {
|
|
||||||
z.Error = z.Open()
|
|
||||||
break
|
|
||||||
}
|
|
||||||
|
|
||||||
z.Error = z.Clone()
|
|
||||||
if z.Error != nil {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return z.Error
|
|
||||||
}
|
|
||||||
|
|
||||||
func (z *Git) Open() error {
|
|
||||||
|
|
||||||
for range Only.Once {
|
|
||||||
if z.IsNotOk() {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
|
|
||||||
z.repo, z.Error = git.PlainOpen(z.RepoDir)
|
|
||||||
if z.Error != nil {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
|
|
||||||
z.worktree, z.Error = z.repo.Worktree()
|
|
||||||
if z.Error != nil {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
|
|
||||||
var ref *plumbing.Reference
|
|
||||||
ref, z.Error = z.repo.Head()
|
|
||||||
if z.Error != nil {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
|
|
||||||
if ref.Hash().IsZero() {
|
|
||||||
z.Error = errors.New("invalid HEAD reference")
|
|
||||||
break
|
|
||||||
}
|
|
||||||
|
|
||||||
fmt.Printf("Git opened\n\trepo: %s\n\tdir: %s\n", z.RepoUrl, z.RepoDir)
|
|
||||||
}
|
|
||||||
|
|
||||||
return z.Error
|
|
||||||
}
|
|
||||||
|
|
||||||
func (z *Git) Clone() error {
|
|
||||||
|
|
||||||
for range Only.Once {
|
|
||||||
if z.IsNotOk() {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
|
|
||||||
var ok bool
|
|
||||||
ok, z.Error = IsDirExists(z.RepoDir)
|
|
||||||
if z.Error != nil {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
if ok {
|
|
||||||
z.Error = errors.New(fmt.Sprintf("Cannot clone - directory '%s' already exists.", z.RepoDir))
|
|
||||||
break
|
|
||||||
}
|
|
||||||
|
|
||||||
// CONTEXT: Provide Ctrl-C capability as well as operation timeouts.
|
|
||||||
stop := make(chan os.Signal, 1)
|
|
||||||
signal.Notify(stop, os.Interrupt)
|
|
||||||
ctx, cancel := context.WithCancel(context.Background())
|
|
||||||
defer cancel()
|
|
||||||
go func() {
|
|
||||||
<-stop
|
|
||||||
fmt.Println("\nCanceling operation...")
|
|
||||||
cancel()
|
|
||||||
}()
|
|
||||||
// CONTEXT: Provide Ctrl-C capability as well as operation timeouts.
|
|
||||||
|
|
||||||
pk := z.GetSshAuth()
|
|
||||||
if z.Error != nil {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
|
|
||||||
options := &git.CloneOptions {
|
|
||||||
URL: z.RepoUrl,
|
|
||||||
Auth: pk,
|
|
||||||
RemoteName: "",
|
|
||||||
ReferenceName: "",
|
|
||||||
SingleBranch: false,
|
|
||||||
NoCheckout: false,
|
|
||||||
Depth: 0,
|
|
||||||
RecurseSubmodules: 0,
|
|
||||||
Progress: os.Stdout,
|
|
||||||
Tags: 0,
|
|
||||||
InsecureSkipTLS: false,
|
|
||||||
CABundle: nil,
|
|
||||||
}
|
|
||||||
z.repo, z.Error = git.PlainCloneContext(ctx, z.RepoDir, false, options)
|
|
||||||
if z.Error != nil {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
z.worktree, z.Error = z.repo.Worktree()
|
|
||||||
if z.Error != nil {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
|
|
||||||
var ref *plumbing.Reference
|
|
||||||
ref, z.Error = z.repo.Head()
|
|
||||||
if z.Error != nil {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
|
|
||||||
if ref.Hash().IsZero() {
|
|
||||||
z.Error = errors.New("invalid HEAD reference")
|
|
||||||
break
|
|
||||||
}
|
|
||||||
|
|
||||||
fmt.Printf("Git cloned\n\trepo: %s\n\tdir: %s\n", z.RepoUrl, z.RepoDir)
|
|
||||||
}
|
|
||||||
|
|
||||||
return z.Error
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetSshAuth: Gitlab keys need to be created with at least 3072 bits.
|
|
||||||
// ssh-keygen -t rsa -b 3072 -C 'root@everywhere' -f gitlab_rsa -N ''
|
|
||||||
func (z *Git) GetSshAuth() *ssh.PublicKeys {
|
|
||||||
var pk *ssh.PublicKeys
|
|
||||||
|
|
||||||
for range Only.Once {
|
|
||||||
if z.IsNotOk() {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
|
|
||||||
var u *user.User
|
|
||||||
u, z.Error = user.Current()
|
|
||||||
|
|
||||||
paths := []string {
|
|
||||||
z.KeyFile,
|
|
||||||
filepath.Join(u.HomeDir, ".ssh", "id_rsa"),
|
|
||||||
}
|
|
||||||
|
|
||||||
var path string
|
|
||||||
for _, path = range paths {
|
|
||||||
if path == "" {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
z.Error = checkKeyFile(path)
|
|
||||||
if z.Error != nil {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
break
|
|
||||||
}
|
|
||||||
|
|
||||||
// Try without password first.
|
|
||||||
var password string
|
|
||||||
pk, z.Error = ssh.NewPublicKeysFromFile("git", path, password)
|
|
||||||
if z.Error == nil {
|
|
||||||
fmt.Printf("AUTH: %v\n", pk)
|
|
||||||
break
|
|
||||||
}
|
|
||||||
|
|
||||||
// Then with password.
|
|
||||||
password = getPassword("ApiPassword: ")
|
|
||||||
pk, z.Error = ssh.NewPublicKeysFromFile("git", path, password)
|
|
||||||
if z.Error == nil {
|
|
||||||
fmt.Printf("AUTH: %v\n", pk)
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return pk
|
|
||||||
}
|
|
||||||
|
|
||||||
func checkKeyFile(path string) error {
|
|
||||||
var err error
|
|
||||||
|
|
||||||
for range Only.Once {
|
|
||||||
if path == "" {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
var fi os.FileInfo
|
|
||||||
fi, err = os.Stat(path)
|
|
||||||
if os.IsNotExist(err) {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
if fi.IsDir() {
|
|
||||||
err = errors.New("SSH publickey file is a directory")
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
// techEcho() - turns terminal echo on or off.
|
|
||||||
func termEcho(on bool) {
|
|
||||||
// Common settings and variables for both stty calls.
|
|
||||||
attrs := syscall.ProcAttr{
|
|
||||||
Dir: "",
|
|
||||||
Env: []string{},
|
|
||||||
Files: []uintptr{os.Stdin.Fd(), os.Stdout.Fd(), os.Stderr.Fd()},
|
|
||||||
Sys: nil}
|
|
||||||
var ws syscall.WaitStatus
|
|
||||||
cmd := "echo"
|
|
||||||
if on == false {
|
|
||||||
cmd = "-echo"
|
|
||||||
}
|
|
||||||
|
|
||||||
// Enable/disable echoing.
|
|
||||||
pid, err := syscall.ForkExec(
|
|
||||||
"/bin/stty",
|
|
||||||
[]string{"stty", cmd},
|
|
||||||
&attrs)
|
|
||||||
if err != nil {
|
|
||||||
panic(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Wait for the stty process to complete.
|
|
||||||
_, err = syscall.Wait4(pid, &ws, 0, nil)
|
|
||||||
if err != nil {
|
|
||||||
panic(err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// getPassword - Prompt for password.
|
|
||||||
func getPassword(prompt string) string {
|
|
||||||
fmt.Print(prompt)
|
|
||||||
|
|
||||||
// Catch a ^C interrupt.
|
|
||||||
// Make sure that we reset term echo before exiting.
|
|
||||||
signalChannel := make(chan os.Signal, 1)
|
|
||||||
signal.Notify(signalChannel, os.Interrupt)
|
|
||||||
go func() {
|
|
||||||
for _ = range signalChannel {
|
|
||||||
fmt.Println("\n^C interrupt.")
|
|
||||||
termEcho(true)
|
|
||||||
os.Exit(1)
|
|
||||||
}
|
|
||||||
}()
|
|
||||||
|
|
||||||
// Echo is disabled, now grab the data.
|
|
||||||
termEcho(false) // disable terminal echo
|
|
||||||
reader := bufio.NewReader(os.Stdin)
|
|
||||||
text, err := reader.ReadString('\n')
|
|
||||||
termEcho(true) // always re-enable terminal echo
|
|
||||||
fmt.Println("")
|
|
||||||
if err != nil {
|
|
||||||
// The terminal has been reset, go ahead and exit.
|
|
||||||
fmt.Println("ERROR:", err.Error())
|
|
||||||
os.Exit(1)
|
|
||||||
}
|
|
||||||
return strings.TrimSpace(text)
|
|
||||||
}
|
|
||||||
|
|
||||||
//func (z *Git) setContext() error {
|
|
||||||
//
|
|
||||||
// for range Only.Once {
|
|
||||||
// if z.IsNotOk() {
|
|
||||||
// break
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// stop := make(chan os.Signal, 1)
|
|
||||||
// signal.Notify(stop, os.Interrupt)
|
|
||||||
// ctx, cancel := context.WithCancel(context.Background())
|
|
||||||
// defer cancel() // cancel when we are finished consuming integers
|
|
||||||
//
|
|
||||||
// go func() {
|
|
||||||
// <-stop
|
|
||||||
// Warning("\nSignal detected, canceling operation...")
|
|
||||||
// cancel()
|
|
||||||
// }()
|
|
||||||
//
|
|
||||||
// var auth ssh.AuthMethod
|
|
||||||
// auth, z.Error = ssh.DefaultAuthBuilder("admin-mickh")
|
|
||||||
// if z.Error != nil {
|
|
||||||
// break
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// z.repo, z.Error = git.PlainClone(z.RepoDir, false, &git.CloneOptions {
|
|
||||||
// URL: z.RepoUrl,
|
|
||||||
// Auth: auth,
|
|
||||||
// })
|
|
||||||
// if z.Error != nil {
|
|
||||||
// break
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// var ref *plumbing.Reference
|
|
||||||
// ref, z.Error = z.repo.Head()
|
|
||||||
// if z.Error != nil {
|
|
||||||
// break
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// var commit *object.Commit
|
|
||||||
// commit, z.Error = z.repo.CommitObject(ref.Hash())
|
|
||||||
// if z.Error != nil {
|
|
||||||
// break
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// fmt.Println(commit)
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// return z.Error
|
|
||||||
//}
|
|
||||||
|
|
||||||
func (z *Git) SaveFile(fn string, data []byte) error {
|
|
||||||
|
|
||||||
for range Only.Once {
|
|
||||||
if z.IsNotOk() {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
|
|
||||||
//z.worktree, z.Error = z.repo.Worktree()
|
|
||||||
//if z.Error != nil {
|
|
||||||
// break
|
|
||||||
//}
|
|
||||||
//
|
|
||||||
//var fh fs.File
|
|
||||||
//var fi os.FileInfo
|
|
||||||
//fi, z.Error = z.fs.Stat(fn)
|
|
||||||
//if errors.Is(z.Error, os.ErrNotExist) {
|
|
||||||
// // Create new file
|
|
||||||
// fh, z.Error = z.fs.Create(fn)
|
|
||||||
//} else {
|
|
||||||
// // Open file
|
|
||||||
// fh, z.Error = z.fs.OpenFile(fn, os.O_RDWR|os.O_CREATE, 0664)
|
|
||||||
//}
|
|
||||||
|
|
||||||
fh, err := os.OpenFile(filepath.Join(z.RepoDir, fn), os.O_RDWR|os.O_CREATE, 0664)
|
|
||||||
if err != nil {
|
|
||||||
z.Error = err
|
|
||||||
break
|
|
||||||
}
|
|
||||||
defer fh.Close()
|
|
||||||
|
|
||||||
fmt.Printf("Saved file '%s'\n", fn)
|
|
||||||
_, z.Error = fh.Write(data)
|
|
||||||
if z.Error != nil {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
|
|
||||||
// Run git status before adding the file to the worktree
|
|
||||||
//fmt.Println(z.worktree.Status())
|
|
||||||
|
|
||||||
// git add $filePath
|
|
||||||
_, z.Error = z.worktree.Add(fn)
|
|
||||||
if z.Error != nil {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
|
|
||||||
//// Run git status after the file has been added adding to the worktree
|
|
||||||
//fmt.Println(z.worktree.Status())
|
|
||||||
//
|
|
||||||
//// git commit -m $message
|
|
||||||
//msg := fmt.Sprintf("Updated file '%s'", fn)
|
|
||||||
//_, z.Error = z.worktree.Commit(msg, &git.CommitOptions{})
|
|
||||||
//if z.Error != nil {
|
|
||||||
// break
|
|
||||||
//}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
return z.Error
|
|
||||||
}
|
|
||||||
|
|
||||||
func (z *Git) Status() error {
|
|
||||||
|
|
||||||
for range Only.Once {
|
|
||||||
if z.IsNotOk() {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
|
|
||||||
var status git.Status
|
|
||||||
status, z.Error = z.worktree.Status()
|
|
||||||
if z.Error != nil {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
|
|
||||||
if status.String() != "" {
|
|
||||||
fmt.Printf("Status of Git\n\trepo: %s\n\tdir: %s\n%s\n",
|
|
||||||
z.RepoUrl,
|
|
||||||
z.RepoDir,
|
|
||||||
status.String(),
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return z.Error
|
|
||||||
}
|
|
||||||
|
|
||||||
func (z *Git) Add(path string) error {
|
|
||||||
|
|
||||||
for range Only.Once {
|
|
||||||
if z.IsNotOk() {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
|
|
||||||
if path == "" {
|
|
||||||
path = "."
|
|
||||||
}
|
|
||||||
|
|
||||||
fmt.Printf("Adding to Git\n\trepo: %s\n\tdir: %s\n", z.RepoUrl, z.RepoDir)
|
|
||||||
|
|
||||||
_, z.Error = z.worktree.Add(path)
|
|
||||||
if z.Error != nil {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
|
|
||||||
z.Error = z.Status()
|
|
||||||
if z.Error != nil {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//PrintError(z.Error)
|
|
||||||
return z.Error
|
|
||||||
}
|
|
||||||
|
|
||||||
func (z *Git) Commit(msg string, args ...interface{}) error {
|
|
||||||
|
|
||||||
for range Only.Once {
|
|
||||||
if z.IsNotOk() {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
|
|
||||||
z.Error = z.Add(".")
|
|
||||||
if z.Error != nil {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
|
|
||||||
cn := &object.Signature {
|
|
||||||
Name: os.Getenv("USERNAME"),
|
|
||||||
Email: "",
|
|
||||||
When: time.Now(),
|
|
||||||
}
|
|
||||||
|
|
||||||
fmt.Printf("Committing Git\n\trepo: %s\n\tdir: %s\n", z.RepoUrl, z.RepoDir)
|
|
||||||
// Similar to git commit -m $message
|
|
||||||
var ph plumbing.Hash
|
|
||||||
msg := fmt.Sprintf(msg, args...)
|
|
||||||
ph, z.Error = z.worktree.Commit(msg, &git.CommitOptions{
|
|
||||||
All: false,
|
|
||||||
Author: cn,
|
|
||||||
Committer: cn,
|
|
||||||
Parents: nil,
|
|
||||||
SignKey: nil,
|
|
||||||
})
|
|
||||||
if z.Error != nil {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
|
|
||||||
// Similar to git show -s
|
|
||||||
var obj *object.Commit
|
|
||||||
obj, z.Error = z.repo.CommitObject(ph)
|
|
||||||
if z.Error != nil {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
|
|
||||||
if obj.String() != "" {
|
|
||||||
fmt.Printf("Status of Git\n\trepo: %s\n\tdir: %s\n%s\n",
|
|
||||||
z.RepoUrl,
|
|
||||||
z.RepoDir,
|
|
||||||
obj.String(),
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//PrintError(z.Error)
|
|
||||||
return z.Error
|
|
||||||
}
|
|
||||||
|
|
||||||
func (z *Git) Pull() error {
|
|
||||||
|
|
||||||
for range Only.Once {
|
|
||||||
if z.IsNotOk() {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
|
|
||||||
pk := z.GetSshAuth()
|
|
||||||
if z.Error != nil {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
|
|
||||||
fmt.Printf("Pulling Git\n\trepo: %s\n\tdir: %s\n", z.RepoUrl, z.RepoDir)
|
|
||||||
z.Error = z.worktree.Pull(&git.PullOptions {
|
|
||||||
RemoteName: "",
|
|
||||||
ReferenceName: "",
|
|
||||||
SingleBranch: false,
|
|
||||||
Depth: 0,
|
|
||||||
Auth: pk,
|
|
||||||
RecurseSubmodules: 0,
|
|
||||||
Progress: os.Stdout,
|
|
||||||
Force: false,
|
|
||||||
InsecureSkipTLS: false,
|
|
||||||
CABundle: nil,
|
|
||||||
})
|
|
||||||
if z.Error.Error() == "already up-to-date" {
|
|
||||||
z.Error = nil
|
|
||||||
break
|
|
||||||
}
|
|
||||||
if z.Error != nil {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//PrintError(z.Error)
|
|
||||||
return z.Error
|
|
||||||
}
|
|
||||||
|
|
||||||
func (z *Git) Push() error {
|
|
||||||
|
|
||||||
for range Only.Once {
|
|
||||||
if z.IsNotOk() {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
|
|
||||||
z.Error = z.Commit("Updated")
|
|
||||||
if z.Error != nil {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
|
|
||||||
pk := z.GetSshAuth()
|
|
||||||
if z.Error != nil {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
|
|
||||||
fmt.Printf("Pushing Git\n\trepo: %s\n\tdir: %s\n", z.RepoUrl, z.RepoDir)
|
|
||||||
z.Error = z.repo.Push(&git.PushOptions{
|
|
||||||
RemoteName: "",
|
|
||||||
RefSpecs: nil,
|
|
||||||
Auth: pk,
|
|
||||||
Progress: os.Stdout,
|
|
||||||
Prune: false,
|
|
||||||
Force: false,
|
|
||||||
InsecureSkipTLS: false,
|
|
||||||
CABundle: nil,
|
|
||||||
RequireRemoteRefs: nil,
|
|
||||||
})
|
|
||||||
if z.Error != nil {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//PrintError(z.Error)
|
|
||||||
return z.Error
|
|
||||||
}
|
|
||||||
|
|
||||||
func (z *Git) Diff(path string) error {
|
|
||||||
|
|
||||||
for range Only.Once {
|
|
||||||
var c []CommitDiffs
|
|
||||||
|
|
||||||
c, z.Error = z.GetDiffs(path)
|
|
||||||
if z.Error != nil {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
|
|
||||||
if len(c) < 2 {
|
|
||||||
fmt.Printf("Not enough revisions to compare.\n")
|
|
||||||
break
|
|
||||||
}
|
|
||||||
|
|
||||||
f1 := fmt.Sprintf("%s-%s", path, c[0].Hash)
|
|
||||||
f1, z.Error = WriteTempFile(f1, c[0].Contents)
|
|
||||||
if z.Error != nil {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
|
|
||||||
f2 := fmt.Sprintf("%s-%s", path, c[1].Hash)
|
|
||||||
f2, z.Error = WriteTempFile(f2, c[1].Contents)
|
|
||||||
if z.Error != nil {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
|
|
||||||
if z.DiffCmd == "" {
|
|
||||||
z.DiffCmd = "tkdiff"
|
|
||||||
}
|
|
||||||
z.DiffCmd, z.Error = exec.LookPath(z.DiffCmd)
|
|
||||||
|
|
||||||
cmd := exec.Command(z.DiffCmd, f1, f2)
|
|
||||||
|
|
||||||
var out []byte
|
|
||||||
out, z.Error = cmd.Output()
|
|
||||||
//if z.Error != nil {
|
|
||||||
// break
|
|
||||||
//}
|
|
||||||
|
|
||||||
fmt.Printf("# %s\n", cmd.String())
|
|
||||||
|
|
||||||
fmt.Println(string(out))
|
|
||||||
if z.Error != nil {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//PrintError(z.Error)
|
|
||||||
return z.Error
|
|
||||||
}
|
|
||||||
|
|
||||||
type CommitDiffs struct {
|
|
||||||
Hash string
|
|
||||||
Contents string
|
|
||||||
}
|
|
||||||
|
|
||||||
func (z *Git) GetDiffs(path string) ([]CommitDiffs, error) {
|
|
||||||
var ret []CommitDiffs
|
|
||||||
|
|
||||||
for range Only.Once {
|
|
||||||
if z.IsNotOk() {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
|
|
||||||
fmt.Printf("Diff Git\n\trepo: %s\n\tdir: %s\n", z.RepoUrl, z.RepoDir)
|
|
||||||
ref, _ := z.repo.Head()
|
|
||||||
//fmt.Printf("ref '%s'\n", ref.String())
|
|
||||||
|
|
||||||
commit, _ := z.repo.CommitObject(ref.Hash())
|
|
||||||
//fmt.Printf("commit '%s'\n", commit.String())
|
|
||||||
|
|
||||||
var comm []*object.Commit
|
|
||||||
commitIter, _ := z.repo.Log(&git.LogOptions{From: commit.Hash})
|
|
||||||
|
|
||||||
_ = commitIter.ForEach(func(c *object.Commit) error {
|
|
||||||
comm = append(comm, c)
|
|
||||||
return nil
|
|
||||||
})
|
|
||||||
|
|
||||||
var lastHash string
|
|
||||||
//for k := 0; k < len(comm)-1; k++ {
|
|
||||||
for k, _ := range comm {
|
|
||||||
fmt.Printf("# Commit number[%d]: %s", k, comm[k].Hash)
|
|
||||||
f2, _ := comm[k].File(path)
|
|
||||||
if f2 == nil {
|
|
||||||
fmt.Println(" - no path")
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
fc, _ := f2.Contents()
|
|
||||||
hs := GetHash(fc)
|
|
||||||
if hs == lastHash {
|
|
||||||
fmt.Println(" - no change")
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
lastHash = hs
|
|
||||||
|
|
||||||
ret = append(ret, CommitDiffs{
|
|
||||||
Hash: comm[k].Hash.String(),
|
|
||||||
Contents: fc,
|
|
||||||
})
|
|
||||||
fmt.Println(" - changed")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return ret, z.Error
|
|
||||||
}
|
|
@ -1,137 +0,0 @@
|
|||||||
package mmGit
|
|
||||||
|
|
||||||
import (
|
|
||||||
"GoSungrow/Only"
|
|
||||||
"fmt"
|
|
||||||
memfs "github.com/go-git/go-billy/v5/memfs"
|
|
||||||
git "github.com/go-git/go-git/v5"
|
|
||||||
"github.com/go-git/go-git/v5/plumbing/transport/ssh"
|
|
||||||
memory "github.com/go-git/go-git/v5/storage/memory"
|
|
||||||
"os"
|
|
||||||
//"net/http"
|
|
||||||
)
|
|
||||||
|
|
||||||
func (z *Git) MemConnect() error {
|
|
||||||
|
|
||||||
for range Only.Once {
|
|
||||||
if z.IsNotOk() {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
|
|
||||||
//auth := &http.BasicAuth {
|
|
||||||
// ApiUsername: z.ApiUsername,
|
|
||||||
// ApiPassword: z.ApiPassword,
|
|
||||||
//}
|
|
||||||
|
|
||||||
var auth ssh.AuthMethod
|
|
||||||
auth, z.Error = ssh.DefaultAuthBuilder("admin-mickh")
|
|
||||||
if z.Error != nil {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
|
|
||||||
//if z.Error = r.Push(&git.PushOptions{Auth: sshAuth}); err != nil {
|
|
||||||
// log.Error().Err(err).Msg("Push err")
|
|
||||||
// os.Exit(1)
|
|
||||||
//}
|
|
||||||
//if z.Error = r.Push(&git.PushOptions{Auth: sshAuth}); err != nil {
|
|
||||||
// log.Error().Err(err).Msg("Push err")
|
|
||||||
// os.Exit(1)
|
|
||||||
//}
|
|
||||||
|
|
||||||
//s := fmt.Sprintf("%s/.ssh/id_rsa", os.Getenv("HOME"))
|
|
||||||
//sshKey, err = ioutil.FileRead(s)
|
|
||||||
//signer, err := ssh.ParsePrivateKey([]byte(sshKey))
|
|
||||||
//auth = &gitssh.PublicKeys{User: "git", Signer: signer}
|
|
||||||
|
|
||||||
z.storer = memory.NewStorage()
|
|
||||||
z.fs = memfs.New()
|
|
||||||
|
|
||||||
z.repo, z.Error = git.Clone(z.storer, z.fs, &git.CloneOptions{
|
|
||||||
URL: z.RepoUrl,
|
|
||||||
Auth: auth,
|
|
||||||
})
|
|
||||||
if z.Error != nil {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return z.Error
|
|
||||||
}
|
|
||||||
|
|
||||||
func (z *Git) MemSaveFile(fn string, data []byte) error {
|
|
||||||
|
|
||||||
for range Only.Once {
|
|
||||||
if z.IsNotOk() {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
|
|
||||||
z.worktree, z.Error = z.repo.Worktree()
|
|
||||||
if z.Error != nil {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
|
|
||||||
//var fh fs.File
|
|
||||||
//var fi os.FileInfo
|
|
||||||
//fi, z.Error = z.fs.Stat(fn)
|
|
||||||
//if errors.Is(z.Error, os.ErrNotExist) {
|
|
||||||
// // Create new file
|
|
||||||
// fh, z.Error = z.fs.Create(fn)
|
|
||||||
//} else {
|
|
||||||
// // Open file
|
|
||||||
// fh, z.Error = z.fs.OpenFile(fn, os.O_RDWR|os.O_CREATE, 0664)
|
|
||||||
//}
|
|
||||||
|
|
||||||
fh, err := z.fs.OpenFile(fn, os.O_RDWR|os.O_CREATE, 0664)
|
|
||||||
if err != nil {
|
|
||||||
z.Error = err
|
|
||||||
break
|
|
||||||
}
|
|
||||||
defer fh.Close()
|
|
||||||
|
|
||||||
_, z.Error = fh.Write(data)
|
|
||||||
if z.Error != nil {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
|
|
||||||
// Run git status before adding the file to the worktree
|
|
||||||
fmt.Println(z.worktree.Status())
|
|
||||||
|
|
||||||
// git add $filePath
|
|
||||||
_, z.Error = z.worktree.Add(fn)
|
|
||||||
if z.Error != nil {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
|
|
||||||
// Run git status after the file has been added adding to the worktree
|
|
||||||
fmt.Println(z.worktree.Status())
|
|
||||||
|
|
||||||
// git commit -m $message
|
|
||||||
msg := fmt.Sprintf("Updated file '%s'", fn)
|
|
||||||
_, z.Error = z.worktree.Commit(msg, &git.CommitOptions{})
|
|
||||||
if z.Error != nil {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
return z.Error
|
|
||||||
}
|
|
||||||
|
|
||||||
func (z *Git) MemCommit(msg string, args ...interface{}) error {
|
|
||||||
|
|
||||||
for range Only.Once {
|
|
||||||
if z.IsNotOk() {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
|
|
||||||
// Similar to git commit -m $message
|
|
||||||
msg := fmt.Sprintf(msg, args...)
|
|
||||||
_, z.Error = z.worktree.Commit(msg, &git.CommitOptions{})
|
|
||||||
if z.Error != nil {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
return z.Error
|
|
||||||
}
|
|
159
mmGit/struct.go
159
mmGit/struct.go
@ -1,159 +0,0 @@
|
|||||||
package mmGit
|
|
||||||
|
|
||||||
import (
|
|
||||||
"GoSungrow/Only"
|
|
||||||
"errors"
|
|
||||||
"github.com/go-git/go-billy/v5"
|
|
||||||
"github.com/go-git/go-git/v5"
|
|
||||||
"github.com/go-git/go-git/v5/storage/memory"
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
type Git struct {
|
|
||||||
Username string
|
|
||||||
Password string
|
|
||||||
KeyFile string
|
|
||||||
Token string
|
|
||||||
RepoUrl string
|
|
||||||
RepoDir string
|
|
||||||
DiffCmd string
|
|
||||||
|
|
||||||
repo *git.Repository
|
|
||||||
|
|
||||||
modeMemory bool
|
|
||||||
worktree *git.Worktree
|
|
||||||
storer *memory.Storage
|
|
||||||
fs billy.Filesystem
|
|
||||||
|
|
||||||
Error error
|
|
||||||
}
|
|
||||||
|
|
||||||
func New() *Git {
|
|
||||||
var ret Git
|
|
||||||
|
|
||||||
for range Only.Once {
|
|
||||||
}
|
|
||||||
|
|
||||||
return &ret
|
|
||||||
}
|
|
||||||
|
|
||||||
func (z *Git) SetAuth(username string, password string) error {
|
|
||||||
|
|
||||||
for range Only.Once {
|
|
||||||
if username == "" {
|
|
||||||
z.Error = errors.New("username empty")
|
|
||||||
break
|
|
||||||
}
|
|
||||||
z.Username = username
|
|
||||||
|
|
||||||
if password == "" {
|
|
||||||
z.Error = errors.New("password empty")
|
|
||||||
break
|
|
||||||
}
|
|
||||||
z.Password = password
|
|
||||||
}
|
|
||||||
|
|
||||||
return z.Error
|
|
||||||
}
|
|
||||||
|
|
||||||
func (z *Git) SetKeyFile(path string) error {
|
|
||||||
|
|
||||||
for range Only.Once {
|
|
||||||
if path == "" {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
|
|
||||||
z.Error = checkKeyFile(path)
|
|
||||||
if z.Error != nil {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
|
|
||||||
z.KeyFile = path
|
|
||||||
}
|
|
||||||
|
|
||||||
return z.Error
|
|
||||||
}
|
|
||||||
|
|
||||||
func (z *Git) SetToken(t string) error {
|
|
||||||
|
|
||||||
for range Only.Once {
|
|
||||||
if t == "" {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
|
|
||||||
z.Token = t
|
|
||||||
}
|
|
||||||
|
|
||||||
return z.Error
|
|
||||||
}
|
|
||||||
|
|
||||||
func (z *Git) SetRepo(repo string) error {
|
|
||||||
|
|
||||||
for range Only.Once {
|
|
||||||
if repo == "" {
|
|
||||||
z.Error = errors.New("repo empty")
|
|
||||||
break
|
|
||||||
}
|
|
||||||
z.RepoUrl = repo
|
|
||||||
}
|
|
||||||
|
|
||||||
return z.Error
|
|
||||||
}
|
|
||||||
|
|
||||||
func (z *Git) SetDir(dir string) error {
|
|
||||||
|
|
||||||
for range Only.Once {
|
|
||||||
if dir == "" {
|
|
||||||
z.Error = errors.New("dir empty")
|
|
||||||
break
|
|
||||||
}
|
|
||||||
z.RepoDir = dir
|
|
||||||
}
|
|
||||||
|
|
||||||
return z.Error
|
|
||||||
}
|
|
||||||
|
|
||||||
func (z *Git) SetDiffCmd(cmd string) error {
|
|
||||||
|
|
||||||
for range Only.Once {
|
|
||||||
if cmd == "" {
|
|
||||||
cmd = "tkdiff"
|
|
||||||
}
|
|
||||||
z.DiffCmd = cmd
|
|
||||||
}
|
|
||||||
|
|
||||||
return z.Error
|
|
||||||
}
|
|
||||||
|
|
||||||
func (z *Git) IsOk() bool {
|
|
||||||
var ok bool
|
|
||||||
|
|
||||||
for range Only.Once {
|
|
||||||
//if z.ApiUsername == "" {
|
|
||||||
// z.Error = errors.New("username empty")
|
|
||||||
// break
|
|
||||||
//}
|
|
||||||
//
|
|
||||||
//if z.ApiPassword == "" {
|
|
||||||
// z.Error = errors.New("password empty")
|
|
||||||
// break
|
|
||||||
//}
|
|
||||||
|
|
||||||
if z.RepoUrl == "" {
|
|
||||||
z.Error = errors.New("repo empty")
|
|
||||||
break
|
|
||||||
}
|
|
||||||
|
|
||||||
if z.RepoDir == "" {
|
|
||||||
z.Error = errors.New("repo dir empty")
|
|
||||||
break
|
|
||||||
}
|
|
||||||
|
|
||||||
ok = true
|
|
||||||
}
|
|
||||||
|
|
||||||
return ok
|
|
||||||
}
|
|
||||||
func (z *Git) IsNotOk() bool {
|
|
||||||
return !z.IsOk()
|
|
||||||
}
|
|
@ -1,87 +0,0 @@
|
|||||||
package mmGit
|
|
||||||
|
|
||||||
import (
|
|
||||||
"GoSungrow/Only"
|
|
||||||
"crypto/md5"
|
|
||||||
"encoding/hex"
|
|
||||||
"errors"
|
|
||||||
"fmt"
|
|
||||||
"os"
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
func IsDirExists(path string) (bool, error) {
|
|
||||||
var ok bool
|
|
||||||
var err error
|
|
||||||
|
|
||||||
for range Only.Once {
|
|
||||||
if path == "" {
|
|
||||||
err = errors.New("empty git dir path")
|
|
||||||
break
|
|
||||||
}
|
|
||||||
|
|
||||||
var fi os.FileInfo
|
|
||||||
fi, err = os.Stat(path)
|
|
||||||
if os.IsNotExist(err) {
|
|
||||||
err = nil
|
|
||||||
break
|
|
||||||
}
|
|
||||||
|
|
||||||
if !fi.IsDir() {
|
|
||||||
err = errors.New("git path is not a dir")
|
|
||||||
break
|
|
||||||
}
|
|
||||||
|
|
||||||
ok = true
|
|
||||||
}
|
|
||||||
|
|
||||||
return ok, err
|
|
||||||
}
|
|
||||||
|
|
||||||
func PrintError(err error) {
|
|
||||||
if err == nil {
|
|
||||||
fmt.Println("OK")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
fmt.Printf("\nERROR: %s\n", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
func GetHash(data string) string {
|
|
||||||
var ret string
|
|
||||||
|
|
||||||
for range Only.Once {
|
|
||||||
h := md5.New()
|
|
||||||
h.Write([]byte(data))
|
|
||||||
ret = hex.EncodeToString(h.Sum(nil))
|
|
||||||
}
|
|
||||||
|
|
||||||
return ret
|
|
||||||
}
|
|
||||||
|
|
||||||
func WriteTempFile(path string, data string) (string, error) {
|
|
||||||
var fn string
|
|
||||||
var err error
|
|
||||||
|
|
||||||
for range Only.Once {
|
|
||||||
fn = fmt.Sprintf("%s/%s", os.TempDir(), path)
|
|
||||||
fmt.Printf("Writing file %s ...", fn)
|
|
||||||
var fh *os.File
|
|
||||||
fh, err = os.OpenFile(fn, os.O_RDWR|os.O_CREATE, 0664)
|
|
||||||
if err != nil {
|
|
||||||
fmt.Printf("%s\n", err)
|
|
||||||
break
|
|
||||||
}
|
|
||||||
defer fh.Close()
|
|
||||||
|
|
||||||
_, err = fh.Write([]byte(data))
|
|
||||||
if err != nil {
|
|
||||||
fmt.Printf("%s\n", err)
|
|
||||||
break
|
|
||||||
}
|
|
||||||
fmt.Println("OK")
|
|
||||||
|
|
||||||
//fmt.Printf("%v\n", data)
|
|
||||||
}
|
|
||||||
|
|
||||||
return fn, err
|
|
||||||
}
|
|
Loading…
x
Reference in New Issue
Block a user