diff --git a/.idea/workspace.xml b/.idea/workspace.xml index 43317cbbb..616d1c19d 100644 --- a/.idea/workspace.xml +++ b/.idea/workspace.xml @@ -5,1085 +5,35 @@ - - - - - - - - - - - - - - - - - - - - - - + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + - - + + + + + + + + + + + + + + + + + - { - "keyToString": { - "DefaultGoTemplateProperty": "Go File", - "RunOnceActivity.go.format.on.save.advertiser.fired": "true", - "RunOnceActivity.go.formatter.settings.were.checked": "true", - "RunOnceActivity.go.migrated.go.modules.settings": "true", - "RunOnceActivity.go.modules.go.list.on.any.changes.was.set": "true", - "RunOnceActivity.go.watchers.conflict.with.on.save.actions.check.performed": "true", - "WebServerToolWindowFactoryState": "false", - "go.import.settings.migrated": "true", - "last_opened_file_path": "/Users/mick", - "node.js.detected.package.eslint": "true", - "node.js.selected.package.eslint": "(autodetect)", - "settings.editor.selected.configurable": "actions.on.save" + +}]]> diff --git a/EXAMPLES.md b/EXAMPLES.md index e69de29bb..61e86ec41 100644 --- a/EXAMPLES.md +++ b/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 +GoSungrow api raw +GoSungrow api save +GoSungrow api put + +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 diff --git a/config.json b/config.json index 8cf2f654f..a7ea9f522 100644 --- a/config.json +++ b/config.json @@ -1,6 +1,6 @@ { "appkey": "93D72E60331ABDCDC7B39ADC2D1F32B3", - "config": "/Users/mick/.GoSungrow/config.json", + "config": "", "debug": false, "host": "https://augateway.isolarcloud.com", "password": "", @@ -8,4 +8,4 @@ "timeout": "30s", "token-expiry": "", "user": "" -} \ No newline at end of file +} diff --git a/defaults/EXAMPLES.md b/defaults/EXAMPLES.md index e69de29bb..61e86ec41 100644 --- a/defaults/EXAMPLES.md +++ b/defaults/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 +GoSungrow api raw +GoSungrow api save +GoSungrow api put + +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 diff --git a/defaults/const.go b/defaults/const.go index 65065ca05..609d3c110 100644 --- a/defaults/const.go +++ b/defaults/const.go @@ -15,7 +15,7 @@ var Examples string const ( Description = "GoSungrow - GoLang implementation to access the iSolarCloud API updated by SunGrow inverters" BinaryName = "GoSungrow" - BinaryVersion = "2.2.1" + BinaryVersion = "2.3.0" SourceRepo = "github.com/MickMake/" + BinaryName BinaryRepo = "github.com/MickMake/" + BinaryName diff --git a/examples.txt b/examples.txt index 1e4984a72..cd2a1278f 100644 --- a/examples.txt +++ b/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.showPSView '{"ps_id":"1171348"}' 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":"3"}' 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 save WebAppService.queryUserCurveTemplateData '{"template_id":"8042","date_type":"1","start_time":"20220223000000","end_time":"20220223235900"}' 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 8041 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"}' 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 get raw template 20220202 GoSungrow get template 8042 20220212 - GoSungrow data get stats GoSungrow data get search-point-names GoSungrow data get device GoSungrow data get model - GoSungrow api raw getPowerStationForHousehold '{"ps_id":"1171348"}' > "org_index_code":"|80384|80393|300977|", - GoSungrow api raw getInstallerInfoByDealerOrgCodeOrId '{"dealer_org_code":"AUSCEKK7"}' GoSungrow api raw getInstallerInfoByDealerOrgCodeOrId '{"org_id":"362245"}' GoSungrow api raw getInstallerInfoByDealerOrgCodeOrId '{"org_id":"80384"}' GoSungrow api raw getInstallerInfoByDealerOrgCodeOrId '{"org_id":"80393"}' GoSungrow api raw getInstallerInfoByDealerOrgCodeOrId '{"org_id":"300977"}' - GoSungrow api raw getKpiInfo GoSungrow api raw getInstallInfoList 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 getPowerDeviceModelTechList '{"device_type":"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 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 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 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 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 raw getPowerStationInfo '{"ps_id":"1171348"}' GoSungrow api raw getPowerTrendDayData '{"BeginTime":"20221004"}' GoSungrow api raw getPowerSettingCharges GoSungrow api raw queryUnitList GoSungrow api raw queryPsIdList GoSungrow api get getEncryptPublicKey - GoSungrow api raw getFaultCount GoSungrow api raw getFaultDetail '{"fault_code":"34"}' GoSungrow api raw getFaultMsgByFaultCode '{"fault_code":"703"}' 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 - diff --git a/google/const.go b/google/const.go deleted file mode 100644 index 112c0ff87..000000000 --- a/google/const.go +++ /dev/null @@ -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" -) diff --git a/google/sheet.go b/google/sheet.go deleted file mode 100644 index 7ed6dc333..000000000 --- a/google/sheet.go +++ /dev/null @@ -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 -} diff --git a/google/struct.go b/google/struct.go deleted file mode 100644 index 02dcc2a1e..000000000 --- a/google/struct.go +++ /dev/null @@ -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 -} diff --git a/iSolarCloud/AppService/getDeviceList/data.go b/iSolarCloud/AppService/getDeviceList/data.go index fa72ee9b6..854ae866a 100644 --- a/iSolarCloud/AppService/getDeviceList/data.go +++ b/iSolarCloud/AppService/getDeviceList/data.go @@ -11,7 +11,7 @@ const Url = "/v1/devService/getDeviceList" const Disabled = false type RequestData struct { - PsId int64 `json:"ps_id" required:"true"` + PsId string `json:"ps_id" required:"true"` } func (rd RequestData) IsValid() error { @@ -26,7 +26,7 @@ func (rd RequestData) Help() string { type ResultData struct { PageList []struct { AttrID int64 `json:"attr_id"` - ChnnlID int64 `json:"chnnl_id"` + ChannelId int64 `json:"chnnl_id"` CommandStatus int64 `json:"command_status"` ConnectState int64 `json:"connect_state"` DataFlag int64 `json:"data_flag"` @@ -132,7 +132,7 @@ func (e *EndPoint) GetDataTable() output.Table { d.PsID, d.DeviceType, d.DeviceCode, - d.ChnnlID, + d.ChannelId, d.TypeName, d.DeviceProSn, d.DeviceModel, diff --git a/iSolarCloud/AppService/queryPsProfit/data.go b/iSolarCloud/AppService/queryPsProfit/data.go index bfbef6565..98712e11d 100644 --- a/iSolarCloud/AppService/queryPsProfit/data.go +++ b/iSolarCloud/AppService/queryPsProfit/data.go @@ -41,15 +41,15 @@ type ResultData struct { CuspPowerQuantity interface{} `json:"cusp_power_quantity"` CuspUsePowerQuantity interface{} `json:"cusp_use_power_quantity"` DateID int64 `json:"date_id"` - FlatNetPowerQuantity int64 `json:"flat_net_power_quantity"` - FlatPowerQuantity int64 `json:"flat_power_quantity"` + FlatNetPowerQuantity float64 `json:"flat_net_power_quantity"` + FlatPowerQuantity float64 `json:"flat_power_quantity"` FlatUsePowerQuantity float64 `json:"flat_use_power_quantity"` 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"` PeakPowerQuantity interface{} `json:"peak_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"` TotalProfit float64 `json:"total_profit"` UpdateTime string `json:"update_time"` diff --git a/iSolarCloud/AppService/reportList/data.go b/iSolarCloud/AppService/reportList/data.go index 05b729281..42c24455f 100644 --- a/iSolarCloud/AppService/reportList/data.go +++ b/iSolarCloud/AppService/reportList/data.go @@ -97,7 +97,7 @@ type ResultData struct { SubsidyProfitOriginalUnit string `json:"subsidy_profit_original_unit"` SubsidyProfitTran string `json:"subsidy_profit_tran"` 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"` TotalProfitOriginalUnit string `json:"total_profit_original_unit"` TotalProfitTran string `json:"total_profit_tran"` diff --git a/iSolarCloud/highlevel.go b/iSolarCloud/highlevel.go index 2a35b4d45..6b52faac8 100644 --- a/iSolarCloud/highlevel.go +++ b/iSolarCloud/highlevel.go @@ -113,8 +113,8 @@ func (sg *SunGrow) GetTemplateData(template string, date string, filter string) break } - table.SetTitle("Template %s on %s for %s", template, when.String(), psId) - table.SetFilePrefix(data.SetFilenamePrefix("%s-%s-%s", when.String(), template, psId)) + table.SetTitle("Template %s on %s for %d", template, when.String(), psId) + table.SetFilePrefix(data.SetFilenamePrefix("%s-%s-%d", when.String(), template, psId)) table.SetGraphFilter(filter) table.SetSaveFile(sg.SaveAsFile) table.OutputType = sg.OutputType @@ -694,7 +694,7 @@ func (sg *SunGrow) GetDevices(psIds ...int64) error { for _, psId := range psIds { ep := sg.GetByStruct( "AppService.getDeviceList", - getDeviceList.RequestData{PsId: psId}, + getDeviceList.RequestData{PsId: strconv.FormatInt(psId, 10)}, DefaultCacheTimeout, ) if sg.Error != nil { diff --git a/lsgo/arguments.go b/lsgo/arguments.go deleted file mode 100644 index 322c51450..000000000 --- a/lsgo/arguments.go +++ /dev/null @@ -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") - } -} diff --git a/lsgo/colors.go b/lsgo/colors.go deleted file mode 100644 index 50841ed42..000000000 --- a/lsgo/colors.go +++ /dev/null @@ -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), - }, - } -) diff --git a/lsgo/file-icons.go b/lsgo/file-icons.go deleted file mode 100644 index 39f90b080..000000000 --- a/lsgo/file-icons.go +++ /dev/null @@ -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", -} diff --git a/lsgo/img/demo-1.png b/lsgo/img/demo-1.png deleted file mode 100644 index 14d3bdd60..000000000 Binary files a/lsgo/img/demo-1.png and /dev/null differ diff --git a/lsgo/img/demo-2.png b/lsgo/img/demo-2.png deleted file mode 100644 index da4864dda..000000000 Binary files a/lsgo/img/demo-2.png and /dev/null differ diff --git a/lsgo/img/demo-3.png b/lsgo/img/demo-3.png deleted file mode 100644 index 0637e1cb4..000000000 Binary files a/lsgo/img/demo-3.png and /dev/null differ diff --git a/lsgo/img/demo-4.png b/lsgo/img/demo-4.png deleted file mode 100644 index 5799e5e97..000000000 Binary files a/lsgo/img/demo-4.png and /dev/null differ diff --git a/lsgo/img/demo-5.png b/lsgo/img/demo-5.png deleted file mode 100644 index 102e69aaa..000000000 Binary files a/lsgo/img/demo-5.png and /dev/null differ diff --git a/lsgo/img/ls-go.png b/lsgo/img/ls-go.png deleted file mode 100644 index e469212d4..000000000 Binary files a/lsgo/img/ls-go.png and /dev/null differ diff --git a/lsgo/ls-unix.go b/lsgo/ls-unix.go deleted file mode 100644 index b98ee643f..000000000 --- a/lsgo/ls-unix.go +++ /dev/null @@ -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 -} diff --git a/lsgo/ls-windows.go b/lsgo/ls-windows.go deleted file mode 100644 index cab287f5b..000000000 --- a/lsgo/ls-windows.go +++ /dev/null @@ -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 -} diff --git a/lsgo/lsgo.go b/lsgo/lsgo.go deleted file mode 100644 index aee96430d..000000000 --- a/lsgo/lsgo.go +++ /dev/null @@ -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) - } -} diff --git a/lsgo/sort.go b/lsgo/sort.go deleted file mode 100644 index 22a25f5e9..000000000 --- a/lsgo/sort.go +++ /dev/null @@ -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] - } -} diff --git a/mmGit/gitFilesystem.go b/mmGit/gitFilesystem.go deleted file mode 100644 index 2622c127b..000000000 --- a/mmGit/gitFilesystem.go +++ /dev/null @@ -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 -} diff --git a/mmGit/gitInMemory.go b/mmGit/gitInMemory.go deleted file mode 100644 index 34b98eeae..000000000 --- a/mmGit/gitInMemory.go +++ /dev/null @@ -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 -} diff --git a/mmGit/struct.go b/mmGit/struct.go deleted file mode 100644 index b094e5762..000000000 --- a/mmGit/struct.go +++ /dev/null @@ -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() -} diff --git a/mmGit/utils.go b/mmGit/utils.go deleted file mode 100644 index fd750d0e9..000000000 --- a/mmGit/utils.go +++ /dev/null @@ -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 -}