Compare commits
33 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
94d0efdb12 | ||
|
|
1e821d1c10 | ||
|
|
2c80b53ee8 | ||
|
|
c33af66c6e | ||
|
|
9d47874ae3 | ||
|
|
c7b7a30210 | ||
|
|
fde665cd4d | ||
|
|
eaf2341a2a | ||
|
|
d4bed3e5c7 | ||
|
|
fcb2b3f5a5 | ||
|
|
60349c941a | ||
|
|
11bc70a710 | ||
|
|
665766019f | ||
|
|
57cef9624c | ||
|
|
6bd41ad016 | ||
|
|
05425d638f | ||
|
|
bd5a2e35d4 | ||
|
|
123e7e8758 | ||
|
|
1ec3e2e9fb | ||
|
|
0719c3cc0c | ||
|
|
0a4ceb7c4c | ||
|
|
655f59f00a | ||
|
|
5289f471d6 | ||
|
|
59597befb6 | ||
|
|
df2477a12f | ||
|
|
b709abe682 | ||
|
|
d0f3dc806e | ||
|
|
92d085acf9 | ||
|
|
20dbae21c8 | ||
|
|
9258cb4b9e | ||
|
|
d9794851f9 | ||
|
|
1fcb530ff2 | ||
|
|
364d411438 |
5
.github/ISSUE_TEMPLATE/config.yml
vendored
Normal file
@@ -0,0 +1,5 @@
|
||||
blank_issues_enabled: false
|
||||
contact_links:
|
||||
- name: Questions, Ideas, Discussions
|
||||
url: https://github.com/IceWhaleTech/CasaOS/discussions
|
||||
about: Ask questions, propose ideas, or discuss anything related to CasaOS
|
||||
4
.github/workflows/demo.yml
vendored
@@ -33,7 +33,7 @@ jobs:
|
||||
|
||||
- name: Get old instance and snapshot name, create new instance name
|
||||
run: |
|
||||
echo "OLD_INSTANCE_SNAPSHOT_NAME=$(aws lightsail get-instance-snapshots | grep '"name": "CasaOS-Demo-Snapshot-[0-9]' | sed 's/ //g' | sed 's/"//g' | sed 's/,//g' | sed 's/name://g')" >> $GITHUB_ENV
|
||||
echo "OLD_INSTANCE_SNAPSHOT_NAME=$(aws lightsail get-instance-snapshots | grep '"name": "CasaOS-Demo-Snapshot-1652856810' | sed 's/ //g' | sed 's/"//g' | sed 's/,//g' | sed 's/name://g')" >> $GITHUB_ENV
|
||||
echo "OLD_INSTANCE_NAME=$(aws lightsail get-instances | grep '"name": "CasaOS-Demo-[0-9]' | sed 's/ //g' | sed 's/"//g' | sed 's/,//g' | sed 's/name://g')" >> $GITHUB_ENV
|
||||
echo "NEW_INSTANCE_NAME=CasaOS-Demo-$(date +%s)" >> $GITHUB_ENV
|
||||
|
||||
@@ -43,7 +43,7 @@ jobs:
|
||||
--instance-snapshot-name ${{ env.OLD_INSTANCE_SNAPSHOT_NAME }} \
|
||||
--instance-names ${{ env.NEW_INSTANCE_NAME }} \
|
||||
--availability-zone us-west-2a \
|
||||
--bundle-id large_2_0
|
||||
--bundle-id medium_2_0
|
||||
|
||||
- name: Wait for new instance running
|
||||
run: |
|
||||
|
||||
2
.gitignore
vendored
@@ -29,7 +29,9 @@ gen
|
||||
/out/
|
||||
/db/
|
||||
/docs/
|
||||
/web/
|
||||
/conf/conf.ini
|
||||
__debug_bin
|
||||
main
|
||||
CasaOS
|
||||
github.com
|
||||
|
||||
399
CHANGELOG.md
Normal file
@@ -0,0 +1,399 @@
|
||||
# Changelog
|
||||
|
||||
All notable changes to this project will be documented in this file.
|
||||
|
||||
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
||||
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
||||
|
||||
## [Unreleased]
|
||||
|
||||
### Added
|
||||
|
||||
### Changed
|
||||
|
||||
|
||||
### Removed
|
||||
|
||||
### Security
|
||||
|
||||
### Fixed
|
||||
|
||||
## [0.3.2.1] - 2022-06-13
|
||||
|
||||
### Fixed
|
||||
|
||||
- Fix the problem of application opening failure on non-80 ports ([#283](https://github.com/IceWhaleTech/CasaOS/issues/283) [#280](https://github.com/IceWhaleTech/CasaOS/issues/280))
|
||||
- Modify port failure problem ([#282](https://github.com/IceWhaleTech/CasaOS/issues/282))
|
||||
- Modify environment variables disappearing problem([#284](https://github.com/IceWhaleTech/CasaOS/issues/284))
|
||||
## [0.3.2] - 2022-06-10
|
||||
|
||||
### Added
|
||||
|
||||
- [Files] Files can now be selected multiple files and downloaded, deleted, moved, etc.
|
||||
- [Apps] Support to modify the application opening address.([#204](https://github.com/IceWhaleTech/CasaOS/issues/204))
|
||||
|
||||
### Changed
|
||||
|
||||
- [Apps] Hide the display of non-essential environment variables in the application.([#196](https://github.com/IceWhaleTech/CasaOS/issues/196))
|
||||
- [System] Network, disk, cpu, memory, etc. information is modified to be pushed via socket.
|
||||
- [System] Optimize opening speed.([#214](https://github.com/IceWhaleTech/CasaOS/issues/214))
|
||||
- [Language] Update language pack [zarevskaya](https://github.com/zarevskaya) [patrickhilker](https://github.com/patrickhilker)
|
||||
- [System] Interface path adjustment
|
||||
|
||||
### Removed
|
||||
|
||||
- [Files] Remove the online preview function of PDF files
|
||||
|
||||
### Fixed
|
||||
|
||||
- [System] Fixed the problem that sync data cannot submit the device ID ([#68](https://github.com/IceWhaleTech/CasaOS/issues/68))
|
||||
- [Files] Fixed the code editor center alignment display problem.([#210](https://github.com/IceWhaleTech/CasaOS/issues/210))
|
||||
- [Files] Fixed the problem of wrong name when downloading files.([#240](https://github.com/IceWhaleTech/CasaOS/issues/240))
|
||||
- [System] Fixed the network display as a negative number problem.([#224](https://github.com/IceWhaleTech/CasaOS/issues/224))
|
||||
- [System] Fixed the problem of wireless network card traffic display.([#222](https://github.com/IceWhaleTech/CasaOS/issues/222))
|
||||
|
||||
|
||||
## [0.3.1.1] - 2022-05-17
|
||||
|
||||
### Fixed
|
||||
|
||||
- Fix the data loss problem when importing local applications
|
||||
|
||||
## [0.3.1] - 2022-05-16
|
||||
|
||||
### Added
|
||||
|
||||
- CasaConnect and file add image thumbnail function
|
||||
- Import of docker applications
|
||||
- List support custom sorting function
|
||||
- CasaConnect gives priority to LAN connections
|
||||
- USB auto-mount switch (Raspberry Pi is off by default)
|
||||
- Application custom installation supports Docker Compose configuration import in YAML format
|
||||
- You will see the new version changelog from the next version
|
||||
- Added live preview for icons in custom installed applications
|
||||
|
||||
### Changed
|
||||
|
||||
- Application data is no longer saved to the database
|
||||
- Optimize app store speed issues
|
||||
- Optimize the way WebUI is filled in
|
||||
- Image preview has been completely upgraded and now supports switching between all images in the same folder, as well as dragging, zooming, rotating and resetting.
|
||||
- Added color levels to the CPU and RAM charts
|
||||
- Optimized the display of the Connect friends list right-click menu
|
||||
- Change the initial display directory to /DATA
|
||||
|
||||
### Removed
|
||||
|
||||
- Historical Application Data
|
||||
|
||||
### Fixed
|
||||
|
||||
- Fixed the problem that some Docker CLI commands failed to import
|
||||
- Fix the problem that the application is not easily recognized in /DATA/AppData directory and docker command line after installation, it will be shown as application name
|
||||
- Fix Pi-hole installation failure
|
||||
- Fixed the issue that the app could not be updated using WatchTower
|
||||
- Fixed the problem that the task status was lost after closing Files when there was an upload task
|
||||
|
||||
## [0.3.0] - 2022-04-08
|
||||
|
||||
### Added
|
||||
|
||||
- Add CasaConnect function, now you can share private files peer-to-peer with your friends.
|
||||
- Add a widget for network traffic monitoring.
|
||||
- 12 new popular apps added to App Center
|
||||
|
||||
### Changed
|
||||
|
||||
- Updated the sidebar of Files.
|
||||
- Updated the initial directory of Files to the Root directory.
|
||||
- Armbian 22.02 armhf/arm64/amd64 platform tests passed [@igorpecovnik ](https://github.com/igorpecovnik)
|
||||
- Elementary OS 6.1 Jólnir amd64 platform tests passed [@alvarosamudio ](https://github.com/alvarosamudio)
|
||||
|
||||
### Fixed
|
||||
|
||||
- Fix an issue in Files where the backspace button would trigger a return to the previous level of the directory when creating a folder.
|
||||
- Fix the display problem of application list in CPU widget.
|
||||
- Fix the problem that the ipv6 of the application cannot be opened
|
||||
|
||||
### Removed
|
||||
|
||||
- Interfaces related to "zerotier"
|
||||
|
||||
## [0.2.10] - 2022-03-10
|
||||
|
||||
### Added
|
||||
|
||||
- Added CasaOS own file manager, now you can browse, upload, download files from the system, even edit code online, preview photos and videos through it. It will appear in the first position of Apps.
|
||||
- Added CPU core count display and memory capacity display.
|
||||
|
||||
### Changed
|
||||
|
||||
- Optimized the rendering performance of the home page.
|
||||
- Optimized the internationalization display of the time widget.
|
||||
- Show the icon of the stopped application as gray.
|
||||
- Unify the animation of the drop-down menu.
|
||||
- Optimize the display of the application drop-down menu.
|
||||
- Replaced the default font to optimize the display.
|
||||
|
||||
### Fixed
|
||||
|
||||
- Fix the problem of failed to create storage space
|
||||
|
||||
## [0.2.9] - 2022-02-18
|
||||
|
||||
### Added
|
||||
|
||||
- Add a simple notification function
|
||||
|
||||
### Changed
|
||||
|
||||
- Custom installation of new parameters(Capabilities,Hostname,Privileged)
|
||||
- Update front-end translation [@SemVer](https://github.com/zarevskaya) [@koboldMaki](https://github.com/koboldMaki) [@sgastol](https://github.com/sgastol) [@delki8](https://github.com/delki8)
|
||||
|
||||
- Modify the default location and name of the usb mount
|
||||
|
||||
### Fixed
|
||||
|
||||
- Fix the problem of being indexed by search engines
|
||||
- Fix some style display issues
|
||||
- Solve hard drive can't be formatted, can't finish adding storage
|
||||
|
||||
## [0.2.8] - 2022-01-30
|
||||
|
||||
### Added
|
||||
|
||||
- Add USB disk device display
|
||||
|
||||
### Changed
|
||||
|
||||
- Update translation [@baptiste313](https://github.com/baptiste313) [@thueske](https://github.com/thueske)
|
||||
- Compatible with more types of drives
|
||||
|
||||
### Fixed
|
||||
|
||||
- Fix the language initialization bug
|
||||
- Fix the problem that the login page could not be displayed
|
||||
- Fix missing translated content
|
||||
|
||||
## [0.2.7] - 2022.01.26
|
||||
|
||||
### Changed
|
||||
|
||||
- Apply multilingual support
|
||||
|
||||
### Security
|
||||
|
||||
- Fix an injectable execution bug
|
||||
|
||||
## [0.2.6] - 2022.01.26
|
||||
|
||||
### Added
|
||||
|
||||
- Add a bug report panel.
|
||||
- App Store apps start supporting multiple languages
|
||||
|
||||
### Fixed
|
||||
|
||||
- Fix a disk that cannot be formatted under certain circumstances
|
||||
|
||||
## [0.2.5] - 2022.01.24
|
||||
|
||||
### Added
|
||||
|
||||
- Storage Manager
|
||||
|
||||
### Changed
|
||||
|
||||
- Update Disk widget
|
||||
- Update language files [@ImOstrovskiy](https://github.com/ImOstrovskiy) [@baptiste313](https://github.com/baptiste313)
|
||||
|
||||
### Fixed
|
||||
|
||||
- File synchronization issues
|
||||
- Fix the app store classification problem
|
||||
|
||||
## [0.2.4] - 2021.12.30
|
||||
|
||||
### Changed
|
||||
|
||||
- Brand new App Store
|
||||
- Optimize request method
|
||||
|
||||
### Fixed
|
||||
|
||||
- Fix Sync panel width display error.
|
||||
- Fix App panel width display error.
|
||||
|
||||
## [0.2.3] - 2021.12.11
|
||||
|
||||
### Added
|
||||
|
||||
- Add detailed CPU and memory statistics.
|
||||
- Add the multi-language function and add Chinese translation.
|
||||
- Add the function to modify the search engine.
|
||||
- Add the function of modifying the WebUI port
|
||||
|
||||
### Changed
|
||||
|
||||
- Update update script
|
||||
- Preprocessing usb automounting
|
||||
|
||||
### Fixed
|
||||
|
||||
- Volume path problem when customizing the installation of applications
|
||||
- Fix Cpu and Ram usage display error
|
||||
- Fix translation errors
|
||||
- Fixed an error when importing and exporting appfile.
|
||||
|
||||
## [0.2.2] - 2021.12.02
|
||||
|
||||
### Changed
|
||||
|
||||
- UI adjustment
|
||||
|
||||
### Fixed
|
||||
|
||||
- Fix the problem of data display error when manually installing apps
|
||||
- Fix some spelling problems
|
||||
- Fix the bug of synchronization module
|
||||
|
||||
## [0.2.1] - 2021.11.25
|
||||
|
||||
### Fixed
|
||||
|
||||
- Fix Sync display error
|
||||
- Fix Sync Downoad url error
|
||||
- Fix Smart Block display error
|
||||
- Fix widgets settings dispaly error
|
||||
- Fix application installation path error
|
||||
|
||||
## [0.2.0] - 2021.11.25
|
||||
|
||||
### Added
|
||||
|
||||
- Add sync function
|
||||
|
||||
|
||||
## [0.1.11] - 2021.11.10
|
||||
|
||||
### Changed
|
||||
|
||||
- Adaptation of cell phone terminals
|
||||
- Optimize user experience
|
||||
- Replaced the default background
|
||||
- Optimized the display performance and fixed some bugs
|
||||
|
||||
### Fixed
|
||||
|
||||
- Resolve application installation path errors
|
||||
|
||||
## [0.1.10] - 2021.11.04
|
||||
|
||||
### Added
|
||||
|
||||
- Add application terminal
|
||||
- Add application logs
|
||||
- Add system logs
|
||||
- Add App Store for installation
|
||||
|
||||
## [0.1.9] - 2021.11.01 [YANKED]
|
||||
|
||||
## [0.1.8] - 2021.10.27
|
||||
|
||||
### Added
|
||||
|
||||
- Add system terminal
|
||||
- Add the ability to modify the user name and password
|
||||
|
||||
### Changed
|
||||
|
||||
- Experience optimization
|
||||
- Improve single user management function
|
||||
- Fixed Disk widget display error
|
||||
- Fixed Username display error after change
|
||||
- Adaptation for mobile access
|
||||
|
||||
## [0.1.7] - 2021.10.22
|
||||
|
||||
### Added
|
||||
|
||||
- Add user authentication module, Login page and initialization page.
|
||||
|
||||
### Fixed
|
||||
|
||||
- Fix the problem that the application could not start after the system restarted.
|
||||
- Home storage space data display exception
|
||||
- Script override causes application loss after installation
|
||||
- Fix docker network error
|
||||
|
||||
## [0.1.6] - 2021.10.19
|
||||
|
||||
### Added
|
||||
|
||||
- Add app icon auto-fill via docker image name.
|
||||
- Add a file selector for app install.
|
||||
|
||||
### Changed
|
||||
|
||||
- Modify import reminder.
|
||||
- Optimize the application installation process
|
||||
|
||||
### Fixed
|
||||
|
||||
- Fixed an issue with the app were it would disappear when the app was modified.
|
||||
- Fixed device selector default dir to /dev
|
||||
|
||||
## [0.1.5] - 2021.10.15
|
||||
|
||||
### Added
|
||||
|
||||
- Add CPU RAM Status with widget
|
||||
- Add Disk Info with widget
|
||||
- Realize automatic loading of widgets
|
||||
|
||||
### Changed
|
||||
|
||||
- Enhance the Docker cli import experience and automatically fill in the folders that need to be mounted
|
||||
|
||||
### Removed
|
||||
|
||||
- Remove Weather widget.
|
||||
|
||||
### Fixed
|
||||
|
||||
- AppFile upload does not pass verification
|
||||
- The setting menu of the app is displayed abnormally when the browser window is too narrow
|
||||
- The port is occupied and the program cannot start
|
||||
- Fix display bugs when windows size less than 1024px
|
||||
|
||||
## [0.1.4] - 2021.09.30
|
||||
|
||||
### Added
|
||||
|
||||
- Import and export of application configuration files
|
||||
- Automatic parsing of docker commands
|
||||
|
||||
### Changed
|
||||
|
||||
- Improve the program release process
|
||||
- Application installation process UX/UI optimization
|
||||
|
||||
### Fixed
|
||||
|
||||
- Authentication failure during the operation, resulting in the need to re-login
|
||||
|
||||
## [0.1.3] - 2021.09.29 [YANKED]
|
||||
|
||||
## [0.1.2] - 2021.09.28
|
||||
|
||||
### Fixed
|
||||
|
||||
- Application modification and new creation failure issues
|
||||
|
||||
## [0.1.1] - 2021.09.27
|
||||
|
||||
## [0.1.0] - 2021.09.26
|
||||
|
||||
### Added
|
||||
|
||||
- Application Center
|
||||
2
UI
@@ -16,32 +16,16 @@ RootPath = /casaOS
|
||||
HttpPort = 8089
|
||||
UDPPort =
|
||||
RunMode = release
|
||||
ServerApi = https://api.casaos.zimaboard.com
|
||||
ServerApi = https://api.casaos.io/casaos-api
|
||||
Handshake = socket.casaos.io
|
||||
Token =
|
||||
USBAutoMount = true
|
||||
USBAutoMount =
|
||||
|
||||
|
||||
[user]
|
||||
UserName = admin
|
||||
PWD = zimaboard
|
||||
Email = user@gmail.com
|
||||
Description = description
|
||||
Initialized = false
|
||||
Avatar =
|
||||
NickName =
|
||||
|
||||
[redis]
|
||||
Host = 127.0.0.1:6379
|
||||
Password =
|
||||
MaxIdle = 30
|
||||
MaxActive = 30
|
||||
IdleTimeout = 200
|
||||
|
||||
[system]
|
||||
ConfigStr =
|
||||
WidgetList =
|
||||
Analyse =
|
||||
|
||||
|
||||
[file]
|
||||
ShareDir =
|
||||
|
||||
13
go.mod
@@ -3,16 +3,22 @@ module github.com/IceWhaleTech/CasaOS
|
||||
go 1.16
|
||||
|
||||
require (
|
||||
github.com/Curtis-Milo/nat-type-identifier-go v0.0.0-20220215191915-18d42168c63d
|
||||
github.com/Microsoft/go-winio v0.5.0 // indirect
|
||||
github.com/Microsoft/hcsshim v0.8.22 // indirect
|
||||
github.com/PuerkitoBio/goquery v1.7.0
|
||||
github.com/StackExchange/wmi v0.0.0-20210224194228-fe8f1750fd46 // indirect
|
||||
github.com/ambelovsky/go-structs v1.1.0 // indirect
|
||||
github.com/ambelovsky/gosf v0.0.0-20201109201340-237aea4d6109
|
||||
github.com/ambelovsky/gosf-socketio v0.0.0-20201109193639-add9d32f8b19 // indirect
|
||||
github.com/bits-and-blooms/bitset v1.2.1 // indirect
|
||||
github.com/containerd/containerd v1.5.7
|
||||
github.com/containerd/continuity v0.2.0 // indirect
|
||||
github.com/disintegration/imaging v1.6.2
|
||||
github.com/docker/distribution v2.8.0+incompatible // indirect
|
||||
github.com/docker/docker v20.10.7+incompatible
|
||||
github.com/docker/go-connections v0.4.0
|
||||
github.com/dsoprea/go-exif/v3 v3.0.0-20210625224831-a6301f85c82b
|
||||
github.com/dsoprea/go-logging v0.0.0-20200710184922-b02d349568dd // indirect
|
||||
github.com/forease/gotld v0.0.0-20190808124948-c50ff635576b
|
||||
github.com/gin-contrib/gzip v0.0.2
|
||||
github.com/gin-gonic/gin v1.7.2
|
||||
@@ -26,6 +32,7 @@ require (
|
||||
github.com/gomodule/redigo v1.8.5
|
||||
github.com/google/go-github/v36 v36.0.0
|
||||
github.com/google/uuid v1.3.0 // indirect
|
||||
github.com/googollee/go-socket.io v1.6.2
|
||||
github.com/gorilla/mux v1.8.0 // indirect
|
||||
github.com/gorilla/websocket v1.4.2
|
||||
github.com/jinzhu/copier v0.3.2
|
||||
@@ -36,6 +43,7 @@ require (
|
||||
github.com/mailru/easyjson v0.7.7 // indirect
|
||||
github.com/mattn/go-isatty v0.0.14 // indirect
|
||||
github.com/mattn/go-sqlite3 v1.14.11 // indirect
|
||||
github.com/mholt/archiver/v3 v3.5.1
|
||||
github.com/moby/term v0.0.0-20210619224110-3f7ff695adc6 // indirect
|
||||
github.com/morikuni/aec v1.0.0 // indirect
|
||||
github.com/opencontainers/image-spec v1.0.2 // indirect
|
||||
@@ -50,13 +58,13 @@ require (
|
||||
github.com/sirupsen/logrus v1.8.1
|
||||
github.com/smartystreets/assertions v1.2.0 // indirect
|
||||
github.com/smartystreets/goconvey v1.6.4 // indirect
|
||||
github.com/spf13/afero v1.2.2
|
||||
github.com/swaggo/gin-swagger v1.3.0
|
||||
github.com/swaggo/swag v1.7.3
|
||||
github.com/tidwall/gjson v1.10.2
|
||||
github.com/tklauser/go-sysconf v0.3.6 // indirect
|
||||
github.com/ugorji/go v1.2.6 // indirect
|
||||
go.opencensus.io v0.23.0 // indirect
|
||||
go.uber.org/zap v1.10.0
|
||||
golang.org/x/crypto v0.0.0-20210817164053-32db794688a5
|
||||
golang.org/x/mod v0.5.0 // indirect
|
||||
golang.org/x/net v0.0.0-20211020060615-d418f374d309 // indirect
|
||||
@@ -70,6 +78,7 @@ require (
|
||||
google.golang.org/grpc v1.41.0 // indirect
|
||||
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c // indirect
|
||||
gopkg.in/ini.v1 v1.62.0 // indirect
|
||||
gopkg.in/natefinch/lumberjack.v2 v2.0.0
|
||||
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b // indirect
|
||||
gorm.io/driver/sqlite v1.2.6
|
||||
gorm.io/gorm v1.22.5
|
||||
|
||||
72
go.sum
@@ -54,8 +54,11 @@ github.com/Azure/go-autorest/autorest/mocks v0.4.0/go.mod h1:LTp+uSrOhSkaKrUy935
|
||||
github.com/Azure/go-autorest/autorest/mocks v0.4.1/go.mod h1:LTp+uSrOhSkaKrUy935gNZuuIPPVsHlr9DSOxSayd+k=
|
||||
github.com/Azure/go-autorest/logger v0.2.0/go.mod h1:T9E3cAhj2VqvPOtCYAvby9aBXkZmbF5NWuPV8+WeEW8=
|
||||
github.com/Azure/go-autorest/tracing v0.6.0/go.mod h1:+vhtPC754Xsa23ID7GlGsrdKBpUA79WCAKPPZVC2DeU=
|
||||
github.com/BurntSushi/toml v0.3.1 h1:WXkYYl6Yr3qBf1K79EBnL4mak0OimBfB0XUf9Vl28OQ=
|
||||
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
|
||||
github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo=
|
||||
github.com/Curtis-Milo/nat-type-identifier-go v0.0.0-20220215191915-18d42168c63d h1:62lEBImTxZ83pgzywgDNIrPPuQ+j4ep9QjqrWBn1hrU=
|
||||
github.com/Curtis-Milo/nat-type-identifier-go v0.0.0-20220215191915-18d42168c63d/go.mod h1:lW9x+yEjqKdPbE3+cf2fGPJXCw/hChX3Omi9QHTLFsQ=
|
||||
github.com/KyleBanks/depth v1.2.1 h1:5h8fQADFrWtarTdtDudMmGsC7GPbOAu6RVB3ffsVFHc=
|
||||
github.com/KyleBanks/depth v1.2.1/go.mod h1:jzSb9d0L43HxTQfT+oSA1EEp2q+ne2uh6XgeJcm8brE=
|
||||
github.com/Microsoft/go-winio v0.4.11/go.mod h1:VhR8bwka0BXejwEJY73c50VrPtXAaKcyvVC4A4RozmA=
|
||||
@@ -82,8 +85,6 @@ github.com/Microsoft/hcsshim/test v0.0.0-20201218223536-d3e5debf77da/go.mod h1:5
|
||||
github.com/Microsoft/hcsshim/test v0.0.0-20210227013316-43a75bb4edd3/go.mod h1:mw7qgWloBUl75W/gVH3cQszUg1+gUITj7D6NY7ywVnY=
|
||||
github.com/NYTimes/gziphandler v0.0.0-20170623195520-56545f4a5d46/go.mod h1:3wb06e3pkSAbeQ52E9H9iFoQsEEwGN64994WTCIhntQ=
|
||||
github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU=
|
||||
github.com/PuerkitoBio/goquery v1.7.0 h1:O5SP3b9JWqMSVMG69zMfj577zwkSNpxrFf7ybS74eiw=
|
||||
github.com/PuerkitoBio/goquery v1.7.0/go.mod h1:GsLWisAFVj4WgDibEWF4pvYnkVQBpKBKeU+7zCJoLcc=
|
||||
github.com/PuerkitoBio/purell v1.1.0/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbtSwDGJws/X0=
|
||||
github.com/PuerkitoBio/purell v1.1.1 h1:WEQqlqaGbrPkxLJWfBwQmfEAE1Z7ONdDLqrN38tNFfI=
|
||||
github.com/PuerkitoBio/purell v1.1.1/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbtSwDGJws/X0=
|
||||
@@ -99,8 +100,14 @@ github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuy
|
||||
github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
|
||||
github.com/alecthomas/units v0.0.0-20190717042225-c3de453c63f4/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
|
||||
github.com/alexflint/go-filemutex v0.0.0-20171022225611-72bdc8eae2ae/go.mod h1:CgnQgUtFrFz9mxFNtED3jI5tLDjKlOM+oUF/sTk6ps0=
|
||||
github.com/andybalholm/cascadia v1.1.0 h1:BuuO6sSfQNFRu1LppgbD25Hr2vLYW25JvxHs5zzsLTo=
|
||||
github.com/andybalholm/cascadia v1.1.0/go.mod h1:GsXiBklL0woXo1j/WYWtSYYC4ouU9PqHO0sqidkEA4Y=
|
||||
github.com/ambelovsky/go-structs v1.1.0 h1:LXj4/mHnYw0qhXQhOo96+ULGQ88H8qMcZd5SHef8boY=
|
||||
github.com/ambelovsky/go-structs v1.1.0/go.mod h1:zN3RBXQvxgjjq/Q/WZS7p5AEK+qC9mNg7ycnvoQ63Ak=
|
||||
github.com/ambelovsky/gosf v0.0.0-20201109201340-237aea4d6109 h1:Tp8GVfUOEmJftBqi4+/aXTwJzm24POo6wIHeuTqaT+Y=
|
||||
github.com/ambelovsky/gosf v0.0.0-20201109201340-237aea4d6109/go.mod h1:MUREokfMKREm1fOm2babarrkYdk/dGHWY+ITC3qHHPQ=
|
||||
github.com/ambelovsky/gosf-socketio v0.0.0-20201109193639-add9d32f8b19 h1:suVCm9PiIhz7ftTbWQNe7u2YjVfr8AEuUiNWKWApdMM=
|
||||
github.com/ambelovsky/gosf-socketio v0.0.0-20201109193639-add9d32f8b19/go.mod h1:o0+8DH+3X+FEOgSdNud0+8jJAsjtR9H3hF+O10Zcj/c=
|
||||
github.com/andybalholm/brotli v1.0.1 h1:KqhlKozYbRtJvsPrrEeXcO+N2l6NYT5A2QAFmSULpEc=
|
||||
github.com/andybalholm/brotli v1.0.1/go.mod h1:loMXtMfwqflxFJPmdbJO0a3KNoPuLBgiu3qAvBg8x/Y=
|
||||
github.com/anmitsu/go-shlex v0.0.0-20161002113705-648efa622239/go.mod h1:2FmKhYUyUczH0OGQWaF5ceTx0UBShxjsH6f8oGKYe2c=
|
||||
github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY=
|
||||
github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6/go.mod h1:grANhF5doyWs3UAsr3K4I6qtAmlQcZDesFNEHPZAzj8=
|
||||
@@ -269,6 +276,8 @@ github.com/denverdino/aliyungo v0.0.0-20190125010748-a747050bb1ba/go.mod h1:dV8l
|
||||
github.com/dgrijalva/jwt-go v0.0.0-20170104182250-a601269ab70c/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ=
|
||||
github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ=
|
||||
github.com/dgryski/go-sip13 v0.0.0-20181026042036-e10d5fee7954/go.mod h1:vAd38F8PWV+bWy6jNmig1y/TA+kYO4g3RSRF0IAv0no=
|
||||
github.com/disintegration/imaging v1.6.2 h1:w1LecBlG2Lnp8B3jk5zSuNqd7b4DXhcjwek1ei82L+c=
|
||||
github.com/disintegration/imaging v1.6.2/go.mod h1:44/5580QXChDfwIclfc/PCwrr44amcmDAg8hxG0Ewe4=
|
||||
github.com/dnaeon/go-vcr v1.0.1/go.mod h1:aBB1+wY4s93YsC3HHjMBMrwTj2R9FHDzUr9KyGc8n1E=
|
||||
github.com/docker/distribution v0.0.0-20190905152932-14b96e55d84c/go.mod h1:0+TTO4EOBfRPhZXAeF1Vu+W3hHZ8eLp8PgKVZlcvtFY=
|
||||
github.com/docker/distribution v2.7.1-0.20190205005809-0d3efadf0154+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w=
|
||||
@@ -289,6 +298,21 @@ github.com/docker/go-units v0.4.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDD
|
||||
github.com/docker/libtrust v0.0.0-20150114040149-fa567046d9b1/go.mod h1:cyGadeNEkKy96OOhEzfZl+yxihPEzKnqJwvfuSUqbZE=
|
||||
github.com/docker/spdystream v0.0.0-20160310174837-449fdfce4d96/go.mod h1:Qh8CwZgvJUkLughtfhJv5dyTYa91l1fOUCrgjqmcifM=
|
||||
github.com/docopt/docopt-go v0.0.0-20180111231733-ee0de3bc6815/go.mod h1:WwZ+bS3ebgob9U8Nd0kOddGdZWjyMGR8Wziv+TBNwSE=
|
||||
github.com/dsnet/compress v0.0.2-0.20210315054119-f66993602bf5 h1:iFaUwBSo5Svw6L7HYpRu/0lE3e0BaElwnNO1qkNQxBY=
|
||||
github.com/dsnet/compress v0.0.2-0.20210315054119-f66993602bf5/go.mod h1:qssHWj60/X5sZFNxpG4HBPDHVqxNm4DfnCKgrbZOT+s=
|
||||
github.com/dsnet/golib v0.0.0-20171103203638-1ea166775780/go.mod h1:Lj+Z9rebOhdfkVLjJ8T6VcRQv3SXugXy999NBtR9aFY=
|
||||
github.com/dsoprea/go-exif/v2 v2.0.0-20200321225314-640175a69fe4/go.mod h1:Lm2lMM2zx8p4a34ZemkaUV95AnMl4ZvLbCUbwOvLC2E=
|
||||
github.com/dsoprea/go-exif/v3 v3.0.0-20200717053412-08f1b6708903/go.mod h1:0nsO1ce0mh5czxGeLo4+OCZ/C6Eo6ZlMWsz7rH/Gxv8=
|
||||
github.com/dsoprea/go-exif/v3 v3.0.0-20210625224831-a6301f85c82b h1:NgNuLvW/gAFKU30ULWW0gtkCt56JfB7FrZ2zyo0wT8I=
|
||||
github.com/dsoprea/go-exif/v3 v3.0.0-20210625224831-a6301f85c82b/go.mod h1:cg5SNYKHMmzxsr9X6ZeLh/nfBRHHp5PngtEPcujONtk=
|
||||
github.com/dsoprea/go-logging v0.0.0-20190624164917-c4f10aab7696/go.mod h1:Nm/x2ZUNRW6Fe5C3LxdY1PyZY5wmDv/s5dkPJ/VB3iA=
|
||||
github.com/dsoprea/go-logging v0.0.0-20200517223158-a10564966e9d/go.mod h1:7I+3Pe2o/YSU88W0hWlm9S22W7XI1JFNJ86U0zPKMf8=
|
||||
github.com/dsoprea/go-logging v0.0.0-20200710184922-b02d349568dd h1:l+vLbuxptsC6VQyQsfD7NnEC8BZuFpz45PgY+pH8YTg=
|
||||
github.com/dsoprea/go-logging v0.0.0-20200710184922-b02d349568dd/go.mod h1:7I+3Pe2o/YSU88W0hWlm9S22W7XI1JFNJ86U0zPKMf8=
|
||||
github.com/dsoprea/go-utility v0.0.0-20200711062821-fab8125e9bdf h1:/w4QxepU4AHh3AuO6/g8y/YIIHH5+aKP3Bj8sg5cqhU=
|
||||
github.com/dsoprea/go-utility v0.0.0-20200711062821-fab8125e9bdf/go.mod h1:95+K3z2L0mqsVYd6yveIv1lmtT3tcQQ3dVakPySffW8=
|
||||
github.com/dsoprea/go-utility/v2 v2.0.0-20200717064901-2fccff4aa15e h1:IxIbA7VbCNrwumIYjDoMOdf4KOSkMC6NJE4s8oRbE7E=
|
||||
github.com/dsoprea/go-utility/v2 v2.0.0-20200717064901-2fccff4aa15e/go.mod h1:uAzdkPTub5Y9yQwXe8W4m2XuP0tK4a9Q/dantD0+uaU=
|
||||
github.com/dustin/go-humanize v0.0.0-20171111073723-bb3d318650d4/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk=
|
||||
github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk=
|
||||
github.com/elazarl/goproxy v0.0.0-20180725130230-947c36da3153/go.mod h1:/Zj4wYkgs4iZTTu3o/KG3Itv/qCCa8VVMlb3i9OVuzc=
|
||||
@@ -330,6 +354,9 @@ github.com/gin-gonic/gin v1.7.2 h1:Tg03T9yM2xa8j6I3Z3oqLaQRSmKvxPd6g/2HJ6zICFA=
|
||||
github.com/gin-gonic/gin v1.7.2/go.mod h1:jD2toBW3GZUr5UMcdrwQA10I7RuaFOl/SGeDjXkfUtY=
|
||||
github.com/gliderlabs/ssh v0.1.1/go.mod h1:U7qILu1NlMHj9FlMhZLlkCdDnU1DBEAqr0aevW3Awn0=
|
||||
github.com/go-errors/errors v1.0.1/go.mod h1:f4zRHt4oKfwPJE5k8C9vpYG+aDHdBFUsgrm6/TyX73Q=
|
||||
github.com/go-errors/errors v1.0.2/go.mod h1:psDX2osz5VnTOnFWbDeWwS7yejl+uV3FEWEp4lssFEs=
|
||||
github.com/go-errors/errors v1.1.1 h1:ljK/pL5ltg3qoN+OtN6yCv9HWSfMwxSx90GJCZQxYNg=
|
||||
github.com/go-errors/errors v1.1.1/go.mod h1:psDX2osz5VnTOnFWbDeWwS7yejl+uV3FEWEp4lssFEs=
|
||||
github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU=
|
||||
github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8=
|
||||
github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8=
|
||||
@@ -386,6 +413,7 @@ github.com/godbus/dbus v0.0.0-20180201030542-885f9cc04c9c/go.mod h1:/YcGZj5zSblf
|
||||
github.com/godbus/dbus v0.0.0-20190422162347-ade71ed3457e/go.mod h1:bBOAhwG1umN6/6ZUMtDFBMQR8jRg9O75tm9K00oMsK4=
|
||||
github.com/godbus/dbus/v5 v5.0.3/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA=
|
||||
github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA=
|
||||
github.com/gofrs/uuid v4.0.0+incompatible h1:1SD/1F5pU8p29ybwgQSwpQk+mwdRrXCYuPhW6m+TnJw=
|
||||
github.com/gofrs/uuid v4.0.0+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRxnplIgP/c0N/04lM=
|
||||
github.com/gogo/googleapis v1.2.0/go.mod h1:Njal3psf3qN6dwBtQfUmBZh2ybovJ0tlu3o/AC7HYjU=
|
||||
github.com/gogo/googleapis v1.4.0/go.mod h1:5YRNX2z1oM5gXdAkurHa942MDgEJyk02w4OecKY87+c=
|
||||
@@ -400,6 +428,9 @@ github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q=
|
||||
github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q=
|
||||
github.com/golang-jwt/jwt v3.2.2+incompatible h1:IfV12K8xAKAnZqdXVzCZ+TOjboZ2keLg81eXfW3O+oY=
|
||||
github.com/golang-jwt/jwt v3.2.2+incompatible/go.mod h1:8pz2t5EyA70fFQQSrl6XZXzqecmYZeUEB8OUGHkxJ+I=
|
||||
github.com/golang/geo v0.0.0-20190916061304-5b978397cfec/go.mod h1:QZ0nwyI2jOfgRAoBvP+ab5aRr7c9x7lhGEJrKvBwjWI=
|
||||
github.com/golang/geo v0.0.0-20200319012246-673a6f80352d h1:C/hKUcHT483btRbeGkrRjJz+Zbcj8audldIi9tRJDCc=
|
||||
github.com/golang/geo v0.0.0-20200319012246-673a6f80352d/go.mod h1:QZ0nwyI2jOfgRAoBvP+ab5aRr7c9x7lhGEJrKvBwjWI=
|
||||
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
|
||||
github.com/golang/groupcache v0.0.0-20160516000752-02826c3e7903/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
|
||||
github.com/golang/groupcache v0.0.0-20190129154638-5b532d6fd5ef/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
|
||||
@@ -435,6 +466,9 @@ github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw
|
||||
github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk=
|
||||
github.com/golang/protobuf v1.5.2 h1:ROPKBNFfQgOUMifHyP+KYbvpjbdoFNs+aK7DXlji0Tw=
|
||||
github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY=
|
||||
github.com/golang/snappy v0.0.2 h1:aeE13tS0IiQgFjYdoL8qN3K1N2bXXtI6Vi51/y7BpMw=
|
||||
github.com/golang/snappy v0.0.2/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
|
||||
github.com/gomodule/redigo v1.8.4/go.mod h1:P9dn9mFrCBvWhGE1wpxx6fgq7BAeLBk+UUUzlpkBYO0=
|
||||
github.com/gomodule/redigo v1.8.5 h1:nRAxCa+SVsyjSBrtZmG/cqb6VbTmuRzpg/PoTFlpumc=
|
||||
github.com/gomodule/redigo v1.8.5/go.mod h1:P9dn9mFrCBvWhGE1wpxx6fgq7BAeLBk+UUUzlpkBYO0=
|
||||
github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
|
||||
@@ -481,6 +515,8 @@ github.com/googleapis/gax-go/v2 v2.0.3/go.mod h1:LLvjysVCY1JZeum8Z6l8qUty8fiNwE0
|
||||
github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg=
|
||||
github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk=
|
||||
github.com/googleapis/gnostic v0.4.1/go.mod h1:LRhVm6pbyptWbWbuZ38d1eyptfvIytN3ir6b65WBswg=
|
||||
github.com/googollee/go-socket.io v1.6.2 h1:olKLLHJtHz1IkL/OrTyNriZZvVQYEORNkJAqsOwPask=
|
||||
github.com/googollee/go-socket.io v1.6.2/go.mod h1:0vGP8/dXR9SZUMMD4+xxaGo/lohOw3YWMh2WRiWeKxg=
|
||||
github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1 h1:EGx4pi6eqNxGaHF6qqu48+N2wcFQ5qg5FXgOdqsJ5d8=
|
||||
github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY=
|
||||
github.com/gorilla/handlers v0.0.0-20150720190736-60c7bfde3e33/go.mod h1:Qkdc/uu4tH4g6mTK6auzZ766c4CA0Ng8+o/OAirnOIQ=
|
||||
@@ -516,6 +552,7 @@ github.com/imdario/mergo v0.3.12/go.mod h1:jmQim1M+e3UYxmgPu/WyfjB3N3VflVyUjjjwH
|
||||
github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8=
|
||||
github.com/j-keck/arping v0.0.0-20160618110441-2cf9dc699c56/go.mod h1:ymszkNOg6tORTn+6F6j+Jc8TOr5osrynvN6ivFWZ2GA=
|
||||
github.com/jellevandenhooff/dkim v0.0.0-20150330215556-f50fe3d243e1/go.mod h1:E0B/fFc00Y+Rasa88328GlI/XbtyysCtTHZS8h7IrBU=
|
||||
github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI=
|
||||
github.com/jinzhu/copier v0.3.2 h1:QdBOCbaouLDYaIPFfi1bKv5F5tPpeTwXe4sD0jqtz5w=
|
||||
github.com/jinzhu/copier v0.3.2/go.mod h1:24xnZezI2Yqac9J61UC6/dG/k76ttpq0DdJI3QmUvro=
|
||||
github.com/jinzhu/inflection v1.0.0 h1:K317FqzuhWc8YvSVlFMCCUb36O/S9MCKRDI7QkRKD/E=
|
||||
@@ -544,10 +581,15 @@ github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvW
|
||||
github.com/kisielk/errcheck v1.2.0/go.mod h1:/BMXB+zMLi60iA8Vv6Ksmxu/1UDYcXs4uQLJ+jE2L00=
|
||||
github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8=
|
||||
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
|
||||
github.com/klauspost/compress v1.4.1/go.mod h1:RyIbtBH6LamlWaDj8nUwkbUhJ87Yi3uG0guNDohfE1A=
|
||||
github.com/klauspost/compress v1.11.3/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs=
|
||||
github.com/klauspost/compress v1.11.4/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs=
|
||||
github.com/klauspost/compress v1.11.13/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs=
|
||||
github.com/klauspost/compress v1.13.6 h1:P76CopJELS0TiO2mebmnzgWaajssP/EszplttgQxcgc=
|
||||
github.com/klauspost/compress v1.13.6/go.mod h1:/3/Vjq9QcHkK5uEr5lBEmyoZ1iFhe47etQ6QUkpK6sk=
|
||||
github.com/klauspost/cpuid v1.2.0/go.mod h1:Pj4uuM528wm8OyEC2QMXAi2YiTZ96dNQPGgoMS4s3ek=
|
||||
github.com/klauspost/pgzip v1.2.5 h1:qnWYvvKqedOF2ulHpMG72XQol4ILEJ8k2wwRl/Km8oE=
|
||||
github.com/klauspost/pgzip v1.2.5/go.mod h1:Ch1tH69qFZu15pkjo5kYi6mth2Zzwzt50oCQKQE9RUs=
|
||||
github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
|
||||
github.com/konsorten/go-windows-terminal-sequences v1.0.2/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
|
||||
github.com/konsorten/go-windows-terminal-sequences v1.0.3/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
|
||||
@@ -600,10 +642,13 @@ github.com/mattn/go-sqlite3 v1.14.11 h1:gt+cp9c0XGqe9S/wAHTL3n/7MqY+siPWgWJgqdsF
|
||||
github.com/mattn/go-sqlite3 v1.14.11/go.mod h1:NyWgC/yNuGj7Q9rpYnZvas74GogHl5/Z4A/KQRfk6bU=
|
||||
github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0=
|
||||
github.com/matttproud/golang_protobuf_extensions v1.0.2-0.20181231171920-c182affec369/go.mod h1:BSXmuO+STAnVfrANrmjBb36TMTDstsz7MSK+HVaYKv4=
|
||||
github.com/mholt/archiver/v3 v3.5.1 h1:rDjOBX9JSF5BvoJGvjqK479aL70qh9DIpZCl+k7Clwo=
|
||||
github.com/mholt/archiver/v3 v3.5.1/go.mod h1:e3dqJ7H78uzsRSEACH1joayhuSyhnonssnDhppzS1L4=
|
||||
github.com/microcosm-cc/bluemonday v1.0.1/go.mod h1:hsXNsILzKxV+sX77C5b8FSuKF00vh2OMYv+xgHpAMF4=
|
||||
github.com/miekg/pkcs11 v1.0.3/go.mod h1:XsNlhZGX73bx86s2hdc/FuaLm2CPZJemRLMA+WTFxgs=
|
||||
github.com/mistifyio/go-zfs v2.1.2-0.20190413222219-f784269be439+incompatible/go.mod h1:8AuVvqP/mXw1px98n46wfvcGfQ4ci2FwoAjKYxuo3Z4=
|
||||
github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=
|
||||
github.com/mitchellh/mapstructure v1.1.2 h1:fmNYVwqnSfB9mZU6OS2O6GsXM+wcskZDuKQzvN1EDeE=
|
||||
github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
|
||||
github.com/mitchellh/osext v0.0.0-20151018003038-5e2d6d41470f/go.mod h1:OkQIRizQZAeMln+1tSwduZz7+Af5oFlKirV/MSYes2A=
|
||||
github.com/moby/locker v1.0.1 h1:fOXqR41zeveg4fFODix+1Ch4mj/gT0NE1XJbp/epuBg=
|
||||
@@ -632,6 +677,8 @@ github.com/ncw/swift v1.0.47/go.mod h1:23YIA4yWVnGwv2dQlN4bB7egfYX6YLn0Yo/S6zZO/
|
||||
github.com/neelance/astrewrite v0.0.0-20160511093645-99348263ae86/go.mod h1:kHJEU3ofeGjhHklVoIGuVj85JJwZ6kWPaJwCIxgnFmo=
|
||||
github.com/neelance/sourcemap v0.0.0-20151028013722-8c68805598ab/go.mod h1:Qr6/a/Q4r9LP1IltGz7tA7iOK1WonHEYhu1HRBA7ZiM=
|
||||
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno=
|
||||
github.com/nwaples/rardecode v1.1.0 h1:vSxaY8vQhOcVr4mm5e8XllHWTiM4JF507A0Katqw7MQ=
|
||||
github.com/nwaples/rardecode v1.1.0/go.mod h1:5DzqNKiOdpKKBH87u8VlvAnPZMXcGRhxWkRpHbbfGS0=
|
||||
github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A=
|
||||
github.com/nxadm/tail v1.4.8 h1:nPr65rt6Y5JFSKQO7qToXr7pePgD6Gwiw05lkbyAQTE=
|
||||
github.com/nxadm/tail v1.4.8/go.mod h1:+ncqLTQzXmGhMZNUePPaPqPvBxHAIsmXswZKocGu+AU=
|
||||
@@ -692,6 +739,8 @@ github.com/patrickmn/go-cache v2.1.0+incompatible/go.mod h1:3Qf8kWWT7OJRJbdiICTK
|
||||
github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic=
|
||||
github.com/pelletier/go-toml v1.8.1/go.mod h1:T2/BmBdy8dvIRq1a/8aqjN41wvWlN4lrapLU/GW4pbc=
|
||||
github.com/peterbourgon/diskv v2.0.1+incompatible/go.mod h1:uqqh8zWWbv1HBMNONnaR/tNboyR3/BZd58JJSHlUSCU=
|
||||
github.com/pierrec/lz4/v4 v4.1.2 h1:qvY3YFXRQE/XB8MlLzJH7mSzBs74eA2gg52YTk6jUPM=
|
||||
github.com/pierrec/lz4/v4 v4.1.2/go.mod h1:gZWDp/Ze/IJXGXf23ltt2EXimqmTUXEy0GFuRQyBid4=
|
||||
github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||
github.com/pkg/errors v0.8.1-0.20171018195549-f15c970de5b7/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||
@@ -794,7 +843,6 @@ github.com/sourcegraph/annotate v0.0.0-20160123013949-f4cad6c6324d/go.mod h1:Udh
|
||||
github.com/sourcegraph/syntaxhighlight v0.0.0-20170531221838-bd320f5d308e/go.mod h1:HuIsMU8RRBOtsCgI77wP899iHVBQpCmg4ErYMZB+2IA=
|
||||
github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA=
|
||||
github.com/spf13/afero v1.1.2/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B0CQ=
|
||||
github.com/spf13/afero v1.2.2 h1:5jhuqJyZCZf2JRofRvN/nIFgIWNzPa3/Vz8mYylgbWc=
|
||||
github.com/spf13/afero v1.2.2/go.mod h1:9ZxEEn6pIJ8Rxe320qSDBk6AsU0r9pR7Q4OcevTdifk=
|
||||
github.com/spf13/cast v1.3.0/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE=
|
||||
github.com/spf13/cobra v0.0.2-0.20171109065643-2da4a54c5cee/go.mod h1:1l0Ry5zgKvJasoi3XT1TypsSe7PqH0Sj9dhYf7v3XqQ=
|
||||
@@ -856,6 +904,9 @@ github.com/ugorji/go/codec v1.1.7/go.mod h1:Ax+UKWsSmolVDwsd+7N3ZtXu+yMGCf907BLY
|
||||
github.com/ugorji/go/codec v1.1.13/go.mod h1:oNVt3Dq+FO91WNQ/9JnHKQP2QJxTzoN7wCBFCq1OeuU=
|
||||
github.com/ugorji/go/codec v1.2.6 h1:7kbGefxLoDBuYXOms4yD7223OpNMMPNPZxXk5TvFcyQ=
|
||||
github.com/ugorji/go/codec v1.2.6/go.mod h1:V6TCNZ4PHqoHGFZuSG1W8nrCzzdgA2DozYxWFFpvxTw=
|
||||
github.com/ulikunitz/xz v0.5.8/go.mod h1:nbz6k7qbPmH4IRqmfOplQw/tblSgqTqBwxkY0oWt/14=
|
||||
github.com/ulikunitz/xz v0.5.9 h1:RsKRIA2MO8x56wkkcd3LbtcE/uMszhb6DpRf+3uwa3I=
|
||||
github.com/ulikunitz/xz v0.5.9/go.mod h1:nbz6k7qbPmH4IRqmfOplQw/tblSgqTqBwxkY0oWt/14=
|
||||
github.com/urfave/cli v0.0.0-20171014202726-7bc6a0acffa5/go.mod h1:70zkFmudgCuE/ngEzBv17Jvp/497gISqfk5gWijbERA=
|
||||
github.com/urfave/cli v1.20.0/go.mod h1:70zkFmudgCuE/ngEzBv17Jvp/497gISqfk5gWijbERA=
|
||||
github.com/urfave/cli v1.22.1/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0=
|
||||
@@ -874,6 +925,8 @@ github.com/willf/bitset v1.1.11/go.mod h1:83CECat5yLh5zVOf4P1ErAgKA5UDvKtgyUABdr
|
||||
github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f/go.mod h1:N2zxlSyiKSe5eX1tZViRH5QA0qijqEDrYZiPEAiq3wU=
|
||||
github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415/go.mod h1:GwrjFmJcFw6At/Gs6z4yjiIwzuJ1/+UwLxMQDVQXShQ=
|
||||
github.com/xeipuuv/gojsonschema v0.0.0-20180618132009-1d523034197f/go.mod h1:5yf86TLmAcydyeJq5YvxkGPE2fm/u4myDekKRoLuqhs=
|
||||
github.com/xi2/xz v0.0.0-20171230120015-48954b6210f8 h1:nIPpBwaJSVYIxUFsDv3M8ofmx9yWTog9BfvIu0q41lo=
|
||||
github.com/xi2/xz v0.0.0-20171230120015-48954b6210f8/go.mod h1:HUYIGzjTL3rfEspMxjDjgmT5uz5wzYJKVo23qUhYTos=
|
||||
github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU=
|
||||
github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1:aYKd//L2LvnjZzWKhF00oedf4jCCReLcmhLdhm1A27Q=
|
||||
github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
||||
@@ -900,8 +953,11 @@ go.opencensus.io v0.23.0 h1:gqCw0LfLxScz8irSi8exQc7fyQ0fKQU/qnC/X8+V/1M=
|
||||
go.opencensus.io v0.23.0/go.mod h1:XItmlyltB5F7CS4xOC1DcqMoFqwtC6OG2xF7mCv7P7E=
|
||||
go.opentelemetry.io/proto/otlp v0.7.0/go.mod h1:PqfVotwruBrMGOCsRd/89rSnXhoiJIqeYNgFYFoEGnI=
|
||||
go.uber.org/atomic v1.3.2/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE=
|
||||
go.uber.org/atomic v1.4.0 h1:cxzIVoETapQEqDhQu3QfnvXAV4AlzcvUCxkVUFw3+EU=
|
||||
go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE=
|
||||
go.uber.org/multierr v1.1.0 h1:HoEmRHQPVSqub6w2z2d2EOVs2fjyFRGyofhKuyDq0QI=
|
||||
go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0=
|
||||
go.uber.org/zap v1.10.0 h1:ORx85nbTijNz8ljznvCMR1ZBIPKFn3jQrag10X2AsuM=
|
||||
go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q=
|
||||
go4.org v0.0.0-20180809161055-417644f6feb5/go.mod h1:MkTOUMDaeVYJUOUsaDXIhWPZYa1yOyC1qaOBpL57BhE=
|
||||
golang.org/x/build v0.0.0-20190111050920-041ab4dc3f9d/go.mod h1:OWs+y06UdEOHN4y+MfF/py+xQ/tYqIWW03b70/CG9Rw=
|
||||
@@ -935,6 +991,8 @@ golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EH
|
||||
golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU=
|
||||
golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js=
|
||||
golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
|
||||
golang.org/x/image v0.0.0-20191009234506-e7c1f5e7dbb8 h1:hVwzHzIUGRjiF7EcUjqNxk3NCfkPxbDKRdnNE1Rpg0U=
|
||||
golang.org/x/image v0.0.0-20191009234506-e7c1f5e7dbb8/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
|
||||
golang.org/x/lint v0.0.0-20180702182130-06c8688daad7/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
|
||||
golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
|
||||
golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU=
|
||||
@@ -957,7 +1015,6 @@ golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
||||
golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
||||
golang.org/x/mod v0.5.0 h1:UG21uOlmZabA4fW5i7ZX6bjw1xELEGg/ZLgZq9auk/Q=
|
||||
golang.org/x/mod v0.5.0/go.mod h1:5OXOZSfqPIIbmVBIIKWRFfZjPR0E5r58TLhUjH0a2Ro=
|
||||
golang.org/x/net v0.0.0-20180218175443-cbe0f9307d01/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
@@ -991,6 +1048,7 @@ golang.org/x/net v0.0.0-20200202094626-16171245cfb2/go.mod h1:z5CRVTTTmAJ677TzLL
|
||||
golang.org/x/net v0.0.0-20200222125558-5a598a2470a0/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20200301022130-244492dfa37a/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20200320220750-118fecf932d8/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
|
||||
golang.org/x/net v0.0.0-20200501053045-e0ff5e5a1de5/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
|
||||
golang.org/x/net v0.0.0-20200506145744-7e3656a0809f/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
|
||||
@@ -1329,6 +1387,7 @@ gopkg.in/go-playground/validator.v8 v8.18.2/go.mod h1:RX2a/7Ha8BgOhfk7j780h4/u/R
|
||||
gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw=
|
||||
gopkg.in/ini.v1 v1.62.0 h1:duBzk771uxoUuOlyRLkHsygud9+5lrlGjdFBb4mSKDU=
|
||||
gopkg.in/ini.v1 v1.62.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=
|
||||
gopkg.in/natefinch/lumberjack.v2 v2.0.0 h1:1Lc07Kr7qY4U2YPouBjpCLxpiyxIVoxqXgkXLknAOE8=
|
||||
gopkg.in/natefinch/lumberjack.v2 v2.0.0/go.mod h1:l0ndWWf7gzL7RNwBG7wST/UCcT4T24xpD6X8LsfU/+k=
|
||||
gopkg.in/resty.v1 v1.12.0/go.mod h1:mDo4pnntr5jdWRML875a/NmxYqAlA73dVijT2AXvQQo=
|
||||
gopkg.in/square/go-jose.v2 v2.2.2/go.mod h1:M9dMgbHiYLoDGQrXy7OpJDJWiKiU//h+vD76mk0e1AI=
|
||||
@@ -1342,6 +1401,7 @@ gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v2 v2.2.3/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v2 v2.2.5/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v2 v2.2.7/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=
|
||||
|
||||
75
main.go
@@ -4,13 +4,13 @@ import (
|
||||
"flag"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"runtime"
|
||||
"time"
|
||||
|
||||
"github.com/IceWhaleTech/CasaOS/model/notify"
|
||||
"github.com/IceWhaleTech/CasaOS/pkg/cache"
|
||||
"github.com/IceWhaleTech/CasaOS/pkg/config"
|
||||
"github.com/IceWhaleTech/CasaOS/pkg/sqlite"
|
||||
loger2 "github.com/IceWhaleTech/CasaOS/pkg/utils/loger"
|
||||
"github.com/IceWhaleTech/CasaOS/pkg/utils/loger"
|
||||
"github.com/IceWhaleTech/CasaOS/route"
|
||||
"github.com/IceWhaleTech/CasaOS/service"
|
||||
|
||||
@@ -21,47 +21,35 @@ import (
|
||||
var sqliteDB *gorm.DB
|
||||
|
||||
var configFlag = flag.String("c", "", "config address")
|
||||
|
||||
var dbFlag = flag.String("db", "", "db path")
|
||||
var showUserInfo = flag.Bool("show-user-info", false, "show user info")
|
||||
|
||||
func init() {
|
||||
flag.Parse()
|
||||
config.InitSetup(*configFlag)
|
||||
config.UpdateSetup()
|
||||
loger2.LogSetup()
|
||||
sysType := runtime.GOOS
|
||||
if sysType == "windows" {
|
||||
config.AppInfo.ProjectPath = "C:\\CasaOS\\service"
|
||||
config.Cfg.Section("app").Key("ProjectPath").SetValue("C:\\CasaOS\\service")
|
||||
|
||||
config.AppInfo.RootPath = "C:\\CasaOS"
|
||||
config.Cfg.Section("app").Key("RootPath").SetValue("C:\\CasaOS")
|
||||
config.Cfg.SaveTo(config.SystemConfigInfo.ConfigPath)
|
||||
loger.LogInit()
|
||||
if len(*dbFlag) == 0 {
|
||||
*dbFlag = config.AppInfo.ProjectPath + "/db"
|
||||
}
|
||||
if sysType == "darwin" {
|
||||
config.AppInfo.ProjectPath = "./CasaOS/service"
|
||||
config.Cfg.Section("app").Key("ProjectPath").SetValue("./CasaOS/service")
|
||||
|
||||
config.AppInfo.RootPath = "./CasaOS"
|
||||
config.Cfg.Section("app").Key("RootPath").SetValue("./CasaOS")
|
||||
config.Cfg.SaveTo(config.SystemConfigInfo.ConfigPath)
|
||||
}
|
||||
|
||||
sqliteDB = sqlite.GetDb(config.AppInfo.ProjectPath)
|
||||
sqliteDB = sqlite.GetDb(*dbFlag)
|
||||
//gredis.GetRedisConn(config.RedisInfo),
|
||||
service.MyService = service.NewService(sqliteDB, loger2.NewOLoger())
|
||||
service.MyService = service.NewService(sqliteDB)
|
||||
service.Cache = cache.Init()
|
||||
|
||||
go service.UDPService()
|
||||
|
||||
fmt.Println("token", service.GetToken())
|
||||
fmt.Println("t", service.GetToken())
|
||||
service.UDPAddressMap = make(map[string]string)
|
||||
//go service.SocketConnect()
|
||||
service.CancelList = make(map[string]string)
|
||||
service.InternalInspection = make(map[string][]string)
|
||||
service.NewVersionApp = make(map[string]string)
|
||||
route.InitFunction()
|
||||
|
||||
go service.SendIPToServer()
|
||||
go service.LoopFriend()
|
||||
// go service.LoopFriend()
|
||||
// go service.MyService.App().CheckNewImage()
|
||||
|
||||
}
|
||||
|
||||
@@ -77,12 +65,22 @@ func init() {
|
||||
// @name Authorization
|
||||
// @BasePath /v1
|
||||
func main() {
|
||||
service.NotifyMsg = make(chan notify.Message, 10)
|
||||
if *showUserInfo {
|
||||
fmt.Println("CasaOS User Info")
|
||||
fmt.Println("UserName:" + config.UserInfo.UserName)
|
||||
fmt.Println("Password:" + config.UserInfo.PWD)
|
||||
return
|
||||
}
|
||||
|
||||
go route.SocketInit(service.NotifyMsg)
|
||||
go func() {
|
||||
for i := 0; i < 1000; i++ {
|
||||
time.Sleep(2 * time.Second)
|
||||
//service.NotifyMsg <- strconv.Itoa(i)
|
||||
}
|
||||
}()
|
||||
|
||||
//model.Setup()
|
||||
//gredis.Setup()
|
||||
r := route.InitRouter()
|
||||
@@ -97,20 +95,24 @@ func main() {
|
||||
service.SendIPToServer()
|
||||
|
||||
service.LoopFriend()
|
||||
|
||||
//service.MyService.App().CheckNewImage()
|
||||
})
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
}
|
||||
err = cron2.AddFunc("0/5 * * * * *", func() {
|
||||
if service.ClientCount > 0 {
|
||||
// route.SendNetINfoBySocket()
|
||||
// route.SendCPUBySocket()
|
||||
// route.SendMemBySocket()
|
||||
// route.SendDiskBySocket()
|
||||
// route.SendUSBBySocket()
|
||||
route.SendAllHardwareStatusBySocket()
|
||||
}
|
||||
})
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
}
|
||||
// err = cron2.AddFunc("0/1 * * * * *", func() {
|
||||
|
||||
// //service.SendIPToServer()
|
||||
// //service.LoopNet()
|
||||
|
||||
// })
|
||||
// if err != nil {
|
||||
// fmt.Println(err)
|
||||
// }
|
||||
cron2.Start()
|
||||
defer cron2.Stop()
|
||||
s := &http.Server{
|
||||
@@ -123,4 +125,7 @@ func main() {
|
||||
|
||||
s.ListenAndServe()
|
||||
|
||||
// if err := r.Run(fmt.Sprintf(":%v", config.ServerInfo.HttpPort)); err != nil {
|
||||
// fmt.Println("failed run app: ", err)
|
||||
// }
|
||||
}
|
||||
|
||||
@@ -1,3 +1,13 @@
|
||||
/*
|
||||
* @Author: LinkLeong link@icewhale.com
|
||||
* @Date: 2021-10-08 10:29:08
|
||||
* @LastEditors: LinkLeong
|
||||
* @LastEditTime: 2022-05-25 19:17:45
|
||||
* @FilePath: /CasaOS/middleware/gin.go
|
||||
* @Description:
|
||||
* @Website: https://www.casaos.io
|
||||
* Copyright (c) 2022 by icewhale, All Rights Reserved.
|
||||
*/
|
||||
package middleware
|
||||
|
||||
import (
|
||||
@@ -10,20 +20,16 @@ import (
|
||||
func Cors() gin.HandlerFunc {
|
||||
return func(c *gin.Context) {
|
||||
method := c.Request.Method
|
||||
//origin := c.Request.Header.Get("Origin") //请求头部
|
||||
//if origin != "" {
|
||||
//接收客户端发送的origin (重要!)
|
||||
c.Writer.Header().Set("Access-Control-Allow-Origin", "*")
|
||||
|
||||
c.Header("Access-Control-Allow-Origin", "*")
|
||||
//服务器支持的所有跨域请求的方法
|
||||
c.Header("Access-Control-Allow-Methods", "POST, GET, OPTIONS, PUT, DELETE,UPDATE")
|
||||
//允许跨域设置可以返回其他子段,可以自定义字段
|
||||
c.Header("Access-Control-Allow-Headers", "Authorization, Content-Length, X-CSRF-Token, Token,session,Language")
|
||||
// 允许浏览器(客户端)可以解析的头部 (重要)
|
||||
c.Header("Access-Control-Expose-Headers", "Content-Length, Access-Control-Allow-Origin, Access-Control-Allow-Headers")
|
||||
//c.Writer.Header().Set("Access-Control-Allow-Headers", "Accept, Authorization, Content-Type, Content-Length, X-CSRF-Token, Token, session, Origin, Host, Connection, Accept-Encoding, Accept-Language, X-Requested-With")
|
||||
//设置缓存时间
|
||||
c.Header("Access-Control-Max-Age", "172800")
|
||||
//允许客户端传递校验信息比如 cookie (重要)
|
||||
c.Header("Access-Control-Allow-Credentials", "true")
|
||||
c.Set("content-type", "application/json")
|
||||
//}
|
||||
|
||||
@@ -1,3 +1,13 @@
|
||||
/*
|
||||
* @Author: LinkLeong link@icewhale.com
|
||||
* @Date: 2022-03-18 11:40:55
|
||||
* @LastEditors: LinkLeong
|
||||
* @LastEditTime: 2022-05-13 14:48:01
|
||||
* @FilePath: /CasaOS/model/app-analyse.go
|
||||
* @Description:
|
||||
* @Website: https://www.casaos.io
|
||||
* Copyright (c) 2022 by icewhale, All Rights Reserved.
|
||||
*/
|
||||
package model
|
||||
|
||||
type AppAnalyse struct {
|
||||
@@ -5,6 +15,7 @@ type AppAnalyse struct {
|
||||
Type string `json:"type"`
|
||||
UUId string `json:"uuid"`
|
||||
Language string `json:"language"`
|
||||
Version string `json:"version"`
|
||||
}
|
||||
|
||||
type ConnectionStatus struct {
|
||||
|
||||
@@ -1,5 +1,18 @@
|
||||
/*
|
||||
* @Author: link a624669980@163.com
|
||||
* @Date: 2022-05-16 17:37:08
|
||||
* @LastEditors: link a624669980@163.com
|
||||
* @LastEditTime: 2022-06-07 17:12:30
|
||||
* @FilePath: \CasaOS\model\category.go
|
||||
* @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
|
||||
|
||||
*/
|
||||
package model
|
||||
|
||||
// type ServerCategoryList struct {
|
||||
// Version string `json:"version"`
|
||||
// Item []CategoryList `json:"item"`
|
||||
// }
|
||||
type ServerCategoryList struct {
|
||||
Id uint `gorm:"column:id;primary_key" json:"id"`
|
||||
//CreatedAt time.Time `json:"created_at"`
|
||||
|
||||
33
model/file.go
Normal file
@@ -0,0 +1,33 @@
|
||||
/*
|
||||
* @Author: LinkLeong link@icewhale.com
|
||||
* @Date: 2022-05-20 16:27:12
|
||||
* @LastEditors: LinkLeong
|
||||
* @LastEditTime: 2022-06-09 18:18:46
|
||||
* @FilePath: /CasaOS/model/file.go
|
||||
* @Description:
|
||||
* @Website: https://www.casaos.io
|
||||
* Copyright (c) 2022 by icewhale, All Rights Reserved.
|
||||
*/
|
||||
package model
|
||||
|
||||
type FileOperate struct {
|
||||
Type string `json:"type" binding:"required"`
|
||||
Item []FileItem `json:"item" binding:"required"`
|
||||
TotalSize int64 `json:"total_size"`
|
||||
ProcessedSize int64 `json:"processed_size"`
|
||||
To string `json:"to" binding:"required"`
|
||||
Style string `json:"style"`
|
||||
Finished bool `json:"finished"`
|
||||
}
|
||||
|
||||
type FileItem struct {
|
||||
From string `json:"from" binding:"required"`
|
||||
Finished bool `json:"finished"`
|
||||
Size int64 `json:"size"`
|
||||
ProcessedSize int64 `json:"processed_size"`
|
||||
}
|
||||
|
||||
type FileUpdate struct {
|
||||
FilePath string `json:"path" binding:"required"`
|
||||
FileContent string `json:"content" binding:"required"`
|
||||
}
|
||||
@@ -104,6 +104,7 @@ func (p *PathArray) Scan(input interface{}) error {
|
||||
//}
|
||||
|
||||
type CustomizationPostData struct {
|
||||
CustomId string `json:"custom_id"`
|
||||
Origin string `json:"origin"`
|
||||
NetworkModel string `json:"network_model"`
|
||||
Index string `json:"index"`
|
||||
@@ -126,4 +127,6 @@ type CustomizationPostData struct {
|
||||
Privileged bool `json:"privileged"`
|
||||
CapAdd []string `json:"cap_add"`
|
||||
Cmd []string `json:"cmd"`
|
||||
Protocol string `json:"protocol"`
|
||||
Host string `json:"host"`
|
||||
}
|
||||
|
||||
21
model/notify/application.go
Normal file
@@ -0,0 +1,21 @@
|
||||
/*
|
||||
* @Author: LinkLeong link@icewhale.com
|
||||
* @Date: 2022-05-27 15:01:58
|
||||
* @LastEditors: LinkLeong
|
||||
* @LastEditTime: 2022-05-31 14:51:21
|
||||
* @FilePath: /CasaOS/model/notify/application.go
|
||||
* @Description:
|
||||
* @Website: https://www.casaos.io
|
||||
* Copyright (c) 2022 by icewhale, All Rights Reserved.
|
||||
*/
|
||||
package notify
|
||||
|
||||
type Application struct {
|
||||
Name string `json:"name"`
|
||||
State string `json:"state"`
|
||||
Type string `json:"type"`
|
||||
Icon string `json:"icon"`
|
||||
Message string `json:"message"`
|
||||
Finished bool `json:"finished"`
|
||||
Success bool `json:"success"`
|
||||
}
|
||||
22
model/notify/file.go
Normal file
@@ -0,0 +1,22 @@
|
||||
/*
|
||||
* @Author: LinkLeong link@icewhale.com
|
||||
* @Date: 2022-05-26 14:21:57
|
||||
* @LastEditors: LinkLeong
|
||||
* @LastEditTime: 2022-06-02 11:14:15
|
||||
* @FilePath: /CasaOS/model/notify/file.go
|
||||
* @Description:
|
||||
* @Website: https://www.casaos.io
|
||||
* Copyright (c) 2022 by icewhale, All Rights Reserved.
|
||||
*/
|
||||
package notify
|
||||
|
||||
type File struct {
|
||||
Finished bool `json:"finished"`
|
||||
ProcessedSize int64 `json:"processed_size"`
|
||||
ProcessingPath string `json:"processing_path"`
|
||||
Status string `json:"status"`
|
||||
TotalSize int64 `json:"total_size"`
|
||||
Id string `json:"id"`
|
||||
To string `json:"to"`
|
||||
Type string `json:"type"`
|
||||
}
|
||||
20
model/notify/message.go
Normal file
@@ -0,0 +1,20 @@
|
||||
/*
|
||||
* @Author: LinkLeong link@icewhale.com
|
||||
* @Date: 2022-05-26 14:39:22
|
||||
* @LastEditors: LinkLeong
|
||||
* @LastEditTime: 2022-05-26 19:08:52
|
||||
* @FilePath: /CasaOS/model/notify/message.go
|
||||
* @Description:
|
||||
* @Website: https://www.casaos.io
|
||||
* Copyright (c) 2022 by icewhale, All Rights Reserved.
|
||||
*/
|
||||
package notify
|
||||
|
||||
import (
|
||||
f "github.com/ambelovsky/gosf"
|
||||
)
|
||||
|
||||
type Message struct {
|
||||
Path string `json:"path"`
|
||||
Msg f.Message `json:"msg"`
|
||||
}
|
||||
16
model/notify/person.go
Normal file
@@ -0,0 +1,16 @@
|
||||
/*
|
||||
* @Author: LinkLeong link@icewhale.com
|
||||
* @Date: 2022-05-27 18:42:42
|
||||
* @LastEditors: LinkLeong
|
||||
* @LastEditTime: 2022-05-27 18:43:08
|
||||
* @FilePath: /CasaOS/model/notify/person.go
|
||||
* @Description:
|
||||
* @Website: https://www.casaos.io
|
||||
* Copyright (c) 2022 by icewhale, All Rights Reserved.
|
||||
*/
|
||||
package notify
|
||||
|
||||
type Person struct {
|
||||
ShareId string `json:"share_id"`
|
||||
Type string `json:"type"`
|
||||
}
|
||||
18
model/notify/result.go
Normal file
@@ -0,0 +1,18 @@
|
||||
/*
|
||||
* @Author: LinkLeong link@icewhale.com
|
||||
* @Date: 2022-05-26 14:21:11
|
||||
* @LastEditors: LinkLeong
|
||||
* @LastEditTime: 2022-05-27 11:15:59
|
||||
* @FilePath: /CasaOS/model/notify/result.go
|
||||
* @Description:
|
||||
* @Website: https://www.casaos.io
|
||||
* Copyright (c) 2022 by icewhale, All Rights Reserved.
|
||||
*/
|
||||
|
||||
package notify
|
||||
|
||||
// Notify struct for Notify
|
||||
type NotifyModel struct {
|
||||
Data interface{} `json:"data"`
|
||||
State string `json:"state"`
|
||||
}
|
||||
1
model/receive/app.go
Normal file
@@ -0,0 +1 @@
|
||||
package receive
|
||||
@@ -1,3 +1,13 @@
|
||||
/*
|
||||
* @Author: LinkLeong link@icewhale.com
|
||||
* @Date: 2022-05-13 18:15:46
|
||||
* @LastEditors: LinkLeong
|
||||
* @LastEditTime: 2022-05-30 16:43:59
|
||||
* @FilePath: /CasaOS/model/sys_common.go
|
||||
* @Description:
|
||||
* @Website: https://www.casaos.io
|
||||
* Copyright (c) 2022 by icewhale, All Rights Reserved.
|
||||
*/
|
||||
package model
|
||||
|
||||
import "time"
|
||||
@@ -18,6 +28,7 @@ type UserModel struct {
|
||||
Initialized bool
|
||||
Avatar string
|
||||
NickName string
|
||||
Public string
|
||||
}
|
||||
|
||||
//服务配置
|
||||
@@ -30,6 +41,7 @@ type ServerModel struct {
|
||||
Token string
|
||||
UDPPort string
|
||||
USBAutoMount string
|
||||
SocketPort string
|
||||
}
|
||||
|
||||
//服务配置
|
||||
|
||||
@@ -4,7 +4,7 @@ import "time"
|
||||
|
||||
type Version struct {
|
||||
Id uint `gorm:"column:id;primary_key" json:"id"`
|
||||
ChangLog string `json:"chang_log"`
|
||||
ChangeLog string `json:"change_log"`
|
||||
Version string `json:"version"`
|
||||
CreatedAt time.Time `json:"created_at"`
|
||||
UpdatedAt time.Time `json:"updated_at"`
|
||||
|
||||
@@ -1,9 +0,0 @@
|
||||
package model
|
||||
|
||||
type ZeroTierUpData struct {
|
||||
Config ZeroTierConfig `json:"config"`
|
||||
}
|
||||
|
||||
type ZeroTierConfig struct {
|
||||
Private bool `json:"private"`
|
||||
}
|
||||
@@ -10,4 +10,5 @@ type Path struct {
|
||||
Size int64 `json:"size"` //File Size
|
||||
Type string `json:"type,omitempty"`
|
||||
Label string `json:"label,omitempty"`
|
||||
Write bool `json:"write"`
|
||||
}
|
||||
|
||||
@@ -22,8 +22,7 @@ var UserInfo = &model.UserModel{}
|
||||
//用户相关
|
||||
var AppInfo = &model.APPModel{}
|
||||
|
||||
//redis相关配置
|
||||
var RedisInfo = &model.RedisModel{}
|
||||
//var RedisInfo = &model.RedisModel{}
|
||||
|
||||
//server相关
|
||||
var ServerInfo = &model.ServerModel{}
|
||||
@@ -53,7 +52,7 @@ func InitSetup(config string) {
|
||||
|
||||
mapTo("user", UserInfo)
|
||||
mapTo("app", AppInfo)
|
||||
mapTo("redis", RedisInfo)
|
||||
//mapTo("redis", RedisInfo)
|
||||
mapTo("server", ServerInfo)
|
||||
mapTo("system", SystemConfigInfo)
|
||||
mapTo("file", FileSettingInfo)
|
||||
|
||||
@@ -9,7 +9,7 @@ import (
|
||||
func GetGithubClient() *github.Client {
|
||||
ctx := context.Background()
|
||||
ts := oauth2.StaticTokenSource(
|
||||
&oauth2.Token{AccessToken: "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"},
|
||||
&oauth2.Token{AccessToken: ""},
|
||||
)
|
||||
tc := oauth2.NewClient(ctx, ts)
|
||||
client := github.NewClient(tc)
|
||||
|
||||
@@ -12,15 +12,15 @@ import (
|
||||
|
||||
var gdb *gorm.DB
|
||||
|
||||
func GetDb(projectPath string) *gorm.DB {
|
||||
func GetDb(dbPath string) *gorm.DB {
|
||||
if gdb != nil {
|
||||
return gdb
|
||||
}
|
||||
// 参考 https://github.com/go-sql-driver/mysql#dsn-data-source-name 获取详情
|
||||
//dsn := fmt.Sprintf("%v:%v@tcp(%v:%v)/%v?charset=utf8mb4&parseTime=True&loc=Local", m.User, m.PWD, m.IP, m.Port, m.DBName)
|
||||
//db, err := gorm.Open(mysql2.Open(dsn), &gorm.Config{})
|
||||
file.IsNotExistMkDir(projectPath + "/db/")
|
||||
db, err := gorm.Open(sqlite.Open(projectPath+"/db/casaOS.db"), &gorm.Config{})
|
||||
file.IsNotExistMkDir(dbPath)
|
||||
db, err := gorm.Open(sqlite.Open(dbPath+"/casaOS.db"), &gorm.Config{})
|
||||
c, _ := db.DB()
|
||||
c.SetMaxIdleConns(10)
|
||||
c.SetMaxOpenConns(100)
|
||||
@@ -31,7 +31,7 @@ func GetDb(projectPath string) *gorm.DB {
|
||||
return nil
|
||||
}
|
||||
gdb = db
|
||||
err = db.AutoMigrate(&model2.TaskDBModel{}, &model2.AppNotify{}, &model2.AppListDBModel{}, &model2.SerialDisk{}, model2.PersonDownloadDBModel{}, model2.FriendModel{})
|
||||
err = db.AutoMigrate(&model2.TaskDBModel{}, &model2.AppNotify{}, &model2.AppListDBModel{}, &model2.SerialDisk{}, model2.PersonDownloadDBModel{}, model2.FriendModel{}, model2.PersonDownRecordDBModel{}, model2.ApplicationModel{})
|
||||
if err != nil {
|
||||
fmt.Println("检查和创建数据库出错", err)
|
||||
}
|
||||
|
||||
@@ -2,9 +2,11 @@ package file
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"log"
|
||||
"mime/multipart"
|
||||
"os"
|
||||
"path"
|
||||
@@ -12,6 +14,8 @@ import (
|
||||
"path/filepath"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"github.com/mholt/archiver/v3"
|
||||
)
|
||||
|
||||
// GetSize get the file size
|
||||
@@ -182,7 +186,7 @@ func ReadFullFile(path string) []byte {
|
||||
}
|
||||
|
||||
// File copies a single file from src to dst
|
||||
func CopyFile(src, dst string) error {
|
||||
func CopyFile(src, dst, style string) error {
|
||||
var err error
|
||||
var srcfd *os.File
|
||||
var dstfd *os.File
|
||||
@@ -193,20 +197,13 @@ func CopyFile(src, dst string) error {
|
||||
if !strings.HasSuffix(dst, "/") {
|
||||
dst += "/"
|
||||
}
|
||||
dstPath := dst
|
||||
dst += lastPath
|
||||
for i := 0; Exists(dst); i++ {
|
||||
name := strings.Split(lastPath, ".")
|
||||
nameIndex := 0
|
||||
if len(name) > 2 {
|
||||
nameIndex = len(name) - 2
|
||||
if Exists(dst) {
|
||||
if style == "skip" {
|
||||
return nil
|
||||
} else {
|
||||
os.Remove(dst)
|
||||
}
|
||||
name[nameIndex] = name[nameIndex] + "(Copy)"
|
||||
dst = dstPath
|
||||
for _, v := range name {
|
||||
dst += v + "."
|
||||
}
|
||||
dst = strings.TrimSuffix(dst, ".")
|
||||
}
|
||||
|
||||
if srcfd, err = os.Open(src); err != nil {
|
||||
@@ -240,7 +237,7 @@ func GetNoDuplicateFileName(fullPath string) string {
|
||||
}
|
||||
|
||||
// Dir copies a whole directory recursively
|
||||
func CopyDir(src string, dst string) error {
|
||||
func CopyDir(src string, dst string, style string) error {
|
||||
var err error
|
||||
var fds []os.FileInfo
|
||||
var srcinfo os.FileInfo
|
||||
@@ -249,16 +246,23 @@ func CopyDir(src string, dst string) error {
|
||||
return err
|
||||
}
|
||||
if !srcinfo.IsDir() {
|
||||
if err = CopyFile(src, dst); err != nil {
|
||||
if err = CopyFile(src, dst, style); err != nil {
|
||||
fmt.Println(err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
dstPath := dst
|
||||
//dstPath := dst
|
||||
lastPath := src[strings.LastIndex(src, "/")+1:]
|
||||
dst += "/" + lastPath
|
||||
for i := 0; Exists(dst); i++ {
|
||||
dst = dstPath + "/" + lastPath + strconv.Itoa(i+1)
|
||||
// for i := 0; Exists(dst); i++ {
|
||||
// dst = dstPath + "/" + lastPath + strconv.Itoa(i+1)
|
||||
// }
|
||||
if Exists(dst) {
|
||||
if style == "skip" {
|
||||
return nil
|
||||
} else {
|
||||
os.Remove(dst)
|
||||
}
|
||||
}
|
||||
if err = os.MkdirAll(dst, srcinfo.Mode()); err != nil {
|
||||
return err
|
||||
@@ -271,11 +275,11 @@ func CopyDir(src string, dst string) error {
|
||||
dstfp := dst //path.Join(dst, fd.Name())
|
||||
|
||||
if fd.IsDir() {
|
||||
if err = CopyDir(srcfp, dstfp); err != nil {
|
||||
if err = CopyDir(srcfp, dstfp, style); err != nil {
|
||||
fmt.Println(err)
|
||||
}
|
||||
} else {
|
||||
if err = CopyFile(srcfp, dstfp); err != nil {
|
||||
if err = CopyFile(srcfp, dstfp, style); err != nil {
|
||||
fmt.Println(err)
|
||||
}
|
||||
}
|
||||
@@ -283,7 +287,6 @@ func CopyDir(src string, dst string) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
//文件写入临时目录
|
||||
func WriteToPath(data []byte, path, name string) error {
|
||||
fullPath := path
|
||||
if strings.HasSuffix(path, "/") {
|
||||
@@ -333,3 +336,149 @@ func SpliceFiles(dir, path string, length int, startPoint int) error {
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func GetCompressionAlgorithm(t string) (string, archiver.Writer, error) {
|
||||
|
||||
switch t {
|
||||
case "zip", "":
|
||||
return ".zip", archiver.NewZip(), nil
|
||||
case "tar":
|
||||
return ".tar", archiver.NewTar(), nil
|
||||
case "targz":
|
||||
return ".tar.gz", archiver.NewTarGz(), nil
|
||||
case "tarbz2":
|
||||
return ".tar.bz2", archiver.NewTarBz2(), nil
|
||||
case "tarxz":
|
||||
return ".tar.xz", archiver.NewTarXz(), nil
|
||||
case "tarlz4":
|
||||
return ".tar.lz4", archiver.NewTarLz4(), nil
|
||||
case "tarsz":
|
||||
return ".tar.sz", archiver.NewTarSz(), nil
|
||||
default:
|
||||
return "", nil, errors.New("format not implemented")
|
||||
}
|
||||
}
|
||||
func AddFile(ar archiver.Writer, path, commonPath string) error {
|
||||
|
||||
info, err := os.Stat(path)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if !info.IsDir() && !info.Mode().IsRegular() {
|
||||
return nil
|
||||
}
|
||||
|
||||
file, err := os.Open(path)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer file.Close()
|
||||
|
||||
if path != commonPath {
|
||||
filename := info.Name()
|
||||
err = ar.Write(archiver.File{
|
||||
FileInfo: archiver.FileInfo{
|
||||
FileInfo: info,
|
||||
CustomName: filename,
|
||||
},
|
||||
ReadCloser: file,
|
||||
})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
if info.IsDir() {
|
||||
names, err := file.Readdirnames(0)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
for _, name := range names {
|
||||
err = AddFile(ar, filepath.Join(path, name), commonPath)
|
||||
if err != nil {
|
||||
log.Printf("Failed to archive %v", err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
func CommonPrefix(sep byte, paths ...string) string {
|
||||
// Handle special cases.
|
||||
switch len(paths) {
|
||||
case 0:
|
||||
return ""
|
||||
case 1:
|
||||
return path.Clean(paths[0])
|
||||
}
|
||||
|
||||
// Note, we treat string as []byte, not []rune as is often
|
||||
// done in Go. (And sep as byte, not rune). This is because
|
||||
// most/all supported OS' treat paths as string of non-zero
|
||||
// bytes. A filename may be displayed as a sequence of Unicode
|
||||
// runes (typically encoded as UTF-8) but paths are
|
||||
// not required to be valid UTF-8 or in any normalized form
|
||||
// (e.g. "é" (U+00C9) and "é" (U+0065,U+0301) are different
|
||||
// file names.
|
||||
c := []byte(path.Clean(paths[0]))
|
||||
|
||||
// We add a trailing sep to handle the case where the
|
||||
// common prefix directory is included in the path list
|
||||
// (e.g. /home/user1, /home/user1/foo, /home/user1/bar).
|
||||
// path.Clean will have cleaned off trailing / separators with
|
||||
// the exception of the root directory, "/" (in which case we
|
||||
// make it "//", but this will get fixed up to "/" bellow).
|
||||
c = append(c, sep)
|
||||
|
||||
// Ignore the first path since it's already in c
|
||||
for _, v := range paths[1:] {
|
||||
// Clean up each path before testing it
|
||||
v = path.Clean(v) + string(sep)
|
||||
|
||||
// Find the first non-common byte and truncate c
|
||||
if len(v) < len(c) {
|
||||
c = c[:len(v)]
|
||||
}
|
||||
for i := 0; i < len(c); i++ {
|
||||
if v[i] != c[i] {
|
||||
c = c[:i]
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Remove trailing non-separator characters and the final separator
|
||||
for i := len(c) - 1; i >= 0; i-- {
|
||||
if c[i] == sep {
|
||||
c = c[:i]
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
return string(c)
|
||||
}
|
||||
|
||||
func GetFileOrDirSize(path string) (int64, error) {
|
||||
fileInfo, err := os.Stat(path)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
if fileInfo.IsDir() {
|
||||
return DirSizeB(path + "/")
|
||||
}
|
||||
return fileInfo.Size(), nil
|
||||
}
|
||||
|
||||
//getFileSize get file size by path(B)
|
||||
func DirSizeB(path string) (int64, error) {
|
||||
var size int64
|
||||
err := filepath.Walk(path, func(_ string, info os.FileInfo, err error) error {
|
||||
if !info.IsDir() {
|
||||
size += info.Size()
|
||||
}
|
||||
return err
|
||||
})
|
||||
return size, err
|
||||
}
|
||||
|
||||
84
pkg/utils/file/image.go
Normal file
@@ -0,0 +1,84 @@
|
||||
package file
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"io"
|
||||
"os"
|
||||
|
||||
"github.com/disintegration/imaging"
|
||||
"github.com/dsoprea/go-exif/v3"
|
||||
exifcommon "github.com/dsoprea/go-exif/v3/common"
|
||||
)
|
||||
|
||||
func GetImage(path string, width, height int) ([]byte, error) {
|
||||
if thumbnail, err := GetThumbnailByOwnerPhotos(path); err == nil {
|
||||
return thumbnail, nil
|
||||
} else {
|
||||
return GetThumbnailByWebPhoto(path, width, height)
|
||||
}
|
||||
}
|
||||
func GetThumbnailByOwnerPhotos(path string) ([]byte, error) {
|
||||
file, err := os.Open(path)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
buff := &bytes.Buffer{}
|
||||
|
||||
defer file.Close()
|
||||
offset := 0
|
||||
offsets := []int{12, 30}
|
||||
|
||||
head := make([]byte, 0xffff)
|
||||
|
||||
r := io.TeeReader(file, buff)
|
||||
_, err = r.Read(head)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
for _, offset = range offsets {
|
||||
if _, err = exif.ParseExifHeader(head[offset:]); err == nil {
|
||||
break
|
||||
}
|
||||
}
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
im, err := exifcommon.NewIfdMappingWithStandard()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
_, index, err := exif.Collect(im, exif.NewTagIndex(), head[offset:])
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
ifd := index.RootIfd.NextIfd()
|
||||
if ifd == nil {
|
||||
return nil, exif.ErrNoThumbnail
|
||||
}
|
||||
thumbnail, err := ifd.Thumbnail()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return thumbnail, nil
|
||||
}
|
||||
func GetThumbnailByWebPhoto(path string, width, height int) ([]byte, error) {
|
||||
src, err := imaging.Open(path)
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
img := imaging.Resize(src, width, 0, imaging.Lanczos)
|
||||
|
||||
f, err := imaging.FormatFromFilename(path)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
buf := bytes.Buffer{}
|
||||
imaging.Encode(&buf, img, f)
|
||||
return buf.Bytes(), nil
|
||||
}
|
||||
@@ -2,7 +2,6 @@ package httper
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
@@ -23,6 +22,42 @@ func Get(url string, head map[string]string) (response string) {
|
||||
for k, v := range head {
|
||||
req.Header.Add(k, v)
|
||||
}
|
||||
if err != nil {
|
||||
return ""
|
||||
}
|
||||
resp, err := client.Do(req)
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
//需要错误日志的处理
|
||||
//loger.Error(error)
|
||||
return ""
|
||||
//panic(error)
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
var buffer [512]byte
|
||||
result := bytes.NewBuffer(nil)
|
||||
for {
|
||||
n, err := resp.Body.Read(buffer[0:])
|
||||
result.Write(buffer[0:n])
|
||||
if err != nil && err == io.EOF {
|
||||
break
|
||||
} else if err != nil {
|
||||
//loger.Error(err)
|
||||
return ""
|
||||
// panic(err)
|
||||
}
|
||||
}
|
||||
response = result.String()
|
||||
return
|
||||
}
|
||||
|
||||
//发送GET请求
|
||||
//url:请求地址
|
||||
//response:请求返回的内容
|
||||
func PersonGet(url string) (response string) {
|
||||
client := &http.Client{Timeout: 5 * time.Second}
|
||||
req, err := http.NewRequest("GET", url, nil)
|
||||
|
||||
if err != nil {
|
||||
return ""
|
||||
}
|
||||
@@ -78,88 +113,6 @@ func Post(url string, data []byte, contentType string, head map[string]string) (
|
||||
return
|
||||
}
|
||||
|
||||
//发送POST请求
|
||||
//url:请求地址,data:POST请求提交的数据,contentType:请求体格式,如:application/json
|
||||
//content:请求放回的内容
|
||||
func ZeroTierPost(url string, data map[string]string, head map[string]string, cookies []*http.Cookie) (content string, code int) {
|
||||
b, _ := json.Marshal(data)
|
||||
req, err := http.NewRequest("POST", url, bytes.NewReader(b))
|
||||
for _, cookie := range cookies {
|
||||
req.AddCookie(cookie)
|
||||
}
|
||||
for k, v := range head {
|
||||
req.Header.Add(k, v)
|
||||
}
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
client := &http.Client{Timeout: 20 * time.Second}
|
||||
resp, error := client.Do(req)
|
||||
|
||||
if error != nil {
|
||||
panic(error)
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
code = resp.StatusCode
|
||||
result, _ := ioutil.ReadAll(resp.Body)
|
||||
content = string(result)
|
||||
return
|
||||
}
|
||||
|
||||
//发送POST请求
|
||||
//url:请求地址,data:POST请求提交的数据,contentType:请求体格式,如:application/json
|
||||
//content:请求放回的内容
|
||||
func ZeroTierPostJson(url string, data string, head map[string]string) (content string, code int) {
|
||||
var postData *bytes.Buffer
|
||||
|
||||
jsonStr := []byte(data)
|
||||
postData = bytes.NewBuffer(jsonStr)
|
||||
|
||||
req, err := http.NewRequest("POST", url, postData)
|
||||
for k, v := range head {
|
||||
req.Header.Add(k, v)
|
||||
}
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
client := &http.Client{Timeout: 20 * time.Second}
|
||||
resp, error := client.Do(req)
|
||||
|
||||
if error != nil {
|
||||
panic(error)
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
result, _ := ioutil.ReadAll(resp.Body)
|
||||
content = string(result)
|
||||
code = resp.StatusCode
|
||||
return
|
||||
}
|
||||
|
||||
func ZeroTierDelete(url string, head map[string]string) (content string, code int) {
|
||||
|
||||
req, err := http.NewRequest("DELETE", url, nil)
|
||||
for k, v := range head {
|
||||
req.Header.Add(k, v)
|
||||
}
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
client := &http.Client{Timeout: 20 * time.Second}
|
||||
resp, error := client.Do(req)
|
||||
|
||||
if error != nil {
|
||||
panic(error)
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
result, _ := ioutil.ReadAll(resp.Body)
|
||||
content = string(result)
|
||||
code = resp.StatusCode
|
||||
return
|
||||
}
|
||||
|
||||
//发送POST请求
|
||||
//url:请求地址,data:POST请求提交的数据,contentType:请求体格式,如:application/json
|
||||
//content:请求放回的内容
|
||||
|
||||
@@ -1,9 +1,10 @@
|
||||
package ip_helper
|
||||
|
||||
import (
|
||||
httper2 "github.com/IceWhaleTech/CasaOS/pkg/utils/httper"
|
||||
"net"
|
||||
"strings"
|
||||
|
||||
httper2 "github.com/IceWhaleTech/CasaOS/pkg/utils/httper"
|
||||
)
|
||||
|
||||
func IsIPv4(address string) bool {
|
||||
@@ -39,3 +40,35 @@ func GetLoclIp() string {
|
||||
}
|
||||
return "127.0.0.1"
|
||||
}
|
||||
func GetDeviceAllIP(port string) []string {
|
||||
var address []string
|
||||
addrs, err := net.InterfaceAddrs()
|
||||
if err != nil {
|
||||
return address
|
||||
}
|
||||
for _, a := range addrs {
|
||||
if ipNet, ok := a.(*net.IPNet); ok && !ipNet.IP.IsLoopback() {
|
||||
if ipNet.IP.To16() != nil {
|
||||
address = append(address, ipNet.IP.String()+":"+port)
|
||||
}
|
||||
}
|
||||
}
|
||||
return address
|
||||
}
|
||||
|
||||
func HasLocalIP(ip net.IP) bool {
|
||||
if ip.IsLoopback() {
|
||||
return true
|
||||
}
|
||||
ip.String()
|
||||
|
||||
ip4 := ip.To4()
|
||||
if ip4 == nil {
|
||||
return false
|
||||
}
|
||||
|
||||
return ip4[0] == 10 || // 10.0.0.0/8
|
||||
(ip4[0] == 172 && ip4[1] >= 16 && ip4[1] <= 31) || // 172.16.0.0/12
|
||||
(ip4[0] == 169 && ip4[1] == 254) || // 169.254.0.0/16
|
||||
(ip4[0] == 192 && ip4[1] == 168) // 192.168.0.0/16
|
||||
}
|
||||
|
||||
@@ -2,6 +2,7 @@ package ip_helper
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net"
|
||||
"testing"
|
||||
)
|
||||
|
||||
@@ -20,3 +21,7 @@ func TestGetExternalIPV6(t *testing.T) {
|
||||
func TestGetLoclIp(t *testing.T) {
|
||||
fmt.Println(GetLoclIp())
|
||||
}
|
||||
func TestHasLocalIP(t *testing.T) {
|
||||
fmt.Println("dddd")
|
||||
fmt.Println(HasLocalIP(net.ParseIP("192.168.2.10")))
|
||||
}
|
||||
|
||||
@@ -1,109 +1,92 @@
|
||||
/*
|
||||
* @Author: LinkLeong link@icewhale.com
|
||||
* @Date: 2022-06-02 15:09:38
|
||||
* @LastEditors: LinkLeong
|
||||
* @LastEditTime: 2022-06-02 17:43:38
|
||||
* @FilePath: /CasaOS/pkg/utils/loger/log.go
|
||||
* @Description:
|
||||
* @Website: https://www.casaos.io
|
||||
* Copyright (c) 2022 by icewhale, All Rights Reserved.
|
||||
*/
|
||||
package loger
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"log"
|
||||
"os"
|
||||
"path"
|
||||
"path/filepath"
|
||||
"runtime"
|
||||
|
||||
"github.com/IceWhaleTech/CasaOS/pkg/config"
|
||||
file2 "github.com/IceWhaleTech/CasaOS/pkg/utils/file"
|
||||
"go.uber.org/zap"
|
||||
"go.uber.org/zap/zapcore"
|
||||
"gopkg.in/natefinch/lumberjack.v2"
|
||||
)
|
||||
|
||||
//定义一个int的别名
|
||||
type Level int
|
||||
var loggers *zap.Logger
|
||||
|
||||
type OLog interface {
|
||||
Debug(v ...interface{})
|
||||
Info(v ...interface{})
|
||||
Warn(v ...interface{})
|
||||
Error(v ...interface{})
|
||||
Fatal(v ...interface{})
|
||||
Path() string
|
||||
}
|
||||
|
||||
type oLog struct {
|
||||
}
|
||||
|
||||
var (
|
||||
F *os.File
|
||||
DefaultPrefix = ""
|
||||
DefaultCallerDepth = 2
|
||||
logger *log.Logger
|
||||
logPrefix = ""
|
||||
levelFlags = []string{"DEBUG", "INFO", "WARN", "ERROR", "FATAL"}
|
||||
)
|
||||
|
||||
//iota在const关键字出现时将被重置为0(const内部的第一行之前),const中每新增一行常量声明将使iota计数一次(iota可理解为const语句块中的行索引)。
|
||||
const (
|
||||
DEBUG Level = iota
|
||||
INFO
|
||||
WARN
|
||||
ERROR
|
||||
FATAL
|
||||
)
|
||||
|
||||
//日志初始化
|
||||
func LogSetup() {
|
||||
var err error
|
||||
filePath := fmt.Sprintf("%s", config.AppInfo.LogSavePath)
|
||||
fileName := fmt.Sprintf("%s.%s",
|
||||
func getFileLogWriter() (writeSyncer zapcore.WriteSyncer) {
|
||||
// 使用 lumberjack 实现 log rotate
|
||||
lumberJackLogger := &lumberjack.Logger{
|
||||
Filename: filepath.Join(config.AppInfo.LogSavePath, fmt.Sprintf("%s.%s",
|
||||
config.AppInfo.LogSaveName,
|
||||
config.AppInfo.LogFileExt,
|
||||
)
|
||||
F, err = file2.MustOpen(fileName, filePath)
|
||||
if err != nil {
|
||||
log.Fatalf("logging.Setup err: %v", err)
|
||||
)),
|
||||
MaxSize: 100,
|
||||
MaxBackups: 60,
|
||||
MaxAge: 1,
|
||||
Compress: true,
|
||||
}
|
||||
|
||||
logger = log.New(F, DefaultPrefix, log.LstdFlags)
|
||||
|
||||
return zapcore.AddSync(lumberJackLogger)
|
||||
}
|
||||
func (o *oLog) Path() string {
|
||||
filePath := fmt.Sprintf("%s", config.AppInfo.LogSavePath)
|
||||
fileName := fmt.Sprintf("%s.%s",
|
||||
config.AppInfo.LogSaveName,
|
||||
config.AppInfo.LogFileExt,
|
||||
|
||||
func LogInit() {
|
||||
encoderConfig := zap.NewProductionEncoderConfig()
|
||||
encoderConfig.EncodeTime = zapcore.EpochTimeEncoder
|
||||
encoder := zapcore.NewJSONEncoder(encoderConfig)
|
||||
fileWriteSyncer := getFileLogWriter()
|
||||
core := zapcore.NewTee(
|
||||
zapcore.NewCore(encoder, zapcore.AddSync(os.Stdout), zapcore.DebugLevel),
|
||||
zapcore.NewCore(encoder, fileWriteSyncer, zapcore.DebugLevel),
|
||||
)
|
||||
return filePath + fileName
|
||||
}
|
||||
func (o *oLog) Debug(v ...interface{}) {
|
||||
setPrefix(DEBUG)
|
||||
logger.Println(v)
|
||||
loggers = zap.New(core)
|
||||
|
||||
}
|
||||
|
||||
func (o *oLog) Info(v ...interface{}) {
|
||||
setPrefix(INFO)
|
||||
logger.Println(v)
|
||||
func Info(message string, fields ...zap.Field) {
|
||||
callerFields := getCallerInfoForLog()
|
||||
fields = append(fields, callerFields...)
|
||||
loggers.Info(message, fields...)
|
||||
}
|
||||
|
||||
func (o *oLog) Warn(v ...interface{}) {
|
||||
setPrefix(WARN)
|
||||
logger.Println(v)
|
||||
func Debug(message string, fields ...zap.Field) {
|
||||
callerFields := getCallerInfoForLog()
|
||||
fields = append(fields, callerFields...)
|
||||
loggers.Debug(message, fields...)
|
||||
}
|
||||
|
||||
func (o *oLog) Error(v ...interface{}) {
|
||||
setPrefix(ERROR)
|
||||
logger.Println(v)
|
||||
func Error(message string, fields ...zap.Field) {
|
||||
callerFields := getCallerInfoForLog()
|
||||
fields = append(fields, callerFields...)
|
||||
loggers.Error(message, fields...)
|
||||
}
|
||||
|
||||
func (o *oLog) Fatal(v ...interface{}) {
|
||||
setPrefix(FATAL)
|
||||
logger.Println(v)
|
||||
func Warn(message string, fields ...zap.Field) {
|
||||
callerFields := getCallerInfoForLog()
|
||||
fields = append(fields, callerFields...)
|
||||
loggers.Warn(message, fields...)
|
||||
}
|
||||
|
||||
func setPrefix(level Level) {
|
||||
_, file, line, ok := runtime.Caller(DefaultCallerDepth)
|
||||
if ok {
|
||||
logPrefix = fmt.Sprintf("[%s][%s:%d]", levelFlags[level], filepath.Base(file), line)
|
||||
} else {
|
||||
logPrefix = fmt.Sprintf("[%s]", levelFlags[level])
|
||||
func getCallerInfoForLog() (callerFields []zap.Field) {
|
||||
|
||||
pc, file, line, ok := runtime.Caller(2) // 回溯两层,拿到写日志的调用方的函数信息
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
funcName := runtime.FuncForPC(pc).Name()
|
||||
funcName = path.Base(funcName) //Base函数返回路径的最后一个元素,只保留函数名
|
||||
|
||||
logger.SetPrefix(logPrefix)
|
||||
}
|
||||
|
||||
func NewOLoger() OLog {
|
||||
return &oLog{}
|
||||
callerFields = append(callerFields, zap.String("func", funcName), zap.String("file", file), zap.Int("line", line))
|
||||
return
|
||||
}
|
||||
|
||||
109
pkg/utils/loger/log_old.go
Normal file
@@ -0,0 +1,109 @@
|
||||
package loger
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"log"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"runtime"
|
||||
|
||||
"github.com/IceWhaleTech/CasaOS/pkg/config"
|
||||
file2 "github.com/IceWhaleTech/CasaOS/pkg/utils/file"
|
||||
)
|
||||
|
||||
//定义一个int的别名
|
||||
type Level int
|
||||
|
||||
type OLog interface {
|
||||
Debug(v ...interface{})
|
||||
Info(v ...interface{})
|
||||
Warn(v ...interface{})
|
||||
Error(v ...interface{})
|
||||
Fatal(v ...interface{})
|
||||
Path() string
|
||||
}
|
||||
|
||||
type oLog struct {
|
||||
}
|
||||
|
||||
var (
|
||||
F *os.File
|
||||
DefaultPrefix = ""
|
||||
DefaultCallerDepth = 2
|
||||
logger *log.Logger
|
||||
logPrefix = ""
|
||||
levelFlags = []string{"DEBUG", "INFO", "WARN", "ERROR", "FATAL"}
|
||||
)
|
||||
|
||||
//iota在const关键字出现时将被重置为0(const内部的第一行之前),const中每新增一行常量声明将使iota计数一次(iota可理解为const语句块中的行索引)。
|
||||
const (
|
||||
DEBUG Level = iota
|
||||
INFO
|
||||
WARN
|
||||
ERROR
|
||||
FATAL
|
||||
)
|
||||
|
||||
//日志初始化
|
||||
func LogSetupOld() {
|
||||
var err error
|
||||
filePath := fmt.Sprintf("%s", config.AppInfo.LogSavePath)
|
||||
fileName := fmt.Sprintf("%s.%s",
|
||||
config.AppInfo.LogSaveName,
|
||||
config.AppInfo.LogFileExt,
|
||||
)
|
||||
F, err = file2.MustOpen(fileName, filePath)
|
||||
if err != nil {
|
||||
log.Fatalf("logging.Setup err: %v", err)
|
||||
}
|
||||
|
||||
logger = log.New(F, DefaultPrefix, log.LstdFlags)
|
||||
|
||||
}
|
||||
func (o *oLog) Path() string {
|
||||
filePath := fmt.Sprintf("%s", config.AppInfo.LogSavePath)
|
||||
fileName := fmt.Sprintf("%s.%s",
|
||||
config.AppInfo.LogSaveName,
|
||||
config.AppInfo.LogFileExt,
|
||||
)
|
||||
return filePath + fileName
|
||||
}
|
||||
func (o *oLog) Debug(v ...interface{}) {
|
||||
setPrefix(DEBUG)
|
||||
logger.Println(v)
|
||||
}
|
||||
|
||||
func (o *oLog) Info(v ...interface{}) {
|
||||
setPrefix(INFO)
|
||||
logger.Println(v)
|
||||
}
|
||||
|
||||
func (o *oLog) Warn(v ...interface{}) {
|
||||
setPrefix(WARN)
|
||||
logger.Println(v)
|
||||
}
|
||||
|
||||
func (o *oLog) Error(v ...interface{}) {
|
||||
setPrefix(ERROR)
|
||||
logger.Println(v)
|
||||
}
|
||||
|
||||
func (o *oLog) Fatal(v ...interface{}) {
|
||||
setPrefix(FATAL)
|
||||
logger.Println(v)
|
||||
}
|
||||
|
||||
func setPrefix(level Level) {
|
||||
_, file, line, ok := runtime.Caller(DefaultCallerDepth)
|
||||
if ok {
|
||||
logPrefix = fmt.Sprintf("[%s][%s:%d]", levelFlags[level], filepath.Base(file), line)
|
||||
} else {
|
||||
logPrefix = fmt.Sprintf("[%s]", levelFlags[level])
|
||||
}
|
||||
|
||||
logger.SetPrefix(logPrefix)
|
||||
}
|
||||
|
||||
func NewOLoger() OLog {
|
||||
return &oLog{}
|
||||
}
|
||||
30
pkg/utils/network_detection.go
Normal file
@@ -0,0 +1,30 @@
|
||||
/*
|
||||
* @Author: LinkLeong a624669980@163.com
|
||||
* @Date: 2022-05-08 14:58:46
|
||||
* @LastEditors: LinkLeong a624669980@163.com
|
||||
* @LastEditTime: 2022-05-09 13:42:26
|
||||
* @FilePath: /CasaOS/pkg/utils/network_detection.go
|
||||
* @Description:
|
||||
*
|
||||
* Copyright (c) 2022 by LinkLeong a624669980@163.com, All Rights Reserved.
|
||||
*/
|
||||
package utils
|
||||
|
||||
import natType "github.com/Curtis-Milo/nat-type-identifier-go"
|
||||
|
||||
/**
|
||||
* @description:
|
||||
* @param {chanstring} data
|
||||
* @param {string} url
|
||||
* @return {*}
|
||||
*/
|
||||
func GetNetWorkTypeDetection(data chan string, url string) {
|
||||
// fmt.Println("url:", url)
|
||||
// httper.Get(url, nil)
|
||||
// aaa <- url
|
||||
result, err := natType.GetDeterminedNatType(true, 5, url)
|
||||
if err == nil {
|
||||
data <- result
|
||||
}
|
||||
|
||||
}
|
||||
29
pkg/utils/network_detection_test.go
Normal file
@@ -0,0 +1,29 @@
|
||||
/*
|
||||
* @Author: LinkLeong a624669980@163.com
|
||||
* @Date: 2022-05-08 15:07:31
|
||||
* @LastEditors: LinkLeong a624669980@163.com
|
||||
* @LastEditTime: 2022-05-09 11:43:30
|
||||
* @FilePath: /CasaOS/pkg/utils/network_detection_test.go
|
||||
* @Description:
|
||||
*
|
||||
* Copyright (c) 2022 by LinkLeong a624669980@163.com, All Rights Reserved.
|
||||
*/
|
||||
|
||||
package utils
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestGetResultTest(t *testing.T) {
|
||||
list := []string{"https://www.google.com", "https://www.bing.com", "https://www.baidu.com"}
|
||||
data := make(chan string)
|
||||
//data <- "init"
|
||||
for _, v := range list {
|
||||
go GetNetWorkTypeDetection(data, v)
|
||||
}
|
||||
result := <-data
|
||||
close(data)
|
||||
fmt.Println(result)
|
||||
}
|
||||
@@ -17,6 +17,7 @@ const (
|
||||
FILE_ALREADY_EXISTS = 20002
|
||||
FILE_OR_DIR_EXISTS = 20003
|
||||
PORT_IS_OCCUPIED = 20004
|
||||
COMMAND_ERROR_INVALID_OPERATION = 20005
|
||||
|
||||
//zerotier
|
||||
GET_TOKEN_ERROR = 30001
|
||||
@@ -32,12 +33,14 @@ const (
|
||||
UNINSTALL_APP_ERROR = 50001
|
||||
PULL_IMAGE_ERROR = 50002
|
||||
DEVICE_NOT_EXIST = 50003
|
||||
ERROR_APP_NAME_EXIST = 50004
|
||||
|
||||
//file
|
||||
FILE_DOES_NOT_EXIST = 60001
|
||||
FILE_READ_ERROR = 60002
|
||||
FILE_DELETE_ERROR = 60003
|
||||
DIR_NOT_EXISTS = 60004
|
||||
SOURCE_DES_SAME = 60005
|
||||
|
||||
//shortcuts
|
||||
SHORTCUTS_URL_ERROR = 70001
|
||||
@@ -76,6 +79,7 @@ var MsgFlags = map[int]string{
|
||||
UNINSTALL_APP_ERROR: "Error uninstalling app",
|
||||
PULL_IMAGE_ERROR: "Error pulling image",
|
||||
DEVICE_NOT_EXIST: "Device does not exist",
|
||||
ERROR_APP_NAME_EXIST: "App name already exists",
|
||||
|
||||
//disk
|
||||
NAME_NOT_AVAILABLE: "Name not available",
|
||||
@@ -85,6 +89,7 @@ var MsgFlags = map[int]string{
|
||||
FORMAT_ERROR: "Formatting failed, please check if the directory is occupied",
|
||||
|
||||
//
|
||||
SOURCE_DES_SAME: "Source and destination cannot be the same.",
|
||||
FILE_DOES_NOT_EXIST: "File does not exist",
|
||||
|
||||
DIR_NOT_EXISTS: "Directory does not exist",
|
||||
@@ -99,6 +104,7 @@ var MsgFlags = map[int]string{
|
||||
PERSON_EXIST_FRIEND: "Friend already exist",
|
||||
PERSON_NOT_EXIST_USER: "User does not exist",
|
||||
PERSON_MYSELF: "You can not add yourself",
|
||||
COMMAND_ERROR_INVALID_OPERATION: "invalid operation",
|
||||
}
|
||||
|
||||
//获取错误信息
|
||||
|
||||
@@ -1,73 +0,0 @@
|
||||
package sort
|
||||
|
||||
import (
|
||||
"github.com/IceWhaleTech/CasaOS/model"
|
||||
"sort"
|
||||
)
|
||||
|
||||
// 数据集类型, 与上一篇排序文章(多字段单独排序)比较, less字段的数据类型不再是 func(p1, p2 *Change) bool
|
||||
// 而是 []func(p1, p2 *Change) bool 因为在第一个比较的值相等的情况下, 还要比较第二个值, 所以这里需要多个比较函数
|
||||
type devSorter struct {
|
||||
dev []model.Devices
|
||||
less []lessFuncDev
|
||||
}
|
||||
|
||||
// sort接口方法之一(Less)
|
||||
type lessFuncDev func(p1, p2 *model.Devices) bool
|
||||
|
||||
// Sort 函数有两个作用
|
||||
// 第一, 将参数(实际的数据集)赋值给ms对象
|
||||
// 第二, 调用内置sort函数进行排序操作
|
||||
func (ms *devSorter) Sort(dev []model.Devices) {
|
||||
ms.dev = dev
|
||||
sort.Sort(ms)
|
||||
}
|
||||
|
||||
// OrderedBy 函数的作用是返回一个multiSorter实例, 并将所有的实际排序函数赋值给实例的less字段,
|
||||
// 上面已经为multiSorter结构体定义了Sort方法, 所以该函数的返回值可以直接调用Sort方法进行排序
|
||||
// 该函数中, 为multiSorter结构体中的less字段赋值, Sort方法中又将实际数据集传入, 赋值给multiSorter的ports字段
|
||||
// 一个函数, 一个方法调用过后, multiSorter实例中两个字段就已经全部被正确赋值, 可以调用系统sort函数进行排序
|
||||
// 该函数也可看作是一个工厂方法, 用来生成less字段已经被赋值的multiSorter实例
|
||||
func DevSort(less ...lessFuncDev) *devSorter {
|
||||
return &devSorter{
|
||||
less: less,
|
||||
}
|
||||
}
|
||||
|
||||
// Len 为sort接口方法之一
|
||||
func (ms *devSorter) Len() int {
|
||||
return len(ms.dev)
|
||||
}
|
||||
|
||||
// Swap 为sort接口方法之一
|
||||
func (ms *devSorter) Swap(i, j int) {
|
||||
ms.dev[i], ms.dev[j] = ms.dev[j], ms.dev[i]
|
||||
}
|
||||
|
||||
// Less 为sort接口方法之一
|
||||
func (ms *devSorter) Less(i, j int) bool {
|
||||
temp := ms.dev
|
||||
p, q := &temp[i], &temp[j]
|
||||
// Try all but the last comparison.
|
||||
var k int
|
||||
// 由于可能有多个需要排序的字段, 也就对应了多个less函数, 当第一个字段的值相等时,
|
||||
// 需要依次尝试比对后续其他字段的值得大小, 所以这里需要获取比较函数的长度, 以便遍历比较
|
||||
for k = 0; k < len(ms.less)-1; k++ {
|
||||
// 提取比较函数, 将函数赋值到新的变量中以便调用
|
||||
less := ms.less[k]
|
||||
switch {
|
||||
case less(p, q):
|
||||
// 如果 p < q, 返回值为true, 不存在两个值相等需要比较后续字段的情况, 所以这里直接返回
|
||||
// 如果 p > q, 返回值为false, 则调到下一个case中处理
|
||||
return true
|
||||
case less(q, p):
|
||||
// 如果 p > q, 返回值为false, 不存在两个值相等需要比较后续字段的情况, 所以这里直接返回
|
||||
return false
|
||||
}
|
||||
// 如果代码走到这里, 说明ms.less[k]函数比较后 p == q; 重新开始下一次循环, 更换到下一个比较函数处理
|
||||
continue
|
||||
}
|
||||
// 如果代码走到这里, 说明所有的比较函数执行过后, 所有比较的值都相等
|
||||
// 直接返回最后一次的比较结果数据即可
|
||||
return ms.less[k](p, q)
|
||||
}
|
||||
@@ -1,74 +0,0 @@
|
||||
package sort
|
||||
|
||||
import (
|
||||
"sort"
|
||||
|
||||
"github.com/IceWhaleTech/CasaOS/model"
|
||||
)
|
||||
|
||||
// 数据集类型, 与上一篇排序文章(多字段单独排序)比较, less字段的数据类型不再是 func(p1, p2 *Change) bool
|
||||
// 而是 []func(p1, p2 *Change) bool 因为在第一个比较的值相等的情况下, 还要比较第二个值, 所以这里需要多个比较函数
|
||||
type evnSorter struct {
|
||||
evn []model.Envs
|
||||
less []lessFuncEnv
|
||||
}
|
||||
|
||||
// sort接口方法之一(Less)
|
||||
type lessFuncEnv func(p1, p2 *model.Envs) bool
|
||||
|
||||
// Sort 函数有两个作用
|
||||
// 第一, 将参数(实际的数据集)赋值给ms对象
|
||||
// 第二, 调用内置sort函数进行排序操作
|
||||
func (ms *evnSorter) Sort(env []model.Envs) {
|
||||
ms.evn = env
|
||||
sort.Sort(ms)
|
||||
}
|
||||
|
||||
// OrderedBy 函数的作用是返回一个multiSorter实例, 并将所有的实际排序函数赋值给实例的less字段,
|
||||
// 上面已经为multiSorter结构体定义了Sort方法, 所以该函数的返回值可以直接调用Sort方法进行排序
|
||||
// 该函数中, 为multiSorter结构体中的less字段赋值, Sort方法中又将实际数据集传入, 赋值给multiSorter的ports字段
|
||||
// 一个函数, 一个方法调用过后, multiSorter实例中两个字段就已经全部被正确赋值, 可以调用系统sort函数进行排序
|
||||
// 该函数也可看作是一个工厂方法, 用来生成less字段已经被赋值的multiSorter实例
|
||||
func EnvSort(less ...lessFuncEnv) *evnSorter {
|
||||
return &evnSorter{
|
||||
less: less,
|
||||
}
|
||||
}
|
||||
|
||||
// Len 为sort接口方法之一
|
||||
func (ms *evnSorter) Len() int {
|
||||
return len(ms.evn)
|
||||
}
|
||||
|
||||
// Swap 为sort接口方法之一
|
||||
func (ms *evnSorter) Swap(i, j int) {
|
||||
ms.evn[i], ms.evn[j] = ms.evn[j], ms.evn[i]
|
||||
}
|
||||
|
||||
// Less 为sort接口方法之一
|
||||
func (ms *evnSorter) Less(i, j int) bool {
|
||||
temp := ms.evn
|
||||
p, q := &temp[i], &temp[j]
|
||||
// Try all but the last comparison.
|
||||
var k int
|
||||
// 由于可能有多个需要排序的字段, 也就对应了多个less函数, 当第一个字段的值相等时,
|
||||
// 需要依次尝试比对后续其他字段的值得大小, 所以这里需要获取比较函数的长度, 以便遍历比较
|
||||
for k = 0; k < len(ms.less)-1; k++ {
|
||||
// 提取比较函数, 将函数赋值到新的变量中以便调用
|
||||
less := ms.less[k]
|
||||
switch {
|
||||
case less(p, q):
|
||||
// 如果 p < q, 返回值为true, 不存在两个值相等需要比较后续字段的情况, 所以这里直接返回
|
||||
// 如果 p > q, 返回值为false, 则调到下一个case中处理
|
||||
return true
|
||||
case less(q, p):
|
||||
// 如果 p > q, 返回值为false, 不存在两个值相等需要比较后续字段的情况, 所以这里直接返回
|
||||
return false
|
||||
}
|
||||
// 如果代码走到这里, 说明ms.less[k]函数比较后 p == q; 重新开始下一次循环, 更换到下一个比较函数处理
|
||||
continue
|
||||
}
|
||||
// 如果代码走到这里, 说明所有的比较函数执行过后, 所有比较的值都相等
|
||||
// 直接返回最后一次的比较结果数据即可
|
||||
return ms.less[k](p, q)
|
||||
}
|
||||
@@ -1,73 +0,0 @@
|
||||
package sort
|
||||
|
||||
import (
|
||||
"github.com/IceWhaleTech/CasaOS/model"
|
||||
"sort"
|
||||
)
|
||||
|
||||
// 数据集类型, 与上一篇排序文章(多字段单独排序)比较, less字段的数据类型不再是 func(p1, p2 *Change) bool
|
||||
// 而是 []func(p1, p2 *Change) bool 因为在第一个比较的值相等的情况下, 还要比较第二个值, 所以这里需要多个比较函数
|
||||
type multiSorter struct {
|
||||
ports []model.Ports
|
||||
less []lessFunc
|
||||
}
|
||||
|
||||
// sort接口方法之一(Less)
|
||||
type lessFunc func(p1, p2 *model.Ports) bool
|
||||
|
||||
// Sort 函数有两个作用
|
||||
// 第一, 将参数(实际的数据集)赋值给ms对象
|
||||
// 第二, 调用内置sort函数进行排序操作
|
||||
func (ms *multiSorter) Sort(ports []model.Ports) {
|
||||
ms.ports = ports
|
||||
sort.Sort(ms)
|
||||
}
|
||||
|
||||
// OrderedBy 函数的作用是返回一个multiSorter实例, 并将所有的实际排序函数赋值给实例的less字段,
|
||||
// 上面已经为multiSorter结构体定义了Sort方法, 所以该函数的返回值可以直接调用Sort方法进行排序
|
||||
// 该函数中, 为multiSorter结构体中的less字段赋值, Sort方法中又将实际数据集传入, 赋值给multiSorter的ports字段
|
||||
// 一个函数, 一个方法调用过后, multiSorter实例中两个字段就已经全部被正确赋值, 可以调用系统sort函数进行排序
|
||||
// 该函数也可看作是一个工厂方法, 用来生成less字段已经被赋值的multiSorter实例
|
||||
func PortsSort(less ...lessFunc) *multiSorter {
|
||||
return &multiSorter{
|
||||
less: less,
|
||||
}
|
||||
}
|
||||
|
||||
// Len 为sort接口方法之一
|
||||
func (ms *multiSorter) Len() int {
|
||||
return len(ms.ports)
|
||||
}
|
||||
|
||||
// Swap 为sort接口方法之一
|
||||
func (ms *multiSorter) Swap(i, j int) {
|
||||
ms.ports[i], ms.ports[j] = ms.ports[j], ms.ports[i]
|
||||
}
|
||||
|
||||
// Less 为sort接口方法之一
|
||||
func (ms *multiSorter) Less(i, j int) bool {
|
||||
port := ms.ports
|
||||
p, q := &port[i], &port[j]
|
||||
// Try all but the last comparison.
|
||||
var k int
|
||||
// 由于可能有多个需要排序的字段, 也就对应了多个less函数, 当第一个字段的值相等时,
|
||||
// 需要依次尝试比对后续其他字段的值得大小, 所以这里需要获取比较函数的长度, 以便遍历比较
|
||||
for k = 0; k < len(ms.less)-1; k++ {
|
||||
// 提取比较函数, 将函数赋值到新的变量中以便调用
|
||||
less := ms.less[k]
|
||||
switch {
|
||||
case less(p, q):
|
||||
// 如果 p < q, 返回值为true, 不存在两个值相等需要比较后续字段的情况, 所以这里直接返回
|
||||
// 如果 p > q, 返回值为false, 则调到下一个case中处理
|
||||
return true
|
||||
case less(q, p):
|
||||
// 如果 p > q, 返回值为false, 不存在两个值相等需要比较后续字段的情况, 所以这里直接返回
|
||||
return false
|
||||
}
|
||||
// 如果代码走到这里, 说明ms.less[k]函数比较后 p == q; 重新开始下一次循环, 更换到下一个比较函数处理
|
||||
continue
|
||||
}
|
||||
// 如果代码走到这里, 说明所有的比较函数执行过后, 所有比较的值都相等
|
||||
// 直接返回最后一次的比较结果数据即可
|
||||
return ms.less[k](p, q)
|
||||
}
|
||||
@@ -1,73 +0,0 @@
|
||||
package sort
|
||||
|
||||
import (
|
||||
"github.com/IceWhaleTech/CasaOS/model"
|
||||
"sort"
|
||||
)
|
||||
|
||||
// 数据集类型, 与上一篇排序文章(多字段单独排序)比较, less字段的数据类型不再是 func(p1, p2 *Change) bool
|
||||
// 而是 []func(p1, p2 *Change) bool 因为在第一个比较的值相等的情况下, 还要比较第二个值, 所以这里需要多个比较函数
|
||||
type volSorter struct {
|
||||
vol []model.Volume
|
||||
less []lessFuncVol
|
||||
}
|
||||
|
||||
// sort接口方法之一(Less)
|
||||
type lessFuncVol func(p1, p2 *model.Volume) bool
|
||||
|
||||
// Sort 函数有两个作用
|
||||
// 第一, 将参数(实际的数据集)赋值给ms对象
|
||||
// 第二, 调用内置sort函数进行排序操作
|
||||
func (ms *volSorter) Sort(vol []model.Volume) {
|
||||
ms.vol = vol
|
||||
sort.Sort(ms)
|
||||
}
|
||||
|
||||
// OrderedBy 函数的作用是返回一个multiSorter实例, 并将所有的实际排序函数赋值给实例的less字段,
|
||||
// 上面已经为multiSorter结构体定义了Sort方法, 所以该函数的返回值可以直接调用Sort方法进行排序
|
||||
// 该函数中, 为multiSorter结构体中的less字段赋值, Sort方法中又将实际数据集传入, 赋值给multiSorter的ports字段
|
||||
// 一个函数, 一个方法调用过后, multiSorter实例中两个字段就已经全部被正确赋值, 可以调用系统sort函数进行排序
|
||||
// 该函数也可看作是一个工厂方法, 用来生成less字段已经被赋值的multiSorter实例
|
||||
func VolSort(less ...lessFuncVol) *volSorter {
|
||||
return &volSorter{
|
||||
less: less,
|
||||
}
|
||||
}
|
||||
|
||||
// Len 为sort接口方法之一
|
||||
func (ms *volSorter) Len() int {
|
||||
return len(ms.vol)
|
||||
}
|
||||
|
||||
// Swap 为sort接口方法之一
|
||||
func (ms *volSorter) Swap(i, j int) {
|
||||
ms.vol[i], ms.vol[j] = ms.vol[j], ms.vol[i]
|
||||
}
|
||||
|
||||
// Less 为sort接口方法之一
|
||||
func (ms *volSorter) Less(i, j int) bool {
|
||||
temp := ms.vol
|
||||
p, q := &temp[i], &temp[j]
|
||||
// Try all but the last comparison.
|
||||
var k int
|
||||
// 由于可能有多个需要排序的字段, 也就对应了多个less函数, 当第一个字段的值相等时,
|
||||
// 需要依次尝试比对后续其他字段的值得大小, 所以这里需要获取比较函数的长度, 以便遍历比较
|
||||
for k = 0; k < len(ms.less)-1; k++ {
|
||||
// 提取比较函数, 将函数赋值到新的变量中以便调用
|
||||
less := ms.less[k]
|
||||
switch {
|
||||
case less(p, q):
|
||||
// 如果 p < q, 返回值为true, 不存在两个值相等需要比较后续字段的情况, 所以这里直接返回
|
||||
// 如果 p > q, 返回值为false, 则调到下一个case中处理
|
||||
return true
|
||||
case less(q, p):
|
||||
// 如果 p > q, 返回值为false, 不存在两个值相等需要比较后续字段的情况, 所以这里直接返回
|
||||
return false
|
||||
}
|
||||
// 如果代码走到这里, 说明ms.less[k]函数比较后 p == q; 重新开始下一次循环, 更换到下一个比较函数处理
|
||||
continue
|
||||
}
|
||||
// 如果代码走到这里, 说明所有的比较函数执行过后, 所有比较的值都相等
|
||||
// 直接返回最后一次的比较结果数据即可
|
||||
return ms.less[k](p, q)
|
||||
}
|
||||
@@ -1,3 +1,13 @@
|
||||
/*
|
||||
* @Author: LinkLeong link@icewhale.com
|
||||
* @Date: 2022-05-13 18:15:46
|
||||
* @LastEditors: LinkLeong
|
||||
* @LastEditTime: 2022-06-02 17:41:47
|
||||
* @FilePath: /CasaOS/pkg/utils/version/version.go
|
||||
* @Description:
|
||||
* @Website: https://www.casaos.io
|
||||
* Copyright (c) 2022 by icewhale, All Rights Reserved.
|
||||
*/
|
||||
package version
|
||||
|
||||
import (
|
||||
@@ -32,6 +42,8 @@ func IsNeedUpdate() (bool, model.Version) {
|
||||
b, _ := strconv.Atoi(v2[i])
|
||||
if a > b {
|
||||
return true, version
|
||||
} else {
|
||||
return false, version
|
||||
}
|
||||
}
|
||||
return false, version
|
||||
|
||||
131
route/init.go
@@ -1,17 +1,17 @@
|
||||
package route
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"encoding/xml"
|
||||
"fmt"
|
||||
"path/filepath"
|
||||
"runtime"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/IceWhaleTech/CasaOS/model"
|
||||
"github.com/IceWhaleTech/CasaOS/model/system_app"
|
||||
"github.com/IceWhaleTech/CasaOS/pkg/config"
|
||||
"github.com/IceWhaleTech/CasaOS/pkg/docker"
|
||||
"github.com/IceWhaleTech/CasaOS/pkg/utils/command"
|
||||
"github.com/IceWhaleTech/CasaOS/pkg/utils/env_helper"
|
||||
"github.com/IceWhaleTech/CasaOS/pkg/utils/file"
|
||||
@@ -27,6 +27,9 @@ func InitFunction() {
|
||||
CheckSerialDiskMount()
|
||||
|
||||
CheckToken2_11()
|
||||
ImportApplications()
|
||||
ChangeAPIUrl()
|
||||
InitSystemApplication()
|
||||
|
||||
}
|
||||
|
||||
@@ -77,14 +80,12 @@ func installSyncthing(appId string) {
|
||||
appInfo.Tip = env_helper.ReplaceStringDefaultENV(appInfo.Tip)
|
||||
}
|
||||
|
||||
appInfo.MaxMemory = service.MyService.ZiMa().GetMemInfo().Total >> 20
|
||||
appInfo.MaxMemory = service.MyService.System().GetMemInfo().Total >> 20
|
||||
|
||||
id := uuid.NewV4().String()
|
||||
|
||||
installLog := model2.AppNotify{}
|
||||
|
||||
// step:下载镜像
|
||||
err := service.MyService.Docker().DockerPullImage(dockerImage+":"+dockerImageVersion, installLog)
|
||||
err := service.MyService.Docker().DockerPullImage(dockerImage+":"+dockerImageVersion, "", "")
|
||||
if err != nil {
|
||||
//pull image error
|
||||
fmt.Println("pull image error", err, dockerImage, dockerImageVersion)
|
||||
@@ -102,8 +103,9 @@ func installSyncthing(appId string) {
|
||||
m.Ports = appInfo.Ports
|
||||
m.Restart = "always"
|
||||
m.Volumes = appInfo.Volumes
|
||||
|
||||
containerId, err := service.MyService.Docker().DockerContainerCreate(dockerImage+":"+dockerImageVersion, id, m, appInfo.NetworkModel)
|
||||
m.Label = id
|
||||
m.CustomId = id
|
||||
containerId, err := service.MyService.Docker().DockerContainerCreate(dockerImage+":"+dockerImageVersion, m, appInfo.NetworkModel)
|
||||
if err != nil {
|
||||
fmt.Println("container create error", err)
|
||||
// create container error
|
||||
@@ -111,83 +113,45 @@ func installSyncthing(appId string) {
|
||||
}
|
||||
|
||||
//step:start container
|
||||
err = service.MyService.Docker().DockerContainerStart(id)
|
||||
err = service.MyService.Docker().DockerContainerStart(containerId)
|
||||
if err != nil {
|
||||
//start container error
|
||||
return
|
||||
}
|
||||
|
||||
portsStr, _ := json.Marshal(appInfo.Ports)
|
||||
envsStr, _ := json.Marshal(appInfo.Envs)
|
||||
volumesStr, _ := json.Marshal(appInfo.Volumes)
|
||||
devicesStr, _ := json.Marshal(appInfo.Devices)
|
||||
//step: 保存数据到数据库
|
||||
md := model2.AppListDBModel{
|
||||
CustomId: id,
|
||||
Title: appInfo.Title,
|
||||
//ScreenshotLink: appInfo.ScreenshotLink,
|
||||
Slogan: appInfo.Tagline,
|
||||
Description: appInfo.Description,
|
||||
//Tags: appInfo.Tags,
|
||||
Icon: appInfo.Icon,
|
||||
Version: dockerImageVersion,
|
||||
ContainerId: containerId,
|
||||
Image: dockerImage,
|
||||
Index: appInfo.Index,
|
||||
PortMap: appInfo.PortMap,
|
||||
Label: appInfo.Title,
|
||||
EnableUPNP: false,
|
||||
Ports: string(portsStr),
|
||||
Envs: string(envsStr),
|
||||
Volumes: string(volumesStr),
|
||||
Position: true,
|
||||
NetModel: appInfo.NetworkModel,
|
||||
Restart: m.Restart,
|
||||
CpuShares: 50,
|
||||
Memory: int64(appInfo.MaxMemory),
|
||||
Devices: string(devicesStr),
|
||||
Origin: m.Origin,
|
||||
CreatedAt: strconv.FormatInt(time.Now().Unix(), 10),
|
||||
UpdatedAt: strconv.FormatInt(time.Now().Unix(), 10),
|
||||
}
|
||||
service.MyService.App().SaveContainer(md)
|
||||
|
||||
checkSystemApp()
|
||||
}
|
||||
|
||||
// check if the system application is installed
|
||||
func checkSystemApp() {
|
||||
list := service.MyService.App().GetSystemAppList()
|
||||
for _, v := range *list {
|
||||
if v.Image == "linuxserver/syncthing" {
|
||||
for _, v := range list {
|
||||
info, err := service.MyService.Docker().DockerContainerInfo(v.ID)
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
if strings.Contains(info.Config.Image, "linuxserver/syncthing") {
|
||||
if v.State != "running" {
|
||||
//step:start container
|
||||
service.MyService.Docker().DockerContainerStart(v.CustomId)
|
||||
service.MyService.Docker().DockerContainerStart(v.ID)
|
||||
}
|
||||
syncIsExistence = true
|
||||
if config.SystemConfigInfo.SyncPort != v.Port {
|
||||
config.SystemConfigInfo.SyncPort = v.Port
|
||||
if config.SystemConfigInfo.SyncPort != v.Labels["web"] {
|
||||
config.SystemConfigInfo.SyncPort = v.Labels["web"]
|
||||
}
|
||||
var paths []model.PathMap
|
||||
json.Unmarshal([]byte(v.Volumes), &paths)
|
||||
|
||||
path := ""
|
||||
for _, i := range paths {
|
||||
if i.ContainerPath == "/config" {
|
||||
path = docker.GetDir(v.CustomId, i.Path) + "/config.xml"
|
||||
for i := 0; i < 10; i++ {
|
||||
if file.CheckNotExist(path) {
|
||||
time.Sleep(1 * time.Second)
|
||||
} else {
|
||||
for _, i := range info.Mounts {
|
||||
if i.Destination == "/config" {
|
||||
path = i.Source
|
||||
break
|
||||
}
|
||||
}
|
||||
break
|
||||
}
|
||||
}
|
||||
content := file.ReadFullFile(path)
|
||||
content := file.ReadFullFile(filepath.Join(path, "config.xml"))
|
||||
syncConfig := &system_app.SyncConfig{}
|
||||
xml.Unmarshal(content, &syncConfig)
|
||||
config.SystemConfigInfo.SyncKey = syncConfig.Key
|
||||
break
|
||||
}
|
||||
}
|
||||
if !syncIsExistence {
|
||||
@@ -261,7 +225,7 @@ func CheckToken2_11() {
|
||||
downloadPath = "C:\\CasaOS\\DATA\\Downloads"
|
||||
}
|
||||
if sysType == "darwin" {
|
||||
downloadPath = "~/CasaOS/DATA/Downloads"
|
||||
downloadPath = "./CasaOS/DATA/Downloads"
|
||||
}
|
||||
config.Cfg.Section("file").Key("DownloadDir").SetValue(downloadPath)
|
||||
config.FileSettingInfo.DownloadDir = downloadPath
|
||||
@@ -280,7 +244,10 @@ func CheckToken2_11() {
|
||||
config.Cfg.SaveTo(config.SystemConfigInfo.ConfigPath)
|
||||
}
|
||||
|
||||
service.MyService.System().ExecUSBAutoMountShell(config.ServerInfo.USBAutoMount)
|
||||
if service.MyService.ZiMa().GetSysInfo().KernelArch == "aarch64" && config.ServerInfo.USBAutoMount != "True" && strings.Contains(service.MyService.ZiMa().GetDeviceTree(), "Raspberry Pi") {
|
||||
service.MyService.System().UpdateUSBAutoMount("False")
|
||||
service.MyService.System().ExecUSBAutoMountShell("False")
|
||||
}
|
||||
|
||||
// str := []string{}
|
||||
// str = append(str, "ddd")
|
||||
@@ -291,3 +258,39 @@ func CheckToken2_11() {
|
||||
// config.Cfg.SaveTo(config.SystemConfigInfo.ConfigPath)
|
||||
|
||||
}
|
||||
|
||||
func ImportApplications() {
|
||||
service.MyService.App().ImportApplications(true)
|
||||
}
|
||||
|
||||
// 0.3.1
|
||||
func ChangeAPIUrl() {
|
||||
|
||||
newAPIUrl := "https://api.casaos.io/casaos-api"
|
||||
if config.ServerInfo.ServerApi == "https://api.casaos.zimaboard.com" {
|
||||
config.ServerInfo.ServerApi = newAPIUrl
|
||||
config.Cfg.Section("server").Key("ServerApi").SetValue(newAPIUrl)
|
||||
config.Cfg.SaveTo(config.SystemConfigInfo.ConfigPath)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// 0.3.1
|
||||
func InitSystemApplication() {
|
||||
list := service.MyService.App().GetApplicationList()
|
||||
if len(list) != 2 {
|
||||
application := model2.ApplicationModel{}
|
||||
application.Name = "Files"
|
||||
application.Icon = "/ui/img/Files.svg"
|
||||
application.Type = "system"
|
||||
application.Order = 0
|
||||
service.MyService.App().CreateApplication(application)
|
||||
|
||||
application.Name = "CasaConnect"
|
||||
application.Icon = "/ui/img/CasaConnect.svg"
|
||||
application.Type = "system"
|
||||
application.Order = 0
|
||||
|
||||
service.MyService.App().CreateApplication(application)
|
||||
}
|
||||
}
|
||||
|
||||
285
route/periodical.go
Normal file
@@ -0,0 +1,285 @@
|
||||
/*
|
||||
* @Author: LinkLeong link@icewhale.com
|
||||
* @Date: 2022-05-27 15:55:36
|
||||
* @LastEditors: LinkLeong
|
||||
* @LastEditTime: 2022-06-10 12:17:59
|
||||
* @FilePath: /CasaOS/route/periodical.go
|
||||
* @Description:
|
||||
* @Website: https://www.casaos.io
|
||||
* Copyright (c) 2022 by icewhale, All Rights Reserved.
|
||||
*/
|
||||
package route
|
||||
|
||||
import (
|
||||
"reflect"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
"unsafe"
|
||||
|
||||
"github.com/IceWhaleTech/CasaOS/model"
|
||||
"github.com/IceWhaleTech/CasaOS/service"
|
||||
)
|
||||
|
||||
func SendNetINfoBySocket() {
|
||||
netList := service.MyService.System().GetNetInfo()
|
||||
newNet := []model.IOCountersStat{}
|
||||
nets := service.MyService.System().GetNet(true)
|
||||
for _, n := range netList {
|
||||
for _, netCardName := range nets {
|
||||
if n.Name == netCardName {
|
||||
item := *(*model.IOCountersStat)(unsafe.Pointer(&n))
|
||||
item.State = strings.TrimSpace(service.MyService.ZiMa().GetNetState(n.Name))
|
||||
item.Time = time.Now().Unix()
|
||||
newNet = append(newNet, item)
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
service.MyService.Notify().SendNetInfoBySocket(newNet)
|
||||
}
|
||||
|
||||
func SendCPUBySocket() {
|
||||
cpu := service.MyService.System().GetCpuPercent()
|
||||
num := service.MyService.System().GetCpuCoreNum()
|
||||
cpuData := make(map[string]interface{})
|
||||
cpuData["percent"] = cpu
|
||||
cpuData["num"] = num
|
||||
service.MyService.Notify().SendCPUInfoBySocket(cpuData)
|
||||
}
|
||||
|
||||
func SendMemBySocket() {
|
||||
service.MyService.Notify().SendMemInfoBySocket(service.MyService.System().GetMemInfo())
|
||||
}
|
||||
|
||||
func SendDiskBySocket() {
|
||||
list := service.MyService.Disk().LSBLK(true)
|
||||
|
||||
summary := model.Summary{}
|
||||
healthy := true
|
||||
findSystem := 0
|
||||
|
||||
for i := 0; i < len(list); i++ {
|
||||
if len(list[i].Children) > 0 && findSystem == 0 {
|
||||
|
||||
for j := 0; j < len(list[i].Children); j++ {
|
||||
|
||||
if len(list[i].Children[j].Children) > 0 {
|
||||
for _, v := range list[i].Children[j].Children {
|
||||
if v.MountPoint == "/" {
|
||||
s, _ := strconv.ParseUint(v.FSSize, 10, 64)
|
||||
a, _ := strconv.ParseUint(v.FSAvail, 10, 64)
|
||||
u, _ := strconv.ParseUint(v.FSUsed, 10, 64)
|
||||
summary.Size += s
|
||||
summary.Avail += a
|
||||
summary.Used += u
|
||||
findSystem = 1
|
||||
break
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if list[i].Children[j].MountPoint == "/" {
|
||||
s, _ := strconv.ParseUint(list[i].Children[j].FSSize, 10, 64)
|
||||
a, _ := strconv.ParseUint(list[i].Children[j].FSAvail, 10, 64)
|
||||
u, _ := strconv.ParseUint(list[i].Children[j].FSUsed, 10, 64)
|
||||
summary.Size += s
|
||||
summary.Avail += a
|
||||
summary.Used += u
|
||||
findSystem = 1
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
if findSystem == 1 {
|
||||
findSystem += 1
|
||||
continue
|
||||
}
|
||||
if list[i].Tran == "sata" || list[i].Tran == "nvme" || list[i].Tran == "spi" || list[i].Tran == "sas" {
|
||||
temp := service.MyService.Disk().SmartCTL(list[i].Path)
|
||||
if reflect.DeepEqual(temp, model.SmartctlA{}) {
|
||||
continue
|
||||
}
|
||||
|
||||
//list[i].Temperature = temp.Temperature.Current
|
||||
if !temp.SmartStatus.Passed {
|
||||
healthy = false
|
||||
}
|
||||
if len(list[i].Children) > 0 {
|
||||
for _, v := range list[i].Children {
|
||||
s, _ := strconv.ParseUint(v.FSSize, 10, 64)
|
||||
a, _ := strconv.ParseUint(v.FSAvail, 10, 64)
|
||||
u, _ := strconv.ParseUint(v.FSUsed, 10, 64)
|
||||
summary.Size += s
|
||||
summary.Avail += a
|
||||
summary.Used += u
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
summary.Health = healthy
|
||||
service.MyService.Notify().SendDiskInfoBySocket(summary)
|
||||
}
|
||||
|
||||
func SendUSBBySocket() {
|
||||
usbList := service.MyService.Disk().LSBLK(false)
|
||||
usb := []model.DriveUSB{}
|
||||
for _, v := range usbList {
|
||||
if v.Tran == "usb" {
|
||||
temp := model.DriveUSB{}
|
||||
temp.Model = v.Model
|
||||
temp.Name = v.Name
|
||||
temp.Size = v.Size
|
||||
mountTemp := true
|
||||
if len(v.Children) == 0 {
|
||||
mountTemp = false
|
||||
}
|
||||
for _, child := range v.Children {
|
||||
if len(child.MountPoint) > 0 {
|
||||
avail, _ := strconv.ParseUint(child.FSAvail, 10, 64)
|
||||
temp.Avail += avail
|
||||
used, _ := strconv.ParseUint(child.FSUsed, 10, 64)
|
||||
temp.Used += used
|
||||
} else {
|
||||
mountTemp = false
|
||||
}
|
||||
}
|
||||
temp.Mount = mountTemp
|
||||
usb = append(usb, temp)
|
||||
}
|
||||
}
|
||||
service.MyService.Notify().SendUSBInfoBySocket(usb)
|
||||
}
|
||||
|
||||
func SendAllHardwareStatusBySocket() {
|
||||
|
||||
netList := service.MyService.System().GetNetInfo()
|
||||
newNet := []model.IOCountersStat{}
|
||||
nets := service.MyService.System().GetNet(true)
|
||||
for _, n := range netList {
|
||||
for _, netCardName := range nets {
|
||||
if n.Name == netCardName {
|
||||
item := *(*model.IOCountersStat)(unsafe.Pointer(&n))
|
||||
item.State = strings.TrimSpace(service.MyService.ZiMa().GetNetState(n.Name))
|
||||
item.Time = time.Now().Unix()
|
||||
newNet = append(newNet, item)
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
cpu := service.MyService.System().GetCpuPercent()
|
||||
num := service.MyService.System().GetCpuCoreNum()
|
||||
cpuData := make(map[string]interface{})
|
||||
cpuData["percent"] = cpu
|
||||
cpuData["num"] = num
|
||||
|
||||
list := service.MyService.Disk().LSBLK(true)
|
||||
|
||||
summary := model.Summary{}
|
||||
healthy := true
|
||||
findSystem := 0
|
||||
|
||||
for i := 0; i < len(list); i++ {
|
||||
if len(list[i].Children) > 0 && findSystem == 0 {
|
||||
|
||||
for j := 0; j < len(list[i].Children); j++ {
|
||||
|
||||
if len(list[i].Children[j].Children) > 0 {
|
||||
for _, v := range list[i].Children[j].Children {
|
||||
if v.MountPoint == "/" {
|
||||
s, _ := strconv.ParseUint(v.FSSize, 10, 64)
|
||||
a, _ := strconv.ParseUint(v.FSAvail, 10, 64)
|
||||
u, _ := strconv.ParseUint(v.FSUsed, 10, 64)
|
||||
summary.Size += s
|
||||
summary.Avail += a
|
||||
summary.Used += u
|
||||
findSystem = 1
|
||||
break
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if list[i].Children[j].MountPoint == "/" {
|
||||
s, _ := strconv.ParseUint(list[i].Children[j].FSSize, 10, 64)
|
||||
a, _ := strconv.ParseUint(list[i].Children[j].FSAvail, 10, 64)
|
||||
u, _ := strconv.ParseUint(list[i].Children[j].FSUsed, 10, 64)
|
||||
summary.Size += s
|
||||
summary.Avail += a
|
||||
summary.Used += u
|
||||
findSystem = 1
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
if findSystem == 1 {
|
||||
findSystem += 1
|
||||
continue
|
||||
}
|
||||
if list[i].Tran == "sata" || list[i].Tran == "nvme" || list[i].Tran == "spi" || list[i].Tran == "sas" {
|
||||
temp := service.MyService.Disk().SmartCTL(list[i].Path)
|
||||
if reflect.DeepEqual(temp, model.SmartctlA{}) {
|
||||
continue
|
||||
}
|
||||
|
||||
//list[i].Temperature = temp.Temperature.Current
|
||||
if !temp.SmartStatus.Passed {
|
||||
healthy = false
|
||||
}
|
||||
if len(list[i].Children) > 0 {
|
||||
for _, v := range list[i].Children {
|
||||
s, _ := strconv.ParseUint(v.FSSize, 10, 64)
|
||||
a, _ := strconv.ParseUint(v.FSAvail, 10, 64)
|
||||
u, _ := strconv.ParseUint(v.FSUsed, 10, 64)
|
||||
summary.Size += s
|
||||
summary.Avail += a
|
||||
summary.Used += u
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
summary.Health = healthy
|
||||
|
||||
usbList := service.MyService.Disk().LSBLK(false)
|
||||
usb := []model.DriveUSB{}
|
||||
for _, v := range usbList {
|
||||
if v.Tran == "usb" {
|
||||
temp := model.DriveUSB{}
|
||||
temp.Model = v.Model
|
||||
temp.Name = v.Name
|
||||
temp.Size = v.Size
|
||||
mountTemp := true
|
||||
if len(v.Children) == 0 {
|
||||
mountTemp = false
|
||||
}
|
||||
for _, child := range v.Children {
|
||||
if len(child.MountPoint) > 0 {
|
||||
avail, _ := strconv.ParseUint(child.FSAvail, 10, 64)
|
||||
temp.Avail += avail
|
||||
used, _ := strconv.ParseUint(child.FSUsed, 10, 64)
|
||||
temp.Used += used
|
||||
} else {
|
||||
mountTemp = false
|
||||
}
|
||||
}
|
||||
temp.Mount = mountTemp
|
||||
usb = append(usb, temp)
|
||||
}
|
||||
}
|
||||
memInfo := service.MyService.System().GetMemInfo()
|
||||
memData := make(map[string]interface{})
|
||||
memData["total"] = memInfo.Total
|
||||
memData["available"] = memInfo.Available
|
||||
memData["used"] = memInfo.Used
|
||||
memData["free"] = memInfo.Free
|
||||
memData["usedPercent"] = memInfo.UsedPercent
|
||||
|
||||
service.MyService.Notify().SendAllHardwareStatusBySocket(summary, usb, memData, cpuData, newNet)
|
||||
|
||||
}
|
||||
103
route/route.go
@@ -31,7 +31,6 @@ func InitRouter() *gin.Engine {
|
||||
if swagHandler != nil {
|
||||
r.GET("/swagger/*any", swagHandler)
|
||||
}
|
||||
|
||||
r.POST("/v1/user/login", v1.Login)
|
||||
|
||||
r.GET("/v1/guide/check", v1.GetGuideCheck)
|
||||
@@ -41,7 +40,9 @@ func InitRouter() *gin.Engine {
|
||||
r.POST("/v1/user/setusernamepwd", v1.Set_Name_Pwd)
|
||||
//get user info
|
||||
r.GET("/v1/user/info", v1.GetUserInfo)
|
||||
|
||||
//get user info
|
||||
r.GET("/v1/person/shareid", v1.GetPersonShareId)
|
||||
r.GET("/v1/sys/socket/port", v1.GetSystemSocketPort)
|
||||
v1Group := r.Group("/v1")
|
||||
|
||||
v1Group.Use(jwt2.JWT(swagHandler))
|
||||
@@ -63,46 +64,15 @@ func InitRouter() *gin.Engine {
|
||||
v1UserGroup.POST("/person/info", v1.PostUserPersonInfo)
|
||||
|
||||
v1UserGroup.GET("/shareid", v1.GetUserShareID)
|
||||
// v1UserGroup.GET("/custom/:name")
|
||||
// v1UserGroup.POST("/custom/:name")
|
||||
|
||||
}
|
||||
|
||||
v1ZiMaGroup := v1Group.Group("/zima")
|
||||
v1ZiMaGroup.Use()
|
||||
{
|
||||
//获取cpu信息
|
||||
v1ZiMaGroup.GET("/getcpuinfo", v1.CupInfo)
|
||||
//获取内存信息
|
||||
v1ZiMaGroup.GET("/getmeminfo", v1.MemInfo)
|
||||
//获取硬盘信息
|
||||
v1ZiMaGroup.GET("/getdiskinfo", v1.DiskInfo)
|
||||
|
||||
//获取网络信息
|
||||
v1ZiMaGroup.GET("/getnetinfo", v1.NetInfo)
|
||||
|
||||
//获取系统信息
|
||||
v1ZiMaGroup.GET("/sysinfo", v1.SysInfo)
|
||||
}
|
||||
v1DDNSGroup := v1Group.Group("/ddns")
|
||||
v1DDNSGroup.Use()
|
||||
{
|
||||
//获取ddns列表
|
||||
v1DDNSGroup.GET("/getlist", v1.DDNSGetDomainList)
|
||||
//测试连接性
|
||||
v1DDNSGroup.GET("/ping/:api_host", v1.DDNSPing)
|
||||
//获取ip
|
||||
v1DDNSGroup.GET("/ip", v1.DDNSGetIP)
|
||||
//设置ddns
|
||||
v1DDNSGroup.POST("/set", v1.DDNSAddConfig)
|
||||
//获取ddns
|
||||
v1DDNSGroup.GET("/list", v1.DDNSConfigList)
|
||||
//获取ddns
|
||||
v1DDNSGroup.DELETE("/delete/:id", v1.DDNSDelete)
|
||||
}
|
||||
v1AppGroup := v1Group.Group("/app")
|
||||
v1AppGroup.Use()
|
||||
{
|
||||
//获取我的已安装的列表
|
||||
v1AppGroup.GET("/mylist", v1.MyAppList)
|
||||
v1AppGroup.GET("/my/list", v1.MyAppList)
|
||||
//
|
||||
v1AppGroup.GET("/usage", v1.AppUsageList)
|
||||
//app详情
|
||||
@@ -117,8 +87,8 @@ func InitRouter() *gin.Engine {
|
||||
v1AppGroup.GET("/category", v1.CategoryList)
|
||||
//容器相关
|
||||
v1AppGroup.GET("/terminal/:id", v1.DockerTerminal)
|
||||
//准备安装
|
||||
//v1AppGroup.GET("/ready/:id", v1.ReadyInstall)
|
||||
v1AppGroup.GET("/order", v1.GetAppOrder)
|
||||
v1AppGroup.POST("/order", v1.PostAppOrder)
|
||||
//app容器详情
|
||||
v1AppGroup.GET("/info/:id", v1.ContainerInfo)
|
||||
//app容器日志
|
||||
@@ -126,11 +96,9 @@ func InitRouter() *gin.Engine {
|
||||
//暂停或启动容器
|
||||
v1AppGroup.PUT("/state/:id", v1.ChangAppState)
|
||||
//安装app
|
||||
v1AppGroup.POST("/install/:id", v1.InstallApp)
|
||||
v1AppGroup.POST("/install", v1.InstallApp)
|
||||
//卸载app
|
||||
v1AppGroup.DELETE("/uninstall/:id", v1.UnInstallApp)
|
||||
//获取安装进度
|
||||
v1AppGroup.GET("/speed/:id", v1.GetInstallSpeed)
|
||||
//获取进度
|
||||
v1AppGroup.GET("/state/:id", v1.GetContainerState)
|
||||
//更新容器配置
|
||||
@@ -139,17 +107,16 @@ func InitRouter() *gin.Engine {
|
||||
v1AppGroup.GET("/update/:id/info", v1.ContainerUpdateInfo)
|
||||
v1AppGroup.GET("/rely/:id/info", v1.ContainerRelyInfo)
|
||||
v1AppGroup.GET("/install/config", v1.GetDockerInstallConfig)
|
||||
//v1AppGroup.POST("/custom/install", v1.CustomInstallApp)
|
||||
v1AppGroup.PUT("/update/:id", v1.PutAppUpdate)
|
||||
v1AppGroup.POST("/share", v1.ShareAppFile)
|
||||
}
|
||||
|
||||
v1SysGroup := v1Group.Group("/sys")
|
||||
v1SysGroup.Use()
|
||||
{
|
||||
//获取检查版本是否需要升级
|
||||
v1SysGroup.GET("/check", v1.CheckVersion)
|
||||
v1SysGroup.GET("/version/check", v1.GetSystemCheckVersion)
|
||||
v1SysGroup.GET("/hardware/info", v1.GetSystemHardwareInfo)
|
||||
v1SysGroup.POST("/update", v1.SystemUpdate)
|
||||
v1SysGroup.GET("/sys", v1.Sys)
|
||||
v1SysGroup.GET("/wsssh", v1.WsSsh)
|
||||
v1SysGroup.GET("/config", v1.GetSystemConfig)
|
||||
v1SysGroup.GET("/error/logs", v1.GetCasaOSErrorLogs)
|
||||
@@ -158,16 +125,19 @@ func InitRouter() *gin.Engine {
|
||||
v1SysGroup.POST("/widget/config", v1.PostSetWidgetConfig)
|
||||
v1SysGroup.GET("/port", v1.GetCasaOSPort)
|
||||
v1SysGroup.PUT("/port", v1.PutCasaOSPort)
|
||||
v1SysGroup.POST("/kill", v1.PostKillCasaOS)
|
||||
v1SysGroup.GET("/info", v1.Info)
|
||||
v1SysGroup.PUT("/usb/off", v1.PutSystemOffUSBAutoMount)
|
||||
v1SysGroup.GET("/usb/on", v1.PutSystemOnUSBAutoMount)
|
||||
v1SysGroup.GET("/usb", v1.GetSystemUSBAutoMount)
|
||||
v1SysGroup.POST("/stop", v1.PostKillCasaOS)
|
||||
v1SysGroup.GET("/utilization", v1.GetSystemUtilization)
|
||||
v1SysGroup.PUT("/usb/:status", v1.PutSystemUSBAutoMount)
|
||||
v1SysGroup.GET("/usb/status", v1.GetSystemUSBAutoMount)
|
||||
v1SysGroup.GET("/cpu", v1.GetSystemCupInfo)
|
||||
v1SysGroup.GET("/mem", v1.GetSystemMemInfo)
|
||||
v1SysGroup.GET("/disk", v1.GetSystemDiskInfo)
|
||||
v1SysGroup.GET("/network", v1.GetSystemNetInfo)
|
||||
|
||||
}
|
||||
v1FileGroup := v1Group.Group("/file")
|
||||
v1FileGroup.Use()
|
||||
{
|
||||
//修改文件名称/目录名称
|
||||
v1FileGroup.PUT("/rename", v1.RenamePath)
|
||||
v1FileGroup.GET("/read", v1.GetFilerContent)
|
||||
v1FileGroup.POST("/upload", v1.PostFileUpload)
|
||||
@@ -178,10 +148,12 @@ func InitRouter() *gin.Engine {
|
||||
v1FileGroup.POST("/create", v1.PostCreateFile)
|
||||
|
||||
v1FileGroup.GET("/download", v1.GetDownloadFile)
|
||||
v1FileGroup.GET("/new/download", v1.GetFileDownloadNew)
|
||||
v1FileGroup.GET("/download/*path", v1.GetDownloadSingleFile)
|
||||
v1FileGroup.POST("/operate", v1.PostOperateFileOrDir)
|
||||
v1FileGroup.DELETE("/delete", v1.DeleteFile)
|
||||
v1FileGroup.PUT("/update", v1.PutFileContent)
|
||||
v1FileGroup.GET("/image", v1.GetFileImage)
|
||||
v1FileGroup.DELETE("/operate/:id", v1.DeleteOperateFileOrDir)
|
||||
|
||||
//v1FileGroup.GET("/download", v1.UserFileDownloadCommonService)
|
||||
}
|
||||
@@ -231,31 +203,12 @@ func InitRouter() *gin.Engine {
|
||||
v1TaskGroup.PUT("/update", v1.PutTaskUpdate)
|
||||
v1TaskGroup.POST("/add", v1.PostTaskAdd)
|
||||
v1TaskGroup.PUT("/completion/:id", v1.PutTaskMarkerCompletion)
|
||||
}
|
||||
|
||||
}
|
||||
v1ShortcutsGroup := v1Group.Group("/shortcuts")
|
||||
v1ShortcutsGroup.Use()
|
||||
{
|
||||
v1ShortcutsGroup.GET("/list", v1.GetShortcutsList)
|
||||
v1ShortcutsGroup.POST("/add", v1.PostShortcutsAdd)
|
||||
v1ShortcutsGroup.PUT("/edit", v1.PutShortcutsEdit)
|
||||
v1ShortcutsGroup.DELETE("/del/:id", v1.DeleteShortcutsDelete)
|
||||
}
|
||||
v1NotifyGroup := v1Group.Group("/notify")
|
||||
v1NotifyGroup.Use()
|
||||
{
|
||||
v1NotifyGroup.GET("/ws", v1.NotifyWS)
|
||||
v1NotifyGroup.PUT("/read/:id", v1.PutNotifyRead)
|
||||
}
|
||||
v1SearchGroup := v1Group.Group("/search")
|
||||
v1SearchGroup.Use()
|
||||
{
|
||||
v1SearchGroup.GET("/search", v1.GetSearchList)
|
||||
}
|
||||
v1PersonGroup := v1Group.Group("/person")
|
||||
v1PersonGroup.Use()
|
||||
{
|
||||
v1PersonGroup.GET("/test", v1.PersonTest)
|
||||
v1PersonGroup.GET("/detection", v1.GetPersonDetection)
|
||||
v1PersonGroup.GET("/users", v1.GetPersonFriend)
|
||||
v1PersonGroup.POST("/user/:shareids", v1.PostAddPersonFriend)
|
||||
v1PersonGroup.DELETE("/user/:shareid", v1.DeletePersonFriend)
|
||||
@@ -267,11 +220,15 @@ func InitRouter() *gin.Engine {
|
||||
v1PersonGroup.DELETE("/file/:uuid", v1.DeletePersonDownloadFile)
|
||||
|
||||
v1PersonGroup.POST("/share", v1.PostPersonShare)
|
||||
v1PersonGroup.POST("/file/:shareid", v1.PostPersonFile)
|
||||
v1PersonGroup.GET("/share", v1.GetPersonShare)
|
||||
v1PersonGroup.POST("/down/dir", v1.PostPersonDownDir)
|
||||
v1PersonGroup.GET("/down/dir", v1.GetPersonDownDir)
|
||||
v1PersonGroup.PUT("/block/:shareid", v1.PutPersonBlock)
|
||||
v1PersonGroup.GET("/public", v1.GetPersonPublic)
|
||||
v1PersonGroup.PUT("/friend/:shareid", v1.PutPersonAgreeFriend)
|
||||
v1PersonGroup.PUT("/write/:shareid", v1.PutPersonWrite)
|
||||
v1PersonGroup.GET("/image/thumbnail/:shareid", v1.GetPersonImageThumbnail)
|
||||
|
||||
}
|
||||
v1AnalyseGroup := v1Group.Group("/analyse")
|
||||
|
||||
60
route/socket.go
Normal file
@@ -0,0 +1,60 @@
|
||||
/*
|
||||
* @Author: LinkLeong link@icewhale.com
|
||||
* @Date: 2022-05-23 17:18:56
|
||||
* @LastEditors: LinkLeong
|
||||
* @LastEditTime: 2022-06-09 21:48:10
|
||||
* @FilePath: /CasaOS/route/socket.go
|
||||
* @Description:
|
||||
* @Website: https://www.casaos.io
|
||||
* Copyright (c) 2022 by icewhale, All Rights Reserved.
|
||||
*/
|
||||
package route
|
||||
|
||||
import (
|
||||
"strconv"
|
||||
"time"
|
||||
|
||||
"github.com/IceWhaleTech/CasaOS/model/notify"
|
||||
"github.com/IceWhaleTech/CasaOS/pkg/config"
|
||||
"github.com/IceWhaleTech/CasaOS/pkg/utils/port"
|
||||
"github.com/IceWhaleTech/CasaOS/service"
|
||||
f "github.com/ambelovsky/gosf"
|
||||
)
|
||||
|
||||
func SocketInit(msg chan notify.Message) {
|
||||
|
||||
// set socket port
|
||||
socketPort := 0
|
||||
if len(config.ServerInfo.SocketPort) == 0 {
|
||||
socketPort, _ = port.GetAvailablePort("tcp")
|
||||
config.ServerInfo.SocketPort = strconv.Itoa(socketPort)
|
||||
config.Cfg.Section("server").Key("SocketPort").SetValue(strconv.Itoa(socketPort))
|
||||
config.Cfg.SaveTo(config.SystemConfigInfo.ConfigPath)
|
||||
} else {
|
||||
socketPort, _ = strconv.Atoi(config.ServerInfo.SocketPort)
|
||||
if !port.IsPortAvailable(socketPort, "tcp") {
|
||||
socketPort, _ := port.GetAvailablePort("tcp")
|
||||
config.ServerInfo.SocketPort = strconv.Itoa(socketPort)
|
||||
config.Cfg.Section("server").Key("SocketPort").SetValue(strconv.Itoa(socketPort))
|
||||
config.Cfg.SaveTo(config.SystemConfigInfo.ConfigPath)
|
||||
}
|
||||
}
|
||||
|
||||
f.OnConnect(func(c *f.Client, request *f.Request) {
|
||||
service.ClientCount += 1
|
||||
})
|
||||
f.OnDisconnect(func(c *f.Client, request *f.Request) {
|
||||
service.ClientCount -= 1
|
||||
})
|
||||
go func(msg chan notify.Message) {
|
||||
for v := range msg {
|
||||
f.Broadcast("", v.Path, &v.Msg)
|
||||
time.Sleep(time.Millisecond * 100)
|
||||
}
|
||||
|
||||
}(msg)
|
||||
|
||||
f.Startup(map[string]interface{}{
|
||||
"port": socketPort})
|
||||
|
||||
}
|
||||
@@ -106,13 +106,18 @@ func PortCheck(c *gin.Context) {
|
||||
// @Param size query int false "size"
|
||||
// @Param position query bool false "是否是首页应用"
|
||||
// @Success 200 {string} string "ok"
|
||||
// @Router /app/mylist [get]
|
||||
// @Router /app/my/list [get]
|
||||
func MyAppList(c *gin.Context) {
|
||||
index, _ := strconv.Atoi(c.DefaultQuery("index", "1"))
|
||||
size, _ := strconv.Atoi(c.DefaultQuery("size", "0"))
|
||||
position, _ := strconv.ParseBool(c.DefaultQuery("position", "true"))
|
||||
list := service.MyService.App().GetMyList(index, size, position)
|
||||
c.JSON(http.StatusOK, &model.Result{Success: oasis_err2.SUCCESS, Message: oasis_err2.GetMsg(oasis_err2.SUCCESS), Data: list})
|
||||
list, unTranslation := service.MyService.App().GetMyList(index, size, position)
|
||||
|
||||
data := make(map[string]interface{}, 2)
|
||||
data["list"] = list
|
||||
data["local"] = unTranslation
|
||||
|
||||
c.JSON(http.StatusOK, &model.Result{Success: oasis_err2.SUCCESS, Message: oasis_err2.GetMsg(oasis_err2.SUCCESS), Data: data})
|
||||
}
|
||||
|
||||
// @Summary my app hardware usage list
|
||||
@@ -204,7 +209,7 @@ func AppInfo(c *gin.Context) {
|
||||
// sort.VolSort(volOrder).Sort(info.Volumes.([]model.PathMap))
|
||||
// sort.DevSort(devOrder).Sort(info.Devices)
|
||||
|
||||
info.MaxMemory = service.MyService.ZiMa().GetMemInfo().Total >> 20
|
||||
info.MaxMemory = service.MyService.System().GetMemInfo().Total >> 20
|
||||
|
||||
c.JSON(http.StatusOK, &model.Result{Success: oasis_err2.SUCCESS, Message: oasis_err2.GetMsg(oasis_err2.SUCCESS), Data: info})
|
||||
}
|
||||
@@ -241,14 +246,3 @@ func ShareAppFile(c *gin.Context) {
|
||||
content := service.MyService.Casa().ShareAppFile(str)
|
||||
c.JSON(http.StatusOK, json.RawMessage(content))
|
||||
}
|
||||
|
||||
// @Summary Resource Usage
|
||||
// @Produce application/json
|
||||
// @Accept application/json
|
||||
// @Tags app
|
||||
// @Security ApiKeyAuth
|
||||
// @Success 200 {string} string "ok"
|
||||
// @Router /app/shares [post]
|
||||
func AppListResourceUsage() {
|
||||
|
||||
}
|
||||
|
||||
@@ -5,17 +5,19 @@ import (
|
||||
"encoding/json"
|
||||
json2 "encoding/json"
|
||||
"net/http"
|
||||
"reflect"
|
||||
"path/filepath"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/IceWhaleTech/CasaOS/model"
|
||||
"github.com/IceWhaleTech/CasaOS/model/notify"
|
||||
"github.com/IceWhaleTech/CasaOS/pkg/config"
|
||||
"github.com/IceWhaleTech/CasaOS/pkg/docker"
|
||||
upnp2 "github.com/IceWhaleTech/CasaOS/pkg/upnp"
|
||||
"github.com/IceWhaleTech/CasaOS/pkg/utils/file"
|
||||
ip_helper2 "github.com/IceWhaleTech/CasaOS/pkg/utils/ip_helper"
|
||||
"github.com/IceWhaleTech/CasaOS/pkg/utils/oasis_err"
|
||||
oasis_err2 "github.com/IceWhaleTech/CasaOS/pkg/utils/oasis_err"
|
||||
port2 "github.com/IceWhaleTech/CasaOS/pkg/utils/port"
|
||||
"github.com/IceWhaleTech/CasaOS/pkg/utils/random"
|
||||
@@ -27,7 +29,6 @@ import (
|
||||
"github.com/gorilla/websocket"
|
||||
"github.com/jinzhu/copier"
|
||||
uuid "github.com/satori/go.uuid"
|
||||
"github.com/tidwall/gjson"
|
||||
"golang.org/x/crypto/ssh"
|
||||
)
|
||||
|
||||
@@ -143,10 +144,8 @@ func SpeedPush(c *gin.Context) {
|
||||
// @Param env formData string false "环境变量"
|
||||
// @Security ApiKeyAuth
|
||||
// @Success 200 {string} string "ok"
|
||||
// @Router /app/install/{id} [post]
|
||||
// @Router /app/install [post]
|
||||
func InstallApp(c *gin.Context) {
|
||||
appId := c.Param("id")
|
||||
language := c.GetHeader("Language")
|
||||
var appInfo model.ServerAppList
|
||||
m := model.CustomizationPostData{}
|
||||
c.BindJSON(&m)
|
||||
@@ -154,7 +153,30 @@ func InstallApp(c *gin.Context) {
|
||||
const CUSTOM = "custom"
|
||||
var dockerImage string
|
||||
var dockerImageVersion string
|
||||
//检查端口
|
||||
|
||||
//check app name is exist
|
||||
if len(m.Protocol) == 0 {
|
||||
m.Protocol = "http"
|
||||
}
|
||||
if m.Origin != "custom" {
|
||||
oldName := m.Label
|
||||
for i := 0; true; i++ {
|
||||
if i != 0 {
|
||||
m.Label = oldName + "-" + strconv.Itoa(i)
|
||||
}
|
||||
if _, err := service.MyService.Docker().DockerListByName(m.Label); err != nil {
|
||||
break
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if _, err := service.MyService.Docker().DockerListByName(m.Label); err == nil {
|
||||
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.ERROR_APP_NAME_EXIST, Message: oasis_err2.GetMsg(oasis_err2.ERROR_APP_NAME_EXIST)})
|
||||
return
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
//check port
|
||||
if len(m.PortMap) > 0 && m.PortMap != "0" {
|
||||
//c.JSON(http.StatusOK, model.Result{Success: oasis_err2.INVALID_PARAMS, Message: oasis_err2.GetMsg(oasis_err2.INVALID_PARAMS)})
|
||||
portMap, _ := strconv.Atoi(m.PortMap)
|
||||
@@ -175,21 +197,6 @@ func InstallApp(c *gin.Context) {
|
||||
dockerImage = m.Image
|
||||
dockerImageVersion = "latest"
|
||||
}
|
||||
if m.Origin != "custom" {
|
||||
appInfo = service.MyService.Casa().GetServerAppInfo(appId, "", language)
|
||||
|
||||
} else {
|
||||
|
||||
appInfo.Title = m.Label
|
||||
appInfo.Description = m.Description
|
||||
appInfo.Icon = m.Icon
|
||||
appInfo.ScreenshotLink = model.Strings{}
|
||||
appInfo.NetworkModel = m.NetworkModel
|
||||
appInfo.Tags = model.Strings{}
|
||||
appInfo.Tagline = ""
|
||||
appInfo.Index = m.Index
|
||||
|
||||
}
|
||||
|
||||
for _, u := range m.Ports {
|
||||
|
||||
@@ -248,19 +255,19 @@ func InstallApp(c *gin.Context) {
|
||||
//
|
||||
//}
|
||||
id := uuid.NewV4().String()
|
||||
|
||||
m.CustomId = id
|
||||
var relyMap = make(map[string]string)
|
||||
go func() {
|
||||
installLog := model2.AppNotify{}
|
||||
installLog.State = 0
|
||||
installLog.CustomId = id
|
||||
installLog.Message = "installing rely"
|
||||
installLog.Class = types.NOTIFY_APP
|
||||
installLog.Type = types.NOTIFY_TYPE_UNIMPORTANT
|
||||
installLog.CreatedAt = strconv.FormatInt(time.Now().Unix(), 10)
|
||||
installLog.UpdatedAt = strconv.FormatInt(time.Now().Unix(), 10)
|
||||
installLog.Id = uuid.NewV4().String()
|
||||
service.MyService.Notify().AddLog(installLog)
|
||||
// installLog := model2.AppNotify{}
|
||||
// installLog.State = 0
|
||||
// installLog.CustomId = m.Label
|
||||
// installLog.Message = "installing rely"
|
||||
// installLog.Class = types.NOTIFY_APP
|
||||
// installLog.Type = types.NOTIFY_TYPE_UNIMPORTANT
|
||||
// installLog.CreatedAt = strconv.FormatInt(time.Now().Unix(), 10)
|
||||
// installLog.UpdatedAt = strconv.FormatInt(time.Now().Unix(), 10)
|
||||
// installLog.Id = uuid.NewV4().String()
|
||||
// service.MyService.Notify().AddLog(installLog)
|
||||
if m.Origin != "custom" {
|
||||
for _, plugin := range appInfo.Plugins {
|
||||
if plugin == "mysql" {
|
||||
@@ -281,7 +288,7 @@ func InstallApp(c *gin.Context) {
|
||||
rely.Type = types.RELY_TYPE_MYSQL
|
||||
rely.ContainerId = mysqlContainerId
|
||||
rely.CustomId = mid
|
||||
rely.ContainerCustomId = id
|
||||
rely.ContainerCustomId = m.Label
|
||||
var mysqlConfig model2.MysqlConfigs
|
||||
|
||||
//结构体转换
|
||||
@@ -293,24 +300,26 @@ func InstallApp(c *gin.Context) {
|
||||
|
||||
} else {
|
||||
docker_base.MysqlDelete(mysqlContainerId)
|
||||
installLog.State = 0
|
||||
installLog.Message = err.Error()
|
||||
service.MyService.Notify().UpdateLog(installLog)
|
||||
// installLog.State = 0
|
||||
// installLog.Message = err.Error()
|
||||
// service.MyService.Notify().UpdateLog(installLog)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
installLog.Message = "pulling"
|
||||
service.MyService.Notify().UpdateLog(installLog)
|
||||
|
||||
// step:下载镜像
|
||||
err := service.MyService.Docker().DockerPullImage(dockerImage+":"+dockerImageVersion, installLog)
|
||||
err := service.MyService.Docker().DockerPullImage(dockerImage+":"+dockerImageVersion, m.Icon, m.Label)
|
||||
if err != nil {
|
||||
installLog.State = 0
|
||||
installLog.Message = err.Error()
|
||||
installLog.Type = types.NOTIFY_TYPE_ERROR
|
||||
service.MyService.Notify().UpdateLog(installLog)
|
||||
notify := notify.Application{}
|
||||
notify.Icon = m.Icon
|
||||
notify.Name = m.Label
|
||||
notify.State = "PULLING"
|
||||
notify.Type = "INSTALL"
|
||||
notify.Success = false
|
||||
notify.Finished = false
|
||||
notify.Message = err.Error()
|
||||
service.MyService.Notify().SendInstallAppBySocket(notify)
|
||||
return
|
||||
}
|
||||
|
||||
@@ -318,60 +327,57 @@ func InstallApp(c *gin.Context) {
|
||||
time.Sleep(time.Second)
|
||||
}
|
||||
|
||||
//if {
|
||||
|
||||
//}
|
||||
|
||||
//step:创建容器
|
||||
// networkName, err := service.MyService.Docker().GetNetWorkNameByNetWorkID(appInfo.NetworkModel)
|
||||
// if err != nil {
|
||||
// //service.MyService.Redis().Set(id, "{\"id\"\""+id+"\",\"state\":false,\"message\":\""+err.Error()+"\",\"speed\":80}", 100)
|
||||
// installLog.State = 0
|
||||
// installLog.Speed = 75
|
||||
// installLog.Type = types.NOTIFY_TYPE_ERROR
|
||||
// installLog.Message = err.Error()
|
||||
// service.MyService.Notify().UpdateLog(installLog)
|
||||
// return
|
||||
// }
|
||||
containerId, err := service.MyService.Docker().DockerContainerCreate(dockerImage+":"+dockerImageVersion, id, m, appInfo.NetworkModel)
|
||||
installLog.Name = appInfo.Title
|
||||
installLog.Icon = appInfo.Icon
|
||||
_, err = service.MyService.Docker().DockerContainerCreate(dockerImage+":"+dockerImageVersion, m, appInfo.NetworkModel)
|
||||
if err != nil {
|
||||
//service.MyService.Redis().Set(id, "{\"id\"\""+id+"\",\"state\":false,\"message\":\""+err.Error()+"\",\"speed\":80}", 100)
|
||||
installLog.State = 0
|
||||
installLog.Type = types.NOTIFY_TYPE_ERROR
|
||||
installLog.Message = err.Error()
|
||||
service.MyService.Notify().UpdateLog(installLog)
|
||||
notify := notify.Application{}
|
||||
notify.Icon = m.Icon
|
||||
notify.Name = m.Label
|
||||
notify.State = "STARTING"
|
||||
notify.Type = "INSTALL"
|
||||
notify.Success = false
|
||||
notify.Finished = false
|
||||
notify.Message = err.Error()
|
||||
service.MyService.Notify().SendInstallAppBySocket(notify)
|
||||
return
|
||||
} else {
|
||||
//service.MyService.Redis().Set(id, "{\"id\":\""+id+"\",\"state\":true,\"message\":\"starting\",\"speed\":80}", 100)
|
||||
installLog.Message = "starting"
|
||||
service.MyService.Notify().UpdateLog(installLog)
|
||||
notify := notify.Application{}
|
||||
notify.Icon = m.Icon
|
||||
notify.Name = m.Label
|
||||
notify.State = "STARTING"
|
||||
notify.Type = "INSTALL"
|
||||
notify.Success = true
|
||||
notify.Finished = false
|
||||
service.MyService.Notify().SendInstallAppBySocket(notify)
|
||||
}
|
||||
|
||||
// echo -e "hellow\nworld" >>
|
||||
|
||||
//step:启动容器
|
||||
err = service.MyService.Docker().DockerContainerStart(id)
|
||||
err = service.MyService.Docker().DockerContainerStart(m.Label)
|
||||
if err != nil {
|
||||
//service.MyService.Redis().Set(id, "{\"id\"\""+id+"\",\"state\":false,\"message\":\""+err.Error()+"\",\"speed\":90}", 100)
|
||||
installLog.State = 0
|
||||
installLog.Type = types.NOTIFY_TYPE_ERROR
|
||||
installLog.Message = err.Error()
|
||||
service.MyService.Notify().UpdateLog(installLog)
|
||||
notify := notify.Application{}
|
||||
notify.Icon = m.Icon
|
||||
notify.Name = m.Label
|
||||
notify.State = "STARTING"
|
||||
notify.Type = "INSTALL"
|
||||
notify.Success = false
|
||||
notify.Finished = false
|
||||
notify.Message = err.Error()
|
||||
service.MyService.Notify().SendInstallAppBySocket(notify)
|
||||
return
|
||||
} else {
|
||||
//service.MyService.Redis().Set(id, "{\"id\":\""+id+"\",\"state\":true,\"message\":\"setting upnp\",\"speed\":90}", 100)
|
||||
if m.Origin != CUSTOM {
|
||||
installLog.Message = "setting upnp"
|
||||
} else {
|
||||
installLog.Message = "nearing completion"
|
||||
}
|
||||
service.MyService.Notify().UpdateLog(installLog)
|
||||
// if m.Origin != CUSTOM {
|
||||
// installLog.Message = "setting upnp"
|
||||
// } else {
|
||||
// installLog.Message = "nearing completion"
|
||||
// }
|
||||
// service.MyService.Notify().UpdateLog(installLog)
|
||||
}
|
||||
|
||||
if m.Origin != CUSTOM {
|
||||
//step:启动upnp
|
||||
//step:enable upnp
|
||||
if m.EnableUPNP {
|
||||
upnp, err := upnp2.Gateway()
|
||||
if err == nil {
|
||||
@@ -403,94 +409,55 @@ func InstallApp(c *gin.Context) {
|
||||
}
|
||||
|
||||
}
|
||||
if err != nil {
|
||||
//service.MyService.Redis().Set(id, "{\"id\"\""+id+"\",\"state\":false,\"message\":\""+err.Error()+"\",\"speed\":95}", 100)
|
||||
installLog.State = 0
|
||||
installLog.Type = types.NOTIFY_TYPE_ERROR
|
||||
installLog.Message = err.Error()
|
||||
service.MyService.Notify().UpdateLog(installLog)
|
||||
} else {
|
||||
//service.MyService.Redis().Set(id, "{\"id\":\""+id+"\",\"state\":true,\"message\":\"checking\",\"speed\":95}", 100)
|
||||
installLog.Message = "checking"
|
||||
service.MyService.Notify().UpdateLog(installLog)
|
||||
}
|
||||
// if err != nil {
|
||||
// //service.MyService.Redis().Set(id, "{\"id\"\""+id+"\",\"state\":false,\"message\":\""+err.Error()+"\",\"speed\":95}", 100)
|
||||
// installLog.State = 0
|
||||
// installLog.Type = types.NOTIFY_TYPE_ERROR
|
||||
// installLog.Message = err.Error()
|
||||
// service.MyService.Notify().UpdateLog(installLog)
|
||||
// } else {
|
||||
// //service.MyService.Redis().Set(id, "{\"id\":\""+id+"\",\"state\":true,\"message\":\"checking\",\"speed\":95}", 100)
|
||||
// installLog.Message = "checking"
|
||||
// service.MyService.Notify().UpdateLog(installLog)
|
||||
// }
|
||||
}
|
||||
}
|
||||
|
||||
//step: 启动成功 检查容器状态确认启动成功
|
||||
container, err := service.MyService.Docker().DockerContainerInfo(id)
|
||||
container, err := service.MyService.Docker().DockerContainerInfo(m.Label)
|
||||
if err != nil && container.ContainerJSONBase.State.Running {
|
||||
//service.MyService.Redis().Set(id, "{\"id\"\""+id+"\",\"state\":false,\"message\":\""+err.Error()+"\",\"speed\":100}", 100)
|
||||
installLog.State = 0
|
||||
installLog.Type = types.NOTIFY_TYPE_ERROR
|
||||
installLog.Message = err.Error()
|
||||
service.MyService.Notify().UpdateLog(installLog)
|
||||
notify := notify.Application{}
|
||||
notify.Icon = m.Icon
|
||||
notify.Name = m.Label
|
||||
notify.State = "INSTALLED"
|
||||
notify.Type = "INSTALL"
|
||||
notify.Success = false
|
||||
notify.Finished = true
|
||||
notify.Message = err.Error()
|
||||
service.MyService.Notify().SendInstallAppBySocket(notify)
|
||||
return
|
||||
} else {
|
||||
//service.MyService.Redis().Set(id, "{\"id\":\""+id+"\",\"state\":true,\"message\":\"installed\",\"speed\":100}", 100)
|
||||
installLog.Message = "installed"
|
||||
service.MyService.Notify().UpdateLog(installLog)
|
||||
notify := notify.Application{}
|
||||
notify.Icon = m.Icon
|
||||
notify.Name = m.Label
|
||||
notify.State = "INSTALLED"
|
||||
notify.Type = "INSTALL"
|
||||
notify.Success = true
|
||||
notify.Finished = true
|
||||
service.MyService.Notify().SendInstallAppBySocket(notify)
|
||||
}
|
||||
|
||||
rely := model.MapStrings{}
|
||||
|
||||
copier.Copy(&rely, &relyMap)
|
||||
// if m.Origin != "custom" {
|
||||
// for i := 0; i < len(m.Volumes); i++ {
|
||||
// m.Volumes[i].Path = docker.GetDir(id, m.Volumes[i].Path)
|
||||
// }
|
||||
// }
|
||||
|
||||
portsStr, _ := json2.Marshal(m.Ports)
|
||||
envsStr, _ := json2.Marshal(m.Envs)
|
||||
volumesStr, _ := json2.Marshal(m.Volumes)
|
||||
devicesStr, _ := json2.Marshal(m.Devices)
|
||||
cmd, _ := json2.Marshal(m.Cmd)
|
||||
capAdd, _ := json.Marshal(m.CapAdd)
|
||||
//step: 保存数据到数据库
|
||||
md := model2.AppListDBModel{
|
||||
CustomId: id,
|
||||
Title: appInfo.Title,
|
||||
//ScreenshotLink: appInfo.ScreenshotLink,
|
||||
Slogan: appInfo.Tagline,
|
||||
Description: appInfo.Description,
|
||||
//Tags: appInfo.Tags,
|
||||
Icon: appInfo.Icon,
|
||||
Version: dockerImageVersion,
|
||||
ContainerId: containerId,
|
||||
Image: dockerImage,
|
||||
Index: appInfo.Index,
|
||||
//Port: m.Port,
|
||||
PortMap: m.PortMap,
|
||||
Label: m.Label,
|
||||
EnableUPNP: m.EnableUPNP,
|
||||
Ports: string(portsStr),
|
||||
Envs: string(envsStr),
|
||||
Volumes: string(volumesStr),
|
||||
Position: m.Position,
|
||||
NetModel: appInfo.NetworkModel,
|
||||
Restart: m.Restart,
|
||||
CpuShares: m.CpuShares,
|
||||
Memory: m.Memory,
|
||||
Devices: string(devicesStr),
|
||||
//Rely: rely,
|
||||
Origin: m.Origin,
|
||||
CreatedAt: strconv.FormatInt(time.Now().Unix(), 10),
|
||||
UpdatedAt: strconv.FormatInt(time.Now().Unix(), 10),
|
||||
Cmd: string(cmd),
|
||||
CapAdd: string(capAdd),
|
||||
HostName: m.HostName,
|
||||
Privileged: m.Privileged,
|
||||
}
|
||||
//if appInfo.NetworkModel == "host" {
|
||||
// m.PortMap = m.Port
|
||||
//}
|
||||
service.MyService.App().SaveContainer(md)
|
||||
//service.MyService.App().SaveContainer(md)
|
||||
config.CasaOSGlobalVariables.AppChange = true
|
||||
|
||||
}()
|
||||
|
||||
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.SUCCESS, Message: oasis_err2.GetMsg(oasis_err2.SUCCESS), Data: id})
|
||||
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.SUCCESS, Message: oasis_err2.GetMsg(oasis_err2.SUCCESS), Data: m.Label})
|
||||
|
||||
}
|
||||
|
||||
@@ -691,35 +658,36 @@ func UnInstallApp(c *gin.Context) {
|
||||
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.INVALID_PARAMS, Message: oasis_err2.GetMsg(oasis_err2.INVALID_PARAMS)})
|
||||
return
|
||||
}
|
||||
info := service.MyService.App().GetUninstallInfo(appId)
|
||||
//info := service.MyService.App().GetUninstallInfo(appId)
|
||||
|
||||
info, err := service.MyService.Docker().DockerContainerInfo(appId)
|
||||
if err != nil {
|
||||
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.ERROR, Message: oasis_err2.GetMsg(oasis_err2.ERROR), Data: err.Error()})
|
||||
return
|
||||
}
|
||||
|
||||
//step:停止容器
|
||||
err := service.MyService.Docker().DockerContainerStop(appId)
|
||||
err = service.MyService.Docker().DockerContainerStop(appId)
|
||||
if err != nil {
|
||||
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.UNINSTALL_APP_ERROR, Message: oasis_err2.GetMsg(oasis_err2.UNINSTALL_APP_ERROR), Data: err.Error()})
|
||||
return
|
||||
}
|
||||
|
||||
//step:删除容器
|
||||
err = service.MyService.Docker().DockerContainerRemove(appId, false)
|
||||
if err != nil {
|
||||
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.UNINSTALL_APP_ERROR, Message: oasis_err2.GetMsg(oasis_err2.UNINSTALL_APP_ERROR), Data: err.Error()})
|
||||
return
|
||||
}
|
||||
|
||||
//存在镜像正在使用的情况
|
||||
// step:删除镜像
|
||||
service.MyService.Docker().DockerImageRemove(info.Image + ":" + info.Version)
|
||||
|
||||
//step: 删除本地数据
|
||||
service.MyService.App().RemoveContainerById(appId)
|
||||
if info.Origin != "custom" {
|
||||
// step:remove image
|
||||
service.MyService.Docker().DockerImageRemove(info.Config.Image)
|
||||
|
||||
if info.Config.Labels["origin"] != "custom" {
|
||||
//step: 删除文件夹
|
||||
vol := gjson.Get(info.Volumes, "#.host")
|
||||
for _, v := range vol.Array() {
|
||||
if strings.Contains(v.String(), appId) {
|
||||
service.MyService.App().DelAppConfigDir(v.String())
|
||||
for _, v := range info.Mounts {
|
||||
if strings.Contains(v.Source, info.Name) {
|
||||
path := filepath.Join(strings.Split(v.Source, info.Name)[0], info.Name)
|
||||
service.MyService.App().DelAppConfigDir(path)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -764,13 +732,14 @@ func UnInstallApp(c *gin.Context) {
|
||||
//}
|
||||
}
|
||||
config.CasaOSGlobalVariables.AppChange = true
|
||||
unInstallLog := model2.AppNotify{}
|
||||
unInstallLog.State = 0
|
||||
unInstallLog.CustomId = appId
|
||||
unInstallLog.Message = "uninstalled"
|
||||
unInstallLog.Id = uuid.NewV4().String()
|
||||
service.MyService.Notify().UpdateLog(unInstallLog)
|
||||
|
||||
notify := notify.Application{}
|
||||
notify.Icon = info.Config.Labels["icon"]
|
||||
notify.Name = strings.ReplaceAll(info.Name, "/", "")
|
||||
notify.State = "FINISHED"
|
||||
notify.Type = "UNINSTALL"
|
||||
notify.Success = true
|
||||
notify.Finished = true
|
||||
service.MyService.Notify().SendUninstallAppBySocket(notify)
|
||||
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.SUCCESS, Message: oasis_err2.GetMsg(oasis_err2.SUCCESS)})
|
||||
|
||||
}
|
||||
@@ -793,7 +762,7 @@ func ChangAppState(c *gin.Context) {
|
||||
} else if state == "start" {
|
||||
err = service.MyService.Docker().DockerContainerStart(appId)
|
||||
} else if state == "restart" {
|
||||
err = service.MyService.Docker().DockerContainerStop(appId)
|
||||
service.MyService.Docker().DockerContainerStop(appId)
|
||||
err = service.MyService.Docker().DockerContainerStart(appId)
|
||||
}
|
||||
if err != nil {
|
||||
@@ -822,20 +791,6 @@ func ContainerLog(c *gin.Context) {
|
||||
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.SUCCESS, Message: oasis_err2.GetMsg(oasis_err2.SUCCESS), Data: log})
|
||||
}
|
||||
|
||||
// @Summary 获取安装进度
|
||||
// @Produce application/json
|
||||
// @Accept application/json
|
||||
// @Tags app
|
||||
// @Param id path string true "容器id"
|
||||
// @Security ApiKeyAuth
|
||||
// @Success 200 {string} string "ok"
|
||||
// @Router /app/speed/{id} [get]
|
||||
func GetInstallSpeed(c *gin.Context) {
|
||||
id := c.Param("id")
|
||||
b := service.MyService.Notify().GetLog(id)
|
||||
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.SUCCESS, Message: oasis_err2.GetMsg(oasis_err2.SUCCESS), Data: b})
|
||||
}
|
||||
|
||||
// @Summary 获取容器状态
|
||||
// @Produce application/json
|
||||
// @Accept application/json
|
||||
@@ -889,19 +844,23 @@ func UpdateSetting(c *gin.Context) {
|
||||
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.INVALID_PARAMS, Message: oasis_err2.GetMsg(oasis_err2.INVALID_PARAMS)})
|
||||
return
|
||||
}
|
||||
var cpd model.CustomizationPostData
|
||||
//var cpd model.CustomizationPostData
|
||||
|
||||
copier.Copy(&cpd, &m)
|
||||
//copier.Copy(&cpd, &m)
|
||||
|
||||
appInfo := service.MyService.App().GetAppDBInfo(id)
|
||||
//appInfo := service.MyService.App().GetAppDBInfo(id)
|
||||
//info, err := service.MyService.Docker().DockerContainerInfo(id)
|
||||
|
||||
var containerId string
|
||||
containerId = appInfo.ContainerId
|
||||
// //check app name is exist
|
||||
// if _, err := service.MyService.Docker().DockerListByName(m.Label); err == nil {
|
||||
// c.JSON(http.StatusOK, model.Result{Success: oasis_err2.ERROR_APP_NAME_EXIST, Message: oasis_err2.GetMsg(oasis_err2.ERROR_APP_NAME_EXIST)})
|
||||
// return
|
||||
// }
|
||||
|
||||
service.MyService.Docker().DockerContainerStop(id)
|
||||
|
||||
portMap, _ := strconv.Atoi(m.PortMap)
|
||||
if !port2.IsPortAvailable(portMap, "tcp") {
|
||||
service.MyService.Docker().DockerContainerStart(id)
|
||||
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.ERROR, Message: "Duplicate port:" + m.PortMap})
|
||||
return
|
||||
}
|
||||
@@ -911,77 +870,54 @@ func UpdateSetting(c *gin.Context) {
|
||||
if u.Protocol == "udp" {
|
||||
t, _ := strconv.Atoi(u.CommendPort)
|
||||
if !port2.IsPortAvailable(t, "udp") {
|
||||
service.MyService.Docker().DockerContainerStart(id)
|
||||
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.ERROR, Message: "Duplicate port:" + u.CommendPort})
|
||||
return
|
||||
}
|
||||
} else if u.Protocol == "tcp" {
|
||||
te, _ := strconv.Atoi(u.CommendPort)
|
||||
if !port2.IsPortAvailable(te, "tcp") {
|
||||
service.MyService.Docker().DockerContainerStart(id)
|
||||
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.ERROR, Message: "Duplicate port:" + u.CommendPort})
|
||||
return
|
||||
}
|
||||
} else if u.Protocol == "both" {
|
||||
t, _ := strconv.Atoi(u.CommendPort)
|
||||
if !port2.IsPortAvailable(t, "udp") {
|
||||
service.MyService.Docker().DockerContainerStart(id)
|
||||
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.ERROR, Message: "Duplicate port:" + u.CommendPort})
|
||||
return
|
||||
}
|
||||
|
||||
te, _ := strconv.Atoi(u.CommendPort)
|
||||
if !port2.IsPortAvailable(te, "tcp") {
|
||||
service.MyService.Docker().DockerContainerStart(id)
|
||||
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.ERROR, Message: "Duplicate port:" + u.CommendPort})
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
service.MyService.Docker().DockerContainerUpdateName(id, id)
|
||||
//service.MyService.Docker().DockerContainerRemove(id, true)
|
||||
|
||||
//如果容器端口均未修改,这不进行处理
|
||||
portsStr, _ := json2.Marshal(m.Ports)
|
||||
containerId, err := service.MyService.Docker().DockerContainerCreate(m.Image, m, m.NetworkModel)
|
||||
if err != nil {
|
||||
service.MyService.Docker().DockerContainerUpdateName(m.Label, id)
|
||||
service.MyService.Docker().DockerContainerStart(id)
|
||||
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.ERROR, Message: oasis_err2.GetMsg(oasis_err2.ERROR)})
|
||||
return
|
||||
}
|
||||
// echo -e "hellow\nworld" >>
|
||||
|
||||
envsStr, _ := json2.Marshal(m.Envs)
|
||||
volumesStr, _ := json2.Marshal(m.Volumes)
|
||||
devicesStr, _ := json2.Marshal(m.Devices)
|
||||
capAddStr, _ := json2.Marshal(m.CapAdd)
|
||||
cmdStr, _ := json.Marshal(m.Cmd)
|
||||
if !reflect.DeepEqual(string(portsStr), appInfo.Ports) || !reflect.DeepEqual(string(envsStr), appInfo.Envs) || !reflect.DeepEqual(string(volumesStr), appInfo.Volumes) || m.PortMap != appInfo.PortMap || m.NetworkModel != appInfo.NetModel || m.HostName != appInfo.HostName || !reflect.DeepEqual(string(cmdStr), appInfo.Cmd) || !reflect.DeepEqual(string(capAddStr), appInfo.CapAdd) || m.Privileged != appInfo.Privileged {
|
||||
|
||||
var newUUid = uuid.NewV4().String()
|
||||
var err error
|
||||
|
||||
// networkName, err := service.MyService.Docker().GetNetWorkNameByNetWorkID(appInfo.NetModel)
|
||||
// if err != nil {
|
||||
// c.JSON(http.StatusOK, model.Result{Success: oasis_err2.ERROR, Message: oasis_err2.GetMsg(oasis_err2.ERROR)})
|
||||
// return
|
||||
// }
|
||||
containerId, err = service.MyService.Docker().DockerContainerCreate(appInfo.Image+":"+appInfo.Version, newUUid, cpd, m.NetworkModel)
|
||||
//step:启动容器
|
||||
err = service.MyService.Docker().DockerContainerStart(containerId)
|
||||
|
||||
if err != nil {
|
||||
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.ERROR, Message: oasis_err2.GetMsg(oasis_err2.ERROR)})
|
||||
return
|
||||
}
|
||||
|
||||
err = service.MyService.Docker().DockerContainerRemove(id, true)
|
||||
if err != nil {
|
||||
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.ERROR, Message: oasis_err2.GetMsg(oasis_err2.ERROR)})
|
||||
return
|
||||
}
|
||||
|
||||
service.MyService.Docker().DockerContainerUpdateName(appInfo.CustomId, newUUid)
|
||||
if err != nil {
|
||||
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.ERROR, Message: oasis_err2.GetMsg(oasis_err2.ERROR)})
|
||||
return
|
||||
}
|
||||
|
||||
} else if !reflect.DeepEqual(string(devicesStr), appInfo.Devices) || m.CpuShares != appInfo.CpuShares || m.Memory != appInfo.Memory || m.Restart != appInfo.Restart {
|
||||
service.MyService.Docker().DockerContainerUpdate(cpd, id)
|
||||
}
|
||||
|
||||
err := service.MyService.Docker().DockerContainerStart(id)
|
||||
if err != nil {
|
||||
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.ERROR, Message: oasis_err2.GetMsg(oasis_err2.ERROR)})
|
||||
return
|
||||
}
|
||||
service.MyService.Docker().DockerContainerRemove(id, true)
|
||||
//更新upnp
|
||||
if m.Origin != CUSTOM {
|
||||
//if appInfo.EnableUPNP != appInfo.EnableUPNP {
|
||||
@@ -1047,31 +983,96 @@ func UpdateSetting(c *gin.Context) {
|
||||
//}
|
||||
}
|
||||
|
||||
appInfo.ContainerId = containerId
|
||||
appInfo.PortMap = m.PortMap
|
||||
appInfo.Label = m.Label
|
||||
appInfo.Index = m.Index
|
||||
appInfo.Ports = string(portsStr)
|
||||
appInfo.Envs = string(envsStr)
|
||||
appInfo.Icon = m.Icon
|
||||
appInfo.Volumes = string(volumesStr)
|
||||
appInfo.Devices = string(devicesStr)
|
||||
appInfo.NetModel = m.NetworkModel
|
||||
appInfo.Position = m.Position
|
||||
appInfo.EnableUPNP = m.EnableUPNP
|
||||
appInfo.Restart = m.Restart
|
||||
appInfo.Memory = m.Memory
|
||||
appInfo.CpuShares = m.CpuShares
|
||||
appInfo.Cmd = string(cmdStr)
|
||||
appInfo.Privileged = m.Privileged
|
||||
appInfo.CapAdd = string(capAddStr)
|
||||
appInfo.HostName = m.HostName
|
||||
appInfo.UpdatedAt = strconv.FormatInt(time.Now().Unix(), 10)
|
||||
service.MyService.App().UpdateApp(appInfo)
|
||||
//service.MyService.App().UpdateApp(appInfo)
|
||||
|
||||
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.SUCCESS, Message: oasis_err2.GetMsg(oasis_err2.SUCCESS)})
|
||||
}
|
||||
|
||||
// @Summary update app version
|
||||
// @Produce application/json
|
||||
// @Accept multipart/form-data
|
||||
// @Tags app
|
||||
// @Param id path string true "容器id"
|
||||
// @Security ApiKeyAuth
|
||||
// @Success 200 {string} string "ok"
|
||||
// @Router /app/update/{id} [put]
|
||||
func PutAppUpdate(c *gin.Context) {
|
||||
id := c.Param("id")
|
||||
|
||||
if len(id) == 0 {
|
||||
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.INVALID_PARAMS, Message: oasis_err2.GetMsg(oasis_err2.INVALID_PARAMS)})
|
||||
return
|
||||
}
|
||||
|
||||
inspect, err := service.MyService.Docker().DockerContainerInfo(id)
|
||||
if err != nil {
|
||||
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.ERROR, Message: oasis_err2.GetMsg(oasis_err2.ERROR), Data: err.Error()})
|
||||
return
|
||||
|
||||
}
|
||||
imageLatest := strings.Split(inspect.Config.Image, ":")[0] + ":latest"
|
||||
err = service.MyService.Docker().DockerPullImage(imageLatest, "", "")
|
||||
if err != nil {
|
||||
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.ERROR, Message: oasis_err2.GetMsg(oasis_err2.ERROR), Data: err.Error()})
|
||||
return
|
||||
|
||||
}
|
||||
service.MyService.Docker().DockerContainerStop(id)
|
||||
service.MyService.Docker().DockerContainerUpdateName(id, id)
|
||||
//service.MyService.Docker().DockerContainerRemove(id, true)
|
||||
inspect.Image = imageLatest
|
||||
inspect.Config.Image = imageLatest
|
||||
containerId, err := service.MyService.Docker().DockerContainerCopyCreate(inspect)
|
||||
if err != nil {
|
||||
service.MyService.Docker().DockerContainerUpdateName(inspect.Name, id)
|
||||
service.MyService.Docker().DockerContainerStart(id)
|
||||
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.ERROR, Message: oasis_err2.GetMsg(oasis_err2.ERROR)})
|
||||
return
|
||||
}
|
||||
|
||||
//step:启动容器
|
||||
err = service.MyService.Docker().DockerContainerStart(containerId)
|
||||
|
||||
if err != nil {
|
||||
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.ERROR, Message: oasis_err2.GetMsg(oasis_err2.ERROR)})
|
||||
return
|
||||
}
|
||||
service.MyService.Docker().DockerContainerRemove(id, true)
|
||||
delete(service.NewVersionApp, id)
|
||||
|
||||
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.SUCCESS, Message: oasis_err2.GetMsg(oasis_err2.SUCCESS)})
|
||||
}
|
||||
|
||||
// @Summary get app index
|
||||
// @Produce application/json
|
||||
// @Accept application/json
|
||||
// @Tags app
|
||||
// @Security ApiKeyAuth
|
||||
// @Success 200 {string} string "ok"
|
||||
// @Router /app/order [get]
|
||||
func GetAppOrder(c *gin.Context) {
|
||||
data := service.MyService.System().GetAppOrderFile()
|
||||
c.JSON(http.StatusOK, model.Result{Success: oasis_err.SUCCESS, Message: oasis_err.GetMsg(oasis_err.SUCCESS), Data: json.RawMessage(data)})
|
||||
}
|
||||
|
||||
// @Summary update app index
|
||||
// @Produce application/json
|
||||
// @Accept application/json
|
||||
// @Tags app
|
||||
// @Security ApiKeyAuth
|
||||
// @Success 200 {string} string "ok"
|
||||
// @Router /app/order [post]
|
||||
func PostAppOrder(c *gin.Context) {
|
||||
data := c.PostForm("data")
|
||||
service.MyService.System().UpAppOrderFile(data)
|
||||
c.JSON(http.StatusOK,
|
||||
model.Result{
|
||||
Success: oasis_err.SUCCESS,
|
||||
Message: oasis_err.GetMsg(oasis_err.SUCCESS),
|
||||
Data: json.RawMessage(data),
|
||||
})
|
||||
}
|
||||
|
||||
// @Summary 获取容器详情
|
||||
// @Produce application/json
|
||||
// @Accept application/json
|
||||
@@ -1109,7 +1110,7 @@ func ContainerInfo(c *gin.Context) {
|
||||
data := make(map[string]interface{}, 5)
|
||||
data["app"] = appInfo
|
||||
data["cpu"] = cpuModel
|
||||
data["memory"] = service.MyService.ZiMa().GetMemInfo().Total
|
||||
data["memory"] = service.MyService.System().GetMemInfo().Total
|
||||
data["container"] = json2.RawMessage(containerInfo)
|
||||
data["info"] = con
|
||||
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.SUCCESS, Message: oasis_err2.GetMsg(oasis_err2.SUCCESS), Data: data})
|
||||
@@ -1132,7 +1133,7 @@ func GetDockerInstallConfig(c *gin.Context) {
|
||||
}
|
||||
}
|
||||
data["networks"] = list
|
||||
data["memory"] = service.MyService.ZiMa().GetMemInfo()
|
||||
data["memory"] = service.MyService.System().GetMemInfo()
|
||||
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.SUCCESS, Message: oasis_err2.GetMsg(oasis_err2.SUCCESS), Data: data})
|
||||
}
|
||||
|
||||
@@ -1160,58 +1161,113 @@ func ContainerRelyInfo(c *gin.Context) {
|
||||
// @Router /app/update/{id}/info [get]
|
||||
func ContainerUpdateInfo(c *gin.Context) {
|
||||
appId := c.Param("id")
|
||||
appInfo := service.MyService.App().GetAppDBInfo(appId)
|
||||
//appInfo := service.MyService.App().GetAppDBInfo(appId)
|
||||
info, err := service.MyService.Docker().DockerContainerInfo(appId)
|
||||
if err != nil {
|
||||
//todo 需要自定义错误
|
||||
|
||||
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.SUCCESS, Message: oasis_err2.GetMsg(oasis_err2.SUCCESS), Data: err.Error()})
|
||||
return
|
||||
}
|
||||
var port model.PortArray
|
||||
json2.Unmarshal([]byte(appInfo.Ports), &port)
|
||||
// json2.Unmarshal([]byte(appInfo.Ports), &port)
|
||||
|
||||
var envs model.EnvArray
|
||||
json2.Unmarshal([]byte(appInfo.Envs), &envs)
|
||||
for k, v := range info.HostConfig.PortBindings {
|
||||
temp := model.PortMap{
|
||||
CommendPort: v[0].HostPort,
|
||||
ContainerPort: k.Port(),
|
||||
|
||||
var vol model.PathArray
|
||||
json2.Unmarshal([]byte(appInfo.Volumes), &vol)
|
||||
|
||||
for i := 0; i < len(vol); i++ {
|
||||
vol[i].Path = strings.ReplaceAll(vol[i].Path, "$AppID", appId)
|
||||
Protocol: k.Proto(),
|
||||
}
|
||||
port = append(port, temp)
|
||||
}
|
||||
|
||||
var dir model.PathArray
|
||||
json2.Unmarshal([]byte(appInfo.Devices), &dir)
|
||||
var envs model.EnvArray
|
||||
// json2.Unmarshal([]byte(appInfo.Envs), &envs)
|
||||
|
||||
showENV := info.Config.Labels["show_env"]
|
||||
showENVList := strings.Split(showENV, ",")
|
||||
showENVMap := make(map[string]string)
|
||||
if len(showENVList) > 1 {
|
||||
for _, name := range showENVList {
|
||||
showENVMap[name] = "1"
|
||||
}
|
||||
}
|
||||
for _, v := range info.Config.Env {
|
||||
if len(showENVList) > 1 {
|
||||
if _, ok := showENVMap[strings.Split(v, "=")[0]]; ok {
|
||||
temp := model.Env{
|
||||
Name: strings.Split(v, "=")[0],
|
||||
Value: strings.Split(v, "=")[1],
|
||||
}
|
||||
envs = append(envs, temp)
|
||||
}
|
||||
} else {
|
||||
temp := model.Env{
|
||||
Name: strings.Split(v, "=")[0],
|
||||
Value: strings.Split(v, "=")[1],
|
||||
}
|
||||
envs = append(envs, temp)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
var vol model.PathArray
|
||||
// json2.Unmarshal([]byte(appInfo.Volumes), &vol)
|
||||
|
||||
for i := 0; i < len(info.Mounts); i++ {
|
||||
temp := model.PathMap{
|
||||
Path: strings.ReplaceAll(info.Mounts[i].Source, "$AppID", info.Name),
|
||||
ContainerPath: info.Mounts[i].Destination,
|
||||
}
|
||||
vol = append(vol, temp)
|
||||
}
|
||||
var driver model.PathArray
|
||||
|
||||
var cmd []string
|
||||
json2.Unmarshal([]byte(appInfo.Cmd), &cmd)
|
||||
var capAdd []string
|
||||
json2.Unmarshal([]byte(appInfo.CapAdd), &capAdd)
|
||||
//volumesStr, _ := json2.Marshal(m.Volumes)
|
||||
//devicesStr, _ := json2.Marshal(m.Devices)
|
||||
for _, v := range info.HostConfig.Resources.Devices {
|
||||
temp := model.PathMap{
|
||||
Path: v.PathOnHost,
|
||||
ContainerPath: v.PathInContainer,
|
||||
}
|
||||
driver = append(driver, temp)
|
||||
}
|
||||
|
||||
m := model.CustomizationPostData{}
|
||||
m.Index = appInfo.Index
|
||||
m.Icon = appInfo.Icon
|
||||
m.Icon = info.Config.Labels["icon"]
|
||||
m.Ports = port
|
||||
m.Image = appInfo.Image + ":" + appInfo.Version
|
||||
m.Origin = appInfo.Origin
|
||||
m.NetworkModel = appInfo.NetModel
|
||||
m.Description = appInfo.Description
|
||||
m.Label = appInfo.Label
|
||||
m.PortMap = appInfo.PortMap
|
||||
m.Devices = dir //appInfo.Devices
|
||||
m.Image = info.Config.Image
|
||||
m.Origin = info.Config.Labels["origin"]
|
||||
if len(m.Origin) == 0 {
|
||||
m.Origin = "local"
|
||||
}
|
||||
m.NetworkModel = string(info.HostConfig.NetworkMode)
|
||||
m.Description = info.Config.Labels["desc"]
|
||||
m.Label = strings.ReplaceAll(info.Name, "/", "")
|
||||
m.PortMap = info.Config.Labels["web"]
|
||||
m.Devices = driver
|
||||
m.Envs = envs
|
||||
m.Memory = info.HostConfig.Memory >> 20
|
||||
m.CpuShares = info.HostConfig.CPUShares
|
||||
m.Volumes = vol //appInfo.Volumes
|
||||
m.Restart = info.HostConfig.RestartPolicy.Name
|
||||
m.EnableUPNP = appInfo.EnableUPNP
|
||||
m.Position = appInfo.Position
|
||||
m.EnableUPNP = false
|
||||
m.Index = info.Config.Labels["index"]
|
||||
m.Position = false
|
||||
m.CustomId = info.Config.Labels["custom_id"]
|
||||
m.Host = info.Config.Labels["host"]
|
||||
if len(m.CustomId) == 0 {
|
||||
m.CustomId = uuid.NewV4().String()
|
||||
}
|
||||
m.CapAdd = info.HostConfig.CapAdd
|
||||
m.Cmd = info.Config.Cmd
|
||||
m.HostName = info.Config.Hostname
|
||||
m.Privileged = info.HostConfig.Privileged
|
||||
|
||||
m.CapAdd = capAdd
|
||||
m.Cmd = cmd
|
||||
m.HostName = appInfo.HostName
|
||||
m.Privileged = appInfo.Privileged
|
||||
m.Protocol = info.Config.Labels["protocol"]
|
||||
if m.Protocol == "" {
|
||||
m.Protocol = "http"
|
||||
}
|
||||
|
||||
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.SUCCESS, Message: oasis_err2.GetMsg(oasis_err2.SUCCESS), Data: m})
|
||||
}
|
||||
|
||||
366
route/v1/file.go
@@ -6,19 +6,25 @@ import (
|
||||
"fmt"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"log"
|
||||
"net/http"
|
||||
"net/url"
|
||||
url2 "net/url"
|
||||
"os"
|
||||
"path"
|
||||
"path/filepath"
|
||||
"strconv"
|
||||
"strings"
|
||||
"sync"
|
||||
|
||||
"github.com/IceWhaleTech/CasaOS/model"
|
||||
"github.com/IceWhaleTech/CasaOS/pkg/config"
|
||||
"github.com/IceWhaleTech/CasaOS/pkg/utils/file"
|
||||
"github.com/IceWhaleTech/CasaOS/pkg/utils/oasis_err"
|
||||
oasis_err2 "github.com/IceWhaleTech/CasaOS/pkg/utils/oasis_err"
|
||||
"github.com/IceWhaleTech/CasaOS/service"
|
||||
"github.com/gin-gonic/gin"
|
||||
"github.com/spf13/afero"
|
||||
uuid "github.com/satori/go.uuid"
|
||||
)
|
||||
|
||||
func downloadReadFile(c *gin.Context) {
|
||||
@@ -47,24 +53,6 @@ func downloadReadFile(c *gin.Context) {
|
||||
}
|
||||
}
|
||||
|
||||
func downloadWriteFile(c *gin.Context) {
|
||||
//写文件
|
||||
var filename = "./output1.csv"
|
||||
|
||||
file, err := os.Create(filename) //创建文件
|
||||
if err != nil {
|
||||
c.String(400, err.Error())
|
||||
return
|
||||
}
|
||||
buf := bufio.NewWriter(file) //创建新的 Writer 对象
|
||||
buf.WriteString("test")
|
||||
buf.Flush()
|
||||
defer file.Close()
|
||||
|
||||
//返回文件流
|
||||
c.File(filename)
|
||||
}
|
||||
|
||||
// @Summary 读取文件
|
||||
// @Produce application/json
|
||||
// @Accept application/json
|
||||
@@ -134,82 +122,106 @@ func GetLocalFile(c *gin.Context) {
|
||||
// @Accept application/json
|
||||
// @Tags file
|
||||
// @Security ApiKeyAuth
|
||||
// @Param path query string true "path of file"
|
||||
// @Param t query string false "Compression format" Enums(zip,tar,targz)
|
||||
// @Param files query string true "file list eg: filename1,filename2,filename3 "
|
||||
// @Success 200 {string} string "ok"
|
||||
// @Router /file/download [get]
|
||||
func GetDownloadFile(c *gin.Context) {
|
||||
filePath := c.Query("path")
|
||||
if len(filePath) == 0 {
|
||||
|
||||
t := c.Query("t")
|
||||
|
||||
files := c.Query("files")
|
||||
|
||||
if len(files) == 0 {
|
||||
c.JSON(http.StatusOK, model.Result{
|
||||
Success: oasis_err2.INVALID_PARAMS,
|
||||
Message: oasis_err2.GetMsg(oasis_err2.INVALID_PARAMS),
|
||||
})
|
||||
return
|
||||
}
|
||||
if !file.Exists(filePath) {
|
||||
list := strings.Split(files, ",")
|
||||
for _, v := range list {
|
||||
if !file.Exists(v) {
|
||||
c.JSON(http.StatusOK, model.Result{
|
||||
Success: oasis_err2.FILE_DOES_NOT_EXIST,
|
||||
Message: oasis_err2.GetMsg(oasis_err2.FILE_DOES_NOT_EXIST),
|
||||
})
|
||||
return
|
||||
}
|
||||
}
|
||||
c.Header("Content-Type", "application/octet-stream")
|
||||
c.Header("Content-Transfer-Encoding", "binary")
|
||||
c.Header("Cache-Control", "no-cache")
|
||||
// handles only single files not folders and multiple files
|
||||
if len(list) == 1 {
|
||||
|
||||
filePath := list[0]
|
||||
info, err := os.Stat(filePath)
|
||||
if err != nil {
|
||||
c.JSON(http.StatusOK, model.Result{
|
||||
Success: oasis_err2.FILE_DOES_NOT_EXIST,
|
||||
Message: oasis_err2.GetMsg(oasis_err2.FILE_DOES_NOT_EXIST),
|
||||
})
|
||||
return
|
||||
}
|
||||
if !info.IsDir() {
|
||||
|
||||
//打开文件
|
||||
fileTmp, _ := os.Open(filePath)
|
||||
defer fileTmp.Close()
|
||||
|
||||
//获取文件的名称
|
||||
fileName := path.Base(filePath)
|
||||
c.Header("Content-Type", "application/octet-stream")
|
||||
c.Header("Content-Disposition", "attachment; filename*=utf-8''"+url2.PathEscape(fileName))
|
||||
c.Header("Content-Transfer-Encoding", "binary")
|
||||
c.Header("Cache-Control", "no-cache")
|
||||
|
||||
c.File(filePath)
|
||||
}
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
// @Summary download
|
||||
// @Produce application/json
|
||||
// @Accept application/json
|
||||
// @Tags file
|
||||
// @Security ApiKeyAuth
|
||||
// @Param path query string true "path of file"
|
||||
// @Success 200 {string} string "ok"
|
||||
// @Router /file/new/download [get]
|
||||
func GetFileDownloadNew(c *gin.Context) {
|
||||
filePath := c.Query("path")
|
||||
if len(filePath) == 0 {
|
||||
extension, ar, err := file.GetCompressionAlgorithm(t)
|
||||
if err != nil {
|
||||
c.JSON(http.StatusOK, model.Result{
|
||||
Success: oasis_err2.INVALID_PARAMS,
|
||||
Message: oasis_err2.GetMsg(oasis_err2.INVALID_PARAMS),
|
||||
})
|
||||
return
|
||||
}
|
||||
if !file.Exists(filePath) {
|
||||
|
||||
err = ar.Create(c.Writer)
|
||||
if err != nil {
|
||||
c.JSON(http.StatusOK, model.Result{
|
||||
Success: oasis_err2.FILE_DOES_NOT_EXIST,
|
||||
Message: oasis_err2.GetMsg(oasis_err2.FILE_DOES_NOT_EXIST),
|
||||
Success: oasis_err.ERROR,
|
||||
Message: oasis_err2.GetMsg(oasis_err2.ERROR),
|
||||
Data: err.Error(),
|
||||
})
|
||||
return
|
||||
}
|
||||
//打开文件
|
||||
fileStat, _ := os.Stat(filePath)
|
||||
var AppFs = afero.NewOsFs()
|
||||
fileT, _ := AppFs.Open(filePath)
|
||||
//fileTmp, _ := os.Open(filePath)
|
||||
//defer fileTmp.Close()
|
||||
//获取文件的名称
|
||||
//fileName := path.Base(filePath)
|
||||
defer ar.Close()
|
||||
commonDir := file.CommonPrefix(filepath.Separator, list...)
|
||||
|
||||
//c.Header("Content-Disposition", "attachment; filename*=utf-8''"+url2.PathEscape(fileName))
|
||||
//在线
|
||||
currentPath := filepath.Base(commonDir)
|
||||
|
||||
name := "_" + currentPath
|
||||
name += extension
|
||||
c.Header("Content-Disposition", "attachment; filename*=utf-8''"+url.PathEscape(name))
|
||||
for _, fname := range list {
|
||||
err = file.AddFile(ar, fname, commonDir)
|
||||
if err != nil {
|
||||
log.Printf("Failed to archive %s: %v", fname, err)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
func GetDownloadSingleFile(c *gin.Context) {
|
||||
filePath := c.Param("path")
|
||||
fileTmp, _ := os.Open(filePath)
|
||||
defer fileTmp.Close()
|
||||
|
||||
fileName := path.Base(filePath)
|
||||
//c.Header("Content-Disposition", "inline")
|
||||
// extraHeaders := map[string]string{
|
||||
// "Content-Disposition": `attachment; filename="` + url2.PathEscape(fileName) + `"`,
|
||||
// }
|
||||
|
||||
//c.Header("Cache-Control", "private")
|
||||
//c.Header("Content-Type", "application/octet-stream")
|
||||
|
||||
http.ServeContent(c.Writer, c.Request, fileStat.Name(), fileStat.ModTime(), fileT)
|
||||
c.Header("Content-Disposition", "attachment; filename*=utf-8''"+url2.PathEscape(fileName))
|
||||
c.File(filePath)
|
||||
}
|
||||
|
||||
// @Summary 获取目录列表
|
||||
@@ -224,10 +236,10 @@ func DirPath(c *gin.Context) {
|
||||
path := c.DefaultQuery("path", "")
|
||||
info := service.MyService.ZiMa().GetDirPath(path)
|
||||
if path == "/DATA/AppData" {
|
||||
list := service.MyService.App().GetAllDBApps()
|
||||
list := service.MyService.Docker().DockerContainerList()
|
||||
apps := make(map[string]string, len(list))
|
||||
for _, v := range list {
|
||||
apps[v.CustomId] = v.Label
|
||||
apps[strings.ReplaceAll(v.Names[0], "/", "")] = strings.ReplaceAll(v.Names[0], "/", "")
|
||||
}
|
||||
for i := 0; i < len(info); i++ {
|
||||
if v, ok := apps[info[i].Name]; ok {
|
||||
@@ -263,7 +275,30 @@ func DirPath(c *gin.Context) {
|
||||
}
|
||||
}
|
||||
|
||||
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.SUCCESS, Message: oasis_err2.GetMsg(oasis_err2.SUCCESS), Data: info})
|
||||
//Hide the files or folders in operation
|
||||
fileQueue := make(map[string]string)
|
||||
if len(service.OpStrArr) > 0 {
|
||||
for _, v := range service.OpStrArr {
|
||||
v, ok := service.FileQueue.Load(v)
|
||||
if !ok {
|
||||
continue
|
||||
}
|
||||
vt := v.(model.FileOperate)
|
||||
for _, i := range vt.Item {
|
||||
lastPath := i.From[strings.LastIndex(i.From, "/")+1:]
|
||||
fileQueue[vt.To+"/"+lastPath] = i.From
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pathList := []model.Path{}
|
||||
for i := 0; i < len(info); i++ {
|
||||
if _, ok := fileQueue[info[i].Path]; !ok {
|
||||
pathList = append(pathList, info[i])
|
||||
}
|
||||
}
|
||||
|
||||
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.SUCCESS, Message: oasis_err2.GetMsg(oasis_err2.SUCCESS), Data: pathList})
|
||||
}
|
||||
|
||||
// @Summary rename file or dir
|
||||
@@ -271,13 +306,15 @@ func DirPath(c *gin.Context) {
|
||||
// @Accept application/json
|
||||
// @Tags file
|
||||
// @Security ApiKeyAuth
|
||||
// @Param oldpath formData string true "path of old"
|
||||
// @Param newpath formData string true "path of new"
|
||||
// @Param oldpath body string true "path of old"
|
||||
// @Param newpath body string true "path of new"
|
||||
// @Success 200 {string} string "ok"
|
||||
// @Router /file/rename [put]
|
||||
func RenamePath(c *gin.Context) {
|
||||
op := c.PostForm("oldpath")
|
||||
np := c.PostForm("newpath")
|
||||
json := make(map[string]string)
|
||||
c.BindJSON(&json)
|
||||
op := json["oldpath"]
|
||||
np := json["newpath"]
|
||||
if len(op) == 0 || len(np) == 0 {
|
||||
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.INVALID_PARAMS, Message: oasis_err2.GetMsg(oasis_err2.INVALID_PARAMS)})
|
||||
return
|
||||
@@ -288,45 +325,59 @@ func RenamePath(c *gin.Context) {
|
||||
|
||||
// @Summary create folder
|
||||
// @Produce application/json
|
||||
// @Accept multipart/form-data
|
||||
// @Accept application/json
|
||||
// @Tags file
|
||||
// @Security ApiKeyAuth
|
||||
// @Param path formData string true "path of folder"
|
||||
// @Param path body string true "path of folder"
|
||||
// @Success 200 {string} string "ok"
|
||||
// @Router /file/mkdir [post]
|
||||
func MkdirAll(c *gin.Context) {
|
||||
path := c.PostForm("path")
|
||||
json := make(map[string]string)
|
||||
c.BindJSON(&json)
|
||||
path := json["path"]
|
||||
var code int
|
||||
if len(path) == 0 {
|
||||
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.INVALID_PARAMS, Message: oasis_err2.GetMsg(oasis_err2.INVALID_PARAMS)})
|
||||
return
|
||||
}
|
||||
// decodedPath, err := url.QueryUnescape(path)
|
||||
// if err != nil {
|
||||
// c.JSON(http.StatusOK, model.Result{Success: oasis_err2.INVALID_PARAMS, Message: oasis_err2.GetMsg(oasis_err2.INVALID_PARAMS)})
|
||||
// return
|
||||
// }
|
||||
code, _ = service.MyService.ZiMa().MkdirAll(path)
|
||||
c.JSON(http.StatusOK, model.Result{Success: code, Message: oasis_err2.GetMsg(code)})
|
||||
}
|
||||
|
||||
// @Summary create file
|
||||
// @Produce application/json
|
||||
// @Accept multipart/form-data
|
||||
// @Accept application/json
|
||||
// @Tags file
|
||||
// @Security ApiKeyAuth
|
||||
// @Param path formData string false "路径"
|
||||
// @Param path body string true "path of folder (path need to url encode)"
|
||||
// @Success 200 {string} string "ok"
|
||||
// @Router /file/create [post]
|
||||
func PostCreateFile(c *gin.Context) {
|
||||
path := c.PostForm("path")
|
||||
json := make(map[string]string)
|
||||
c.BindJSON(&json)
|
||||
path := json["path"]
|
||||
var code int
|
||||
if len(path) == 0 {
|
||||
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.INVALID_PARAMS, Message: oasis_err2.GetMsg(oasis_err2.INVALID_PARAMS)})
|
||||
return
|
||||
}
|
||||
// decodedPath, err := url.QueryUnescape(path)
|
||||
// if err != nil {
|
||||
// c.JSON(http.StatusOK, model.Result{Success: oasis_err2.INVALID_PARAMS, Message: oasis_err2.GetMsg(oasis_err2.INVALID_PARAMS)})
|
||||
// return
|
||||
// }
|
||||
code, _ = service.MyService.ZiMa().CreateFile(path)
|
||||
c.JSON(http.StatusOK, model.Result{Success: code, Message: oasis_err2.GetMsg(code)})
|
||||
}
|
||||
|
||||
// @Summary upload file
|
||||
// @Produce application/json
|
||||
// @Accept multipart/form-data
|
||||
// @Accept application/json
|
||||
// @Tags file
|
||||
// @Security ApiKeyAuth
|
||||
// @Param path formData string false "file path"
|
||||
@@ -342,7 +393,7 @@ func GetFileUpload(c *gin.Context) {
|
||||
path := c.Query("path")
|
||||
dirPath := ""
|
||||
hash := file.GetHashByContent([]byte(fileName))
|
||||
tempDir := "/casaOS/temp/" + hash + strconv.Itoa(totalChunks) + "/"
|
||||
tempDir := config.AppInfo.RootPath + "/temp/" + hash + strconv.Itoa(totalChunks) + "/"
|
||||
if fileName != relative {
|
||||
dirPath = strings.TrimSuffix(relative, fileName)
|
||||
tempDir += dirPath
|
||||
@@ -381,7 +432,7 @@ func PostFileUpload(c *gin.Context) {
|
||||
c.JSON(oasis_err2.INVALID_PARAMS, model.Result{Success: oasis_err2.INVALID_PARAMS, Message: oasis_err2.GetMsg(oasis_err2.INVALID_PARAMS)})
|
||||
return
|
||||
}
|
||||
tempDir := "/casaOS/temp/" + hash + strconv.Itoa(totalChunks) + "/"
|
||||
tempDir := config.AppInfo.RootPath + "/temp/" + hash + strconv.Itoa(totalChunks) + "/"
|
||||
|
||||
if fileName != relative {
|
||||
dirPath = strings.TrimSuffix(relative, fileName)
|
||||
@@ -431,94 +482,177 @@ func PostFileUpload(c *gin.Context) {
|
||||
|
||||
// @Summary copy or move file
|
||||
// @Produce application/json
|
||||
// @Accept multipart/form-data
|
||||
// @Accept application/json
|
||||
// @Tags file
|
||||
// @Security ApiKeyAuth
|
||||
// @Param from formData string true "from path"
|
||||
// @Param to formData string true "to path"
|
||||
// @Param type formData string true "action" Enums(move,copy)
|
||||
// @Param body body model.FileOperate true "type:move,copy"
|
||||
// @Success 200 {string} string "ok"
|
||||
// @Router /file/operate [post]
|
||||
func PostOperateFileOrDir(c *gin.Context) {
|
||||
from := c.PostForm("from")
|
||||
to := c.PostForm("to")
|
||||
t := c.PostForm("type")
|
||||
if len(from) == 0 || len(t) == 0 || len(to) == 0 {
|
||||
|
||||
list := model.FileOperate{}
|
||||
c.BindJSON(&list)
|
||||
|
||||
if len(list.Item) == 0 {
|
||||
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.INVALID_PARAMS, Message: oasis_err2.GetMsg(oasis_err2.INVALID_PARAMS)})
|
||||
return
|
||||
}
|
||||
if t == "move" {
|
||||
lastPath := from[strings.LastIndex(from, "/")+1:]
|
||||
if !file.CheckNotExist(to + "/" + lastPath) {
|
||||
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.FILE_OR_DIR_EXISTS, Message: oasis_err2.GetMsg(oasis_err2.FILE_ALREADY_EXISTS)})
|
||||
if list.To == list.Item[0].From[:strings.LastIndex(list.Item[0].From, "/")] {
|
||||
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.SOURCE_DES_SAME, Message: oasis_err2.GetMsg(oasis_err2.SOURCE_DES_SAME)})
|
||||
return
|
||||
}
|
||||
err := os.Rename(from, to+"/"+lastPath)
|
||||
|
||||
var total int64 = 0
|
||||
for i := 0; i < len(list.Item); i++ {
|
||||
|
||||
size, err := file.GetFileOrDirSize(list.Item[i].From)
|
||||
if err != nil {
|
||||
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.ERROR, Message: oasis_err2.GetMsg(oasis_err2.ERROR), Data: err.Error()})
|
||||
return
|
||||
continue
|
||||
}
|
||||
} else if t == "copy" {
|
||||
err := file.CopyDir(from, to)
|
||||
if err != nil {
|
||||
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.ERROR, Message: oasis_err2.GetMsg(oasis_err2.ERROR), Data: err.Error()})
|
||||
return
|
||||
list.Item[i].Size = size
|
||||
total += size
|
||||
}
|
||||
} else {
|
||||
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.INVALID_PARAMS, Message: oasis_err2.GetMsg(oasis_err2.INVALID_PARAMS)})
|
||||
return
|
||||
|
||||
list.TotalSize = total
|
||||
list.ProcessedSize = 0
|
||||
|
||||
uid := uuid.NewV4().String()
|
||||
service.FileQueue.Store(uid, list)
|
||||
service.OpStrArr = append(service.OpStrArr, uid)
|
||||
|
||||
if len(service.OpStrArr) == 1 {
|
||||
go service.ExecOpFile()
|
||||
go service.CheckFileStatus()
|
||||
|
||||
go service.MyService.Notify().SendFileOperateNotify(false)
|
||||
|
||||
}
|
||||
|
||||
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.SUCCESS, Message: oasis_err2.GetMsg(oasis_err2.SUCCESS)})
|
||||
}
|
||||
|
||||
// @Summary delete file
|
||||
// @Produce application/json
|
||||
// @Accept multipart/form-data
|
||||
// @Accept application/json
|
||||
// @Tags file
|
||||
// @Security ApiKeyAuth
|
||||
// @Param path query string true "path"
|
||||
// @Param body body string true "paths eg ["/a/b/c","/d/e/f"]"
|
||||
// @Success 200 {string} string "ok"
|
||||
// @Router /file/delete [delete]
|
||||
func DeleteFile(c *gin.Context) {
|
||||
path := c.Query("path")
|
||||
//err := os.Remove(path)
|
||||
err := os.RemoveAll(path)
|
||||
|
||||
paths := []string{}
|
||||
c.BindJSON(&paths)
|
||||
if len(paths) == 0 {
|
||||
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.INVALID_PARAMS, Message: oasis_err2.GetMsg(oasis_err2.INVALID_PARAMS)})
|
||||
return
|
||||
}
|
||||
// path := c.Query("path")
|
||||
|
||||
// paths := strings.Split(path, ",")
|
||||
|
||||
for _, v := range paths {
|
||||
err := os.RemoveAll(v)
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.FILE_DELETE_ERROR, Message: oasis_err2.GetMsg(oasis_err2.FILE_DELETE_ERROR), Data: err})
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.SUCCESS, Message: oasis_err2.GetMsg(oasis_err2.SUCCESS)})
|
||||
}
|
||||
|
||||
// @Summary update file
|
||||
// @Produce application/json
|
||||
// @Accept multipart/form-data
|
||||
// @Accept application/json
|
||||
// @Tags file
|
||||
// @Security ApiKeyAuth
|
||||
// @Param path formData string true "path"
|
||||
// @Param content formData string true "content"
|
||||
// @Param path body string true "path"
|
||||
// @Param content body string true "content"
|
||||
// @Success 200 {string} string "ok"
|
||||
// @Router /file/update [put]
|
||||
func PutFileContent(c *gin.Context) {
|
||||
path := c.PostForm("path")
|
||||
content := c.PostForm("content")
|
||||
if !file.Exists(path) {
|
||||
c.JSON(oasis_err2.FILE_ALREADY_EXISTS, model.Result{Success: oasis_err2.FILE_ALREADY_EXISTS, Message: oasis_err2.GetMsg(oasis_err2.FILE_ALREADY_EXISTS)})
|
||||
|
||||
fi := model.FileUpdate{}
|
||||
c.BindJSON(&fi)
|
||||
|
||||
// path := c.PostForm("path")
|
||||
// content := c.PostForm("content")
|
||||
if !file.Exists(fi.FilePath) {
|
||||
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.FILE_ALREADY_EXISTS, Message: oasis_err2.GetMsg(oasis_err2.FILE_ALREADY_EXISTS)})
|
||||
return
|
||||
}
|
||||
//err := os.Remove(path)
|
||||
err := os.RemoveAll(path)
|
||||
err := os.RemoveAll(fi.FilePath)
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.FILE_DELETE_ERROR, Message: oasis_err2.GetMsg(oasis_err2.FILE_DELETE_ERROR), Data: err})
|
||||
return
|
||||
}
|
||||
err = file.CreateFileAndWriteContent(path, content)
|
||||
err = file.CreateFileAndWriteContent(fi.FilePath, fi.FileContent)
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.ERROR, Message: oasis_err2.GetMsg(oasis_err2.ERROR), Data: err})
|
||||
return
|
||||
}
|
||||
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.SUCCESS, Message: oasis_err2.GetMsg(oasis_err2.SUCCESS)})
|
||||
}
|
||||
|
||||
// @Summary image thumbnail/original image
|
||||
// @Produce application/json
|
||||
// @Accept application/json
|
||||
// @Tags file
|
||||
// @Security ApiKeyAuth
|
||||
// @Param path query string true "path"
|
||||
// @Param type query string false "original,thumbnail" Enums(original,thumbnail)
|
||||
// @Success 200 {string} string "ok"
|
||||
// @Router /file/image [get]
|
||||
func GetFileImage(c *gin.Context) {
|
||||
t := c.Query("type")
|
||||
path := c.Query("path")
|
||||
if !file.Exists(path) {
|
||||
c.JSON(http.StatusInternalServerError, model.Result{Success: oasis_err2.FILE_ALREADY_EXISTS, Message: oasis_err2.GetMsg(oasis_err2.FILE_ALREADY_EXISTS)})
|
||||
return
|
||||
}
|
||||
if t == "thumbnail" {
|
||||
f, err := file.GetImage(path, 100, 0)
|
||||
if err != nil {
|
||||
c.JSON(http.StatusInternalServerError, model.Result{Success: oasis_err2.ERROR, Message: oasis_err2.GetMsg(oasis_err2.ERROR), Data: err.Error()})
|
||||
return
|
||||
}
|
||||
c.Writer.WriteString(string(f))
|
||||
return
|
||||
}
|
||||
f, err := os.Open(path)
|
||||
if err != nil {
|
||||
c.JSON(http.StatusInternalServerError, model.Result{Success: oasis_err2.ERROR, Message: oasis_err2.GetMsg(oasis_err2.ERROR), Data: err.Error()})
|
||||
return
|
||||
}
|
||||
defer f.Close()
|
||||
data, err := ioutil.ReadAll(f)
|
||||
if err != nil {
|
||||
c.JSON(http.StatusInternalServerError, model.Result{Success: oasis_err2.ERROR, Message: oasis_err2.GetMsg(oasis_err2.ERROR), Data: err.Error()})
|
||||
return
|
||||
}
|
||||
c.Writer.WriteString(string(data))
|
||||
}
|
||||
|
||||
func DeleteOperateFileOrDir(c *gin.Context) {
|
||||
id := c.Param("id")
|
||||
if id == "0" {
|
||||
service.FileQueue = sync.Map{}
|
||||
service.OpStrArr = []string{}
|
||||
} else {
|
||||
|
||||
service.FileQueue.Delete(id)
|
||||
tempList := []string{}
|
||||
for _, v := range service.OpStrArr {
|
||||
if v != id {
|
||||
tempList = append(tempList, v)
|
||||
}
|
||||
}
|
||||
service.OpStrArr = tempList
|
||||
|
||||
}
|
||||
|
||||
go service.MyService.Notify().SendFileOperateNotify(true)
|
||||
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.SUCCESS, Message: oasis_err2.GetMsg(oasis_err2.SUCCESS)})
|
||||
}
|
||||
|
||||
@@ -1,62 +1,5 @@
|
||||
package v1
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net/http"
|
||||
|
||||
"github.com/IceWhaleTech/CasaOS/service"
|
||||
"github.com/IceWhaleTech/CasaOS/types"
|
||||
"github.com/gin-gonic/gin"
|
||||
"github.com/gorilla/websocket"
|
||||
)
|
||||
|
||||
var upGrader = websocket.Upgrader{
|
||||
CheckOrigin: func(r *http.Request) bool {
|
||||
return true
|
||||
},
|
||||
}
|
||||
|
||||
// @Summary websocket 接口,连接成功后发送一个"notify"字符串
|
||||
// @Produce application/json
|
||||
// @Accept application/json
|
||||
// @Tags notify
|
||||
// @Security ApiKeyAuth
|
||||
// @Param token path string true "token"
|
||||
// @Success 200 {string} string "ok"
|
||||
// @Router /notify/ws [get]
|
||||
func NotifyWS(c *gin.Context) {
|
||||
//升级get请求为webSocket协议
|
||||
ws, err := upGrader.Upgrade(c.Writer, c.Request, nil)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
defer ws.Close()
|
||||
service.WebSocketConns = append(service.WebSocketConns, ws)
|
||||
|
||||
if !service.SocketRun {
|
||||
service.SocketRun = true
|
||||
service.SendMeg()
|
||||
}
|
||||
for {
|
||||
mt, message, err := ws.ReadMessage()
|
||||
fmt.Println(mt, message, err)
|
||||
}
|
||||
func aaa() {
|
||||
|
||||
}
|
||||
|
||||
// @Summary 标记notify已读
|
||||
// @Produce application/json
|
||||
// @Accept application/json
|
||||
// @Tags notify
|
||||
// @Security ApiKeyAuth
|
||||
// @Success 200 {string} string "ok"
|
||||
// @Router /notify/read/{id} [put]
|
||||
func PutNotifyRead(c *gin.Context) {
|
||||
id := c.Param("id")
|
||||
// if len(id) == 0 {
|
||||
// c.JSON(http.StatusOK, model.Result{Success: oasis_err.INVALID_PARAMS, Message: oasis_err.GetMsg(oasis_err.INVALID_PARAMS)})
|
||||
// return
|
||||
// }
|
||||
fmt.Println(id)
|
||||
service.MyService.Notify().MarkRead(id, types.NOTIFY_READ)
|
||||
}
|
||||
|
||||
62
route/v1/notify_old.go
Normal file
@@ -0,0 +1,62 @@
|
||||
package v1
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net/http"
|
||||
|
||||
"github.com/IceWhaleTech/CasaOS/service"
|
||||
"github.com/IceWhaleTech/CasaOS/types"
|
||||
"github.com/gin-gonic/gin"
|
||||
"github.com/gorilla/websocket"
|
||||
)
|
||||
|
||||
var upGrader = websocket.Upgrader{
|
||||
CheckOrigin: func(r *http.Request) bool {
|
||||
return true
|
||||
},
|
||||
}
|
||||
|
||||
// @Summary websocket 接口,连接成功后发送一个"notify"字符串
|
||||
// @Produce application/json
|
||||
// @Accept application/json
|
||||
// @Tags notify
|
||||
// @Security ApiKeyAuth
|
||||
// @Param token path string true "token"
|
||||
// @Success 200 {string} string "ok"
|
||||
// @Router /notify/ws [get]
|
||||
func NotifyWS(c *gin.Context) {
|
||||
//升级get请求为webSocket协议
|
||||
ws, err := upGrader.Upgrade(c.Writer, c.Request, nil)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
defer ws.Close()
|
||||
service.WebSocketConns = append(service.WebSocketConns, ws)
|
||||
|
||||
if !service.SocketRun {
|
||||
service.SocketRun = true
|
||||
service.SendMeg()
|
||||
}
|
||||
for {
|
||||
mt, message, err := ws.ReadMessage()
|
||||
fmt.Println(mt, message, err)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// @Summary 标记notify已读
|
||||
// @Produce application/json
|
||||
// @Accept application/json
|
||||
// @Tags notify
|
||||
// @Security ApiKeyAuth
|
||||
// @Success 200 {string} string "ok"
|
||||
// @Router /notify/read/{id} [put]
|
||||
func PutNotifyRead(c *gin.Context) {
|
||||
id := c.Param("id")
|
||||
// if len(id) == 0 {
|
||||
// c.JSON(http.StatusOK, model.Result{Success: oasis_err.INVALID_PARAMS, Message: oasis_err.GetMsg(oasis_err.INVALID_PARAMS)})
|
||||
// return
|
||||
// }
|
||||
fmt.Println(id)
|
||||
service.MyService.Notify().MarkRead(id, types.NOTIFY_READ)
|
||||
}
|
||||
@@ -1,18 +1,24 @@
|
||||
package v1
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/base64"
|
||||
"encoding/gob"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"net"
|
||||
"net/http"
|
||||
"os"
|
||||
"reflect"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
natType "github.com/Curtis-Milo/nat-type-identifier-go"
|
||||
"github.com/IceWhaleTech/CasaOS/model"
|
||||
"github.com/IceWhaleTech/CasaOS/pkg/config"
|
||||
"github.com/IceWhaleTech/CasaOS/pkg/utils/file"
|
||||
"github.com/IceWhaleTech/CasaOS/pkg/utils/ip_helper"
|
||||
oasis_err2 "github.com/IceWhaleTech/CasaOS/pkg/utils/oasis_err"
|
||||
"github.com/IceWhaleTech/CasaOS/service"
|
||||
model2 "github.com/IceWhaleTech/CasaOS/service/model"
|
||||
@@ -21,33 +27,6 @@ import (
|
||||
uuid "github.com/satori/go.uuid"
|
||||
)
|
||||
|
||||
func PersonTest(c *gin.Context) {
|
||||
token := c.Query("token")
|
||||
_, err := uuid.FromString(token)
|
||||
fmt.Println(err)
|
||||
|
||||
//service.MyService.Person().GetPersionInfo("fb2333a1-72b2-4cb4-9e31-61ccaffa55b9")
|
||||
|
||||
msg := model.MessageModel{}
|
||||
msg.Type = types.PERSONHELLO
|
||||
msg.Data = ""
|
||||
msg.From = config.ServerInfo.Token
|
||||
msg.To = token
|
||||
msg.UUId = uuid.NewV4().String()
|
||||
|
||||
dd, err := service.Dial(msg, true)
|
||||
if err == nil {
|
||||
fmt.Println(err)
|
||||
}
|
||||
fmt.Println(dd)
|
||||
user := service.MyService.Casa().GetUserInfoByShareId(token)
|
||||
if reflect.DeepEqual(user, model.UserInfo{}) {
|
||||
fmt.Println("空数据")
|
||||
}
|
||||
fmt.Println(user)
|
||||
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.SUCCESS, Message: oasis_err2.GetMsg(oasis_err2.SUCCESS)})
|
||||
}
|
||||
|
||||
// @Summary Retry the file that failed to download
|
||||
// @Produce application/json
|
||||
// @Accept application/json
|
||||
@@ -135,7 +114,7 @@ func GetPersonFile(c *gin.Context) {
|
||||
task.Size = 0
|
||||
task.State = types.DOWNLOADAWAIT
|
||||
task.Created = time.Now().Unix()
|
||||
task.Type = 0
|
||||
task.Type = types.PERSONFILEDOWNLOAD
|
||||
task.LocalPath = localPath
|
||||
if service.MyService.Download().GetDownloadListByPath(task) > 0 {
|
||||
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.PERSON_EXIST_DOWNLOAD, Message: oasis_err2.GetMsg(oasis_err2.PERSON_EXIST_DOWNLOAD)})
|
||||
@@ -197,7 +176,7 @@ func DeletePersonDownloadFile(c *gin.Context) {
|
||||
// @Router /person/list [get]
|
||||
func GetPersonDownloadList(c *gin.Context) {
|
||||
state := c.DefaultQuery("state", "")
|
||||
list := service.MyService.Download().GetDownloadListByState(state)
|
||||
list := service.MyService.Download().GetDownloadListByState(state, types.PERSONFILEDOWNLOAD)
|
||||
//if it is downloading, it need to add 'already'
|
||||
for i := 0; i < len(list); i++ {
|
||||
if list[i].State == types.DOWNLOADING {
|
||||
@@ -235,6 +214,79 @@ func PutPersonRemarks(c *gin.Context) {
|
||||
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.SUCCESS, Message: oasis_err2.GetMsg(oasis_err2.SUCCESS)})
|
||||
}
|
||||
|
||||
// @Summary edit friend's
|
||||
// @Produce application/json
|
||||
// @Accept application/json
|
||||
// @Tags person
|
||||
// @Param write formData bool true "write"
|
||||
// @Security ApiKeyAuth
|
||||
// @Success 200 {string} string "ok"
|
||||
// @Router /person/write/{shareid} [put]
|
||||
func PutPersonWrite(c *gin.Context) {
|
||||
token := c.Param("shareid")
|
||||
_, err := uuid.FromString(token)
|
||||
if err != nil {
|
||||
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.INVALID_PARAMS, Message: oasis_err2.GetMsg(oasis_err2.INVALID_PARAMS)})
|
||||
return
|
||||
}
|
||||
write, _ := strconv.ParseBool(c.PostForm("write"))
|
||||
friend := model2.FriendModel{}
|
||||
friend.Token = token
|
||||
friend.Write = write
|
||||
service.MyService.Friend().EditFriendMark(friend)
|
||||
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.SUCCESS, Message: oasis_err2.GetMsg(oasis_err2.SUCCESS)})
|
||||
}
|
||||
|
||||
// @Summary image thumbnail
|
||||
// @Produce application/json
|
||||
// @Accept application/json
|
||||
// @Tags person
|
||||
// @Param write formData bool true "write"
|
||||
// @Security ApiKeyAuth
|
||||
// @Success 200 {string} string "ok"
|
||||
// @Router /person/image/thumbnail/{shareid} [get]
|
||||
func GetPersonImageThumbnail(c *gin.Context) {
|
||||
token := c.Param("shareid")
|
||||
path := c.Query("path")
|
||||
_, err := uuid.FromString(token)
|
||||
if err != nil || len(path) == 0 {
|
||||
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.INVALID_PARAMS, Message: oasis_err2.GetMsg(oasis_err2.INVALID_PARAMS)})
|
||||
return
|
||||
}
|
||||
uuid := uuid.NewV4().String()
|
||||
m := model.MessageModel{}
|
||||
m.Data = path
|
||||
m.From = config.ServerInfo.Token
|
||||
m.To = token
|
||||
m.Type = types.PERSONIMAGETHUMBNAIL
|
||||
m.UUId = uuid
|
||||
|
||||
img, err := service.Dial(m, false)
|
||||
if err != nil {
|
||||
c.JSON(http.StatusInternalServerError, model.Result{Success: oasis_err2.ERROR, Message: oasis_err2.GetMsg(oasis_err2.ERROR), Data: err.Error()})
|
||||
return
|
||||
}
|
||||
|
||||
// var buf bytes.Buffer
|
||||
//err = gob.NewEncoder(&buf).Encode(img.Data)
|
||||
|
||||
if err != nil {
|
||||
c.JSON(http.StatusInternalServerError, model.Result{Success: oasis_err2.ERROR, Message: oasis_err2.GetMsg(oasis_err2.ERROR), Data: err.Error()})
|
||||
return
|
||||
}
|
||||
var buf bytes.Buffer
|
||||
err = gob.NewEncoder(&buf).Encode(img.Data)
|
||||
if err != nil {
|
||||
c.JSON(http.StatusInternalServerError, model.Result{Success: oasis_err2.ERROR, Message: oasis_err2.GetMsg(oasis_err2.ERROR), Data: err.Error()})
|
||||
return
|
||||
}
|
||||
|
||||
imageBuffer, _ := base64.StdEncoding.DecodeString(img.Data.(string))
|
||||
c.Writer.WriteString(string(imageBuffer))
|
||||
// c.String(http.StatusOK, "data:image/"+filesuffix+";base64,"+img.Data.(string))
|
||||
//c.JSON(http.StatusOK, model.Result{Success: oasis_err2.SUCCESS, Message: oasis_err2.GetMsg(oasis_err2.SUCCESS), Data: img.Data.(string)})
|
||||
}
|
||||
|
||||
// @Summary get my friend list
|
||||
// @Produce application/json
|
||||
// @Accept application/json
|
||||
@@ -247,11 +299,39 @@ func GetPersonFriend(c *gin.Context) {
|
||||
for i := 0; i < len(list); i++ {
|
||||
if v, ok := service.UDPAddressMap[list[i].Token]; ok && len(v) > 0 {
|
||||
list[i].OnLine = true
|
||||
if ip_helper.HasLocalIP(net.ParseIP(strings.Split(v, ":")[0])) {
|
||||
list[i].LocalIP = strings.Split(v, ":")[0]
|
||||
}
|
||||
}
|
||||
}
|
||||
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.SUCCESS, Message: oasis_err2.GetMsg(oasis_err2.SUCCESS), Data: list})
|
||||
}
|
||||
|
||||
// @Summary network type detection
|
||||
// @Produce application/json
|
||||
// @Accept application/json
|
||||
// @Tags person
|
||||
// @Security ApiKeyAuth
|
||||
// @Success 200 {string} string "ok"
|
||||
// @Router /person/detection [get]
|
||||
func GetPersonDetection(c *gin.Context) {
|
||||
// - Blocked
|
||||
// - Open Internet
|
||||
// - Full Cone
|
||||
// - Symmetric UDP Firewall
|
||||
// - Restric NAT
|
||||
// - Restric Port NAT
|
||||
// - Symmetric NAT
|
||||
|
||||
result, err := natType.GetDeterminedNatType(true, 5, "stun.l.google.com")
|
||||
if err != nil {
|
||||
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.ERROR, Message: oasis_err2.GetMsg(oasis_err2.ERROR), Data: err.Error()})
|
||||
return
|
||||
}
|
||||
//result := service.MyService.Person().GetPersionNetWorkTypeDetection()
|
||||
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.SUCCESS, Message: oasis_err2.GetMsg(oasis_err2.SUCCESS), Data: result})
|
||||
}
|
||||
|
||||
// @Summary add friend
|
||||
// @Produce application/json
|
||||
// @Accept application/json
|
||||
@@ -296,10 +376,20 @@ func PostAddPersonFriend(c *gin.Context) {
|
||||
|
||||
go service.Dial(message, true)
|
||||
|
||||
msg := model.MessageModel{}
|
||||
msg.Type = types.PERSONGETIP
|
||||
msg.Data = ""
|
||||
msg.From = config.ServerInfo.Token
|
||||
msg.To = v
|
||||
msg.UUId = uuid.NewV4().String()
|
||||
|
||||
service.Dial(msg, true)
|
||||
|
||||
friend := model2.FriendModel{}
|
||||
friend.Token = v
|
||||
friend.Avatar = user.Avatar
|
||||
friend.Block = false
|
||||
friend.State = types.FRIENDSTATEWAIT
|
||||
friend.NickName = user.NickName
|
||||
friend.Profile = user.Desc
|
||||
friend.Version = user.Version
|
||||
@@ -439,6 +529,17 @@ func GetPersonShare(c *gin.Context) {
|
||||
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.SUCCESS, Message: oasis_err2.GetMsg(oasis_err2.SUCCESS), Data: config.FileSettingInfo.ShareDir})
|
||||
}
|
||||
|
||||
// @Summary Get the shareid
|
||||
// @Produce application/json
|
||||
// @Accept application/json
|
||||
// @Tags person
|
||||
// @Security ApiKeyAuth
|
||||
// @Success 200 {string} string "ok"
|
||||
// @Router /person/shareid [get]
|
||||
func GetPersonShareId(c *gin.Context) {
|
||||
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.SUCCESS, Message: oasis_err2.GetMsg(oasis_err2.SUCCESS), Data: config.ServerInfo.Token})
|
||||
}
|
||||
|
||||
// @Summary Modify disabled status
|
||||
// @Produce application/json
|
||||
// @Accept application/json
|
||||
@@ -489,8 +590,214 @@ func DeletePersonFriend(c *gin.Context) {
|
||||
// @Tags person
|
||||
// @Security ApiKeyAuth
|
||||
// @Success 200 {string} string "ok"
|
||||
// @Router /person/public [delete]
|
||||
// @Router /person/public [get]
|
||||
func GetPersonPublic(c *gin.Context) {
|
||||
list := service.MyService.Casa().GetPersonPublic()
|
||||
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.SUCCESS, Message: oasis_err2.GetMsg(oasis_err2.SUCCESS), Data: list})
|
||||
}
|
||||
|
||||
// @Summary upload file to friend
|
||||
// @Produce application/json
|
||||
// @Accept application/json
|
||||
// @Tags person
|
||||
// @Security ApiKeyAuth
|
||||
// @Param path formData string true "Destination path"
|
||||
// @Param local_path formData string true "Full path of the file to be uploaded"
|
||||
// @Success 200 {string} string "ok"
|
||||
// @Router /person/file/{shareid} [post]
|
||||
func PostPersonFile(c *gin.Context) {
|
||||
token := c.Param("shareid")
|
||||
_, err := uuid.FromString(token)
|
||||
path := c.PostForm("path")
|
||||
localPath := c.PostForm("local_path")
|
||||
if err != nil {
|
||||
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.INVALID_PARAMS, Message: oasis_err2.GetMsg(oasis_err2.INVALID_PARAMS)})
|
||||
return
|
||||
}
|
||||
if !file.Exists(localPath) {
|
||||
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.FILE_DOES_NOT_EXIST, Message: oasis_err2.GetMsg(oasis_err2.FILE_DOES_NOT_EXIST)})
|
||||
return
|
||||
}
|
||||
uuid := uuid.NewV4().String()
|
||||
m := model.MessageModel{}
|
||||
m.Data = path
|
||||
m.From = config.ServerInfo.Token
|
||||
m.To = token
|
||||
m.Type = types.PERSONUPLOAD
|
||||
m.UUId = uuid
|
||||
go service.UDPSendData(m, localPath)
|
||||
|
||||
f, _ := os.Stat(localPath)
|
||||
|
||||
task := model2.PersonDownloadDBModel{}
|
||||
task.UUID = uuid
|
||||
task.Name = f.Name()
|
||||
task.Length = 0
|
||||
task.From = token
|
||||
task.Path = path
|
||||
task.Size = f.Size()
|
||||
task.State = types.DOWNLOADFINISHED
|
||||
task.Created = time.Now().Unix()
|
||||
task.Type = types.PERSONFILEUPLOAD
|
||||
task.LocalPath = localPath
|
||||
if service.MyService.Download().GetDownloadListByPath(task) > 0 {
|
||||
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.PERSON_EXIST_DOWNLOAD, Message: oasis_err2.GetMsg(oasis_err2.PERSON_EXIST_DOWNLOAD)})
|
||||
return
|
||||
}
|
||||
service.MyService.Download().AddDownloadTask(task)
|
||||
|
||||
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.SUCCESS, Message: oasis_err2.GetMsg(oasis_err2.SUCCESS)})
|
||||
}
|
||||
|
||||
// @Summary agree add friend
|
||||
// @Produce application/json
|
||||
// @Accept application/json
|
||||
// @Tags person
|
||||
// @Security ApiKeyAuth
|
||||
// @Success 200 {string} string "ok"
|
||||
// @Router /person/friend/{shareid} [put]
|
||||
func PutPersonAgreeFriend(c *gin.Context) {
|
||||
token := c.Param("shareid")
|
||||
_, err := uuid.FromString(token)
|
||||
if err != nil {
|
||||
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.INVALID_PARAMS, Message: oasis_err2.GetMsg(oasis_err2.INVALID_PARAMS)})
|
||||
return
|
||||
}
|
||||
|
||||
user := service.MyService.Friend().GetFriendById(model2.FriendModel{Token: token})
|
||||
|
||||
if user.State != types.FRIENDSTATEREQUEST {
|
||||
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.COMMAND_ERROR_INVALID_OPERATION, Message: oasis_err2.GetMsg(oasis_err2.COMMAND_ERROR_INVALID_OPERATION)})
|
||||
return
|
||||
}
|
||||
service.MyService.Friend().AgreeFrined(user.Token)
|
||||
|
||||
uuid := uuid.NewV4().String()
|
||||
m := model.MessageModel{}
|
||||
m.Data = ""
|
||||
m.From = config.ServerInfo.Token
|
||||
m.To = token
|
||||
m.Type = types.PERSONAGREEFRIEND
|
||||
m.UUId = uuid
|
||||
go service.Dial(m, true)
|
||||
|
||||
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.SUCCESS, Message: oasis_err2.GetMsg(oasis_err2.SUCCESS)})
|
||||
}
|
||||
|
||||
// // @Summary upload file
|
||||
// // @Produce application/json
|
||||
// // @Accept multipart/form-data
|
||||
// // @Tags person
|
||||
// // @Security ApiKeyAuth
|
||||
// // @Param path formData string false "file path"
|
||||
// // @Param file formData file true "file"
|
||||
// // @Success 200 {string} string "ok"
|
||||
// // @Router /person/upload/{shareid} [get]
|
||||
// func GetPersonFileUpload(c *gin.Context) {
|
||||
|
||||
// token := c.Param("shareid")
|
||||
// _, err := uuid.FromString(token)
|
||||
// path := c.Query("path")
|
||||
// if err != nil {
|
||||
// c.JSON(http.StatusOK, model.Result{Success: oasis_err2.INVALID_PARAMS, Message: oasis_err2.GetMsg(oasis_err2.INVALID_PARAMS)})
|
||||
// return
|
||||
// }
|
||||
|
||||
// relative := c.Query("relativePath")
|
||||
// fileName := c.Query("filename")
|
||||
// chunkNumber := c.Query("chunkNumber")
|
||||
// totalChunks, _ := strconv.Atoi(c.DefaultQuery("totalChunks", "0"))
|
||||
// dirPath := ""
|
||||
// hash := file.GetHashByContent([]byte(fileName))
|
||||
// tempDir := "/casaOS/temp/" + hash + strconv.Itoa(totalChunks) + "/"
|
||||
// if fileName != relative {
|
||||
// dirPath = strings.TrimSuffix(relative, fileName)
|
||||
// tempDir += dirPath
|
||||
// file.MkDir(path + "/" + dirPath)
|
||||
// }
|
||||
// tempDir += chunkNumber
|
||||
// if !file.CheckNotExist(tempDir) {
|
||||
// c.JSON(200, model.Result{Success: 200, Message: oasis_err2.GetMsg(oasis_err2.FILE_ALREADY_EXISTS)})
|
||||
// return
|
||||
// }
|
||||
|
||||
// c.JSON(204, model.Result{Success: 204, Message: oasis_err2.GetMsg(oasis_err2.SUCCESS)})
|
||||
// }
|
||||
|
||||
// // @Summary upload file
|
||||
// // @Produce application/json
|
||||
// // @Accept multipart/form-data
|
||||
// // @Tags person
|
||||
// // @Security ApiKeyAuth
|
||||
// // @Param path formData string false "file path"
|
||||
// // @Param file formData file true "file"
|
||||
// // @Success 200 {string} string "ok"
|
||||
// // @Router /person/upload [post]
|
||||
// func PostPersonFileUpload(c *gin.Context) {
|
||||
// token := c.Param("shareid")
|
||||
// _, err := uuid.FromString(token)
|
||||
// if err != nil {
|
||||
// c.JSON(http.StatusOK, model.Result{Success: oasis_err2.INVALID_PARAMS, Message: oasis_err2.GetMsg(oasis_err2.INVALID_PARAMS)})
|
||||
// return
|
||||
// }
|
||||
// f, _, _ := c.Request.FormFile("file")
|
||||
// relative := c.PostForm("relativePath")
|
||||
// fileName := c.PostForm("filename")
|
||||
// totalChunks, _ := strconv.Atoi(c.DefaultPostForm("totalChunks", "0"))
|
||||
// chunkNumber := c.PostForm("chunkNumber")
|
||||
// dirPath := ""
|
||||
// path := c.PostForm("path")
|
||||
|
||||
// hash := file.GetHashByContent([]byte(fileName))
|
||||
|
||||
// if len(path) == 0 {
|
||||
// c.JSON(oasis_err2.INVALID_PARAMS, model.Result{Success: oasis_err2.INVALID_PARAMS, Message: oasis_err2.GetMsg(oasis_err2.INVALID_PARAMS)})
|
||||
// return
|
||||
// }
|
||||
// tempDir := "/casaOS/temp/" + hash + strconv.Itoa(totalChunks) + "/"
|
||||
|
||||
// if fileName != relative {
|
||||
// dirPath = strings.TrimSuffix(relative, fileName)
|
||||
// tempDir += dirPath
|
||||
// file.MkDir(path + "/" + dirPath)
|
||||
// }
|
||||
|
||||
// path += "/" + relative
|
||||
|
||||
// if !file.CheckNotExist(tempDir + chunkNumber) {
|
||||
// file.RMDir(tempDir + chunkNumber)
|
||||
// }
|
||||
|
||||
// if totalChunks > 1 {
|
||||
// file.IsNotExistMkDir(tempDir)
|
||||
|
||||
// out, _ := os.OpenFile(tempDir+chunkNumber, os.O_WRONLY|os.O_CREATE, 0644)
|
||||
// defer out.Close()
|
||||
// _, err := io.Copy(out, f)
|
||||
// if err != nil {
|
||||
// c.JSON(oasis_err2.ERROR, model.Result{Success: oasis_err2.ERROR, Message: oasis_err2.GetMsg(oasis_err2.ERROR), Data: err.Error()})
|
||||
// return
|
||||
// }
|
||||
// } else {
|
||||
// out, _ := os.OpenFile(path, os.O_WRONLY|os.O_CREATE, 0644)
|
||||
// defer out.Close()
|
||||
// _, err := io.Copy(out, f)
|
||||
// if err != nil {
|
||||
// c.JSON(oasis_err2.ERROR, model.Result{Success: oasis_err2.ERROR, Message: oasis_err2.GetMsg(oasis_err2.ERROR), Data: err.Error()})
|
||||
// return
|
||||
// }
|
||||
// c.JSON(http.StatusOK, model.Result{Success: oasis_err2.SUCCESS, Message: oasis_err2.GetMsg(oasis_err2.SUCCESS)})
|
||||
// return
|
||||
// }
|
||||
|
||||
// fileNum, err := ioutil.ReadDir(tempDir)
|
||||
// if err != nil {
|
||||
// c.JSON(oasis_err2.ERROR, model.Result{Success: oasis_err2.ERROR, Message: oasis_err2.GetMsg(oasis_err2.ERROR), Data: err.Error()})
|
||||
// return
|
||||
// }
|
||||
// if totalChunks == len(fileNum) {
|
||||
// file.RMDir(tempDir)
|
||||
// }
|
||||
|
||||
// c.JSON(http.StatusOK, model.Result{Success: oasis_err2.SUCCESS, Message: oasis_err2.GetMsg(oasis_err2.SUCCESS)})
|
||||
// }
|
||||
@@ -23,14 +23,14 @@ import (
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
// @Summary 系统信息
|
||||
// @Summary check version
|
||||
// @Produce application/json
|
||||
// @Accept application/json
|
||||
// @Tags sys
|
||||
// @Security ApiKeyAuth
|
||||
// @Success 200 {string} string "ok"
|
||||
// @Router /sys/chackversion [get]
|
||||
func CheckVersion(c *gin.Context) {
|
||||
// @Router /sys/version/check [get]
|
||||
func GetSystemCheckVersion(c *gin.Context) {
|
||||
need, version := version.IsNeedUpdate()
|
||||
if need {
|
||||
installLog := model2.AppNotify{}
|
||||
@@ -47,7 +47,6 @@ func CheckVersion(c *gin.Context) {
|
||||
data["version"] = version
|
||||
data["current_version"] = types.CURRENTVERSION
|
||||
c.JSON(http.StatusOK, model.Result{Success: oasis_err.SUCCESS, Message: oasis_err.GetMsg(oasis_err.SUCCESS), Data: data})
|
||||
return
|
||||
}
|
||||
|
||||
// @Summary 系统信息
|
||||
@@ -65,7 +64,7 @@ func SystemUpdate(c *gin.Context) {
|
||||
c.JSON(http.StatusOK, model.Result{Success: oasis_err.SUCCESS, Message: oasis_err.GetMsg(oasis_err.SUCCESS)})
|
||||
}
|
||||
|
||||
//系统配置
|
||||
//Get system config
|
||||
func GetSystemConfig(c *gin.Context) {
|
||||
c.JSON(http.StatusOK, model.Result{Success: oasis_err.SUCCESS, Message: oasis_err.GetMsg(oasis_err.SUCCESS), Data: json.RawMessage(config.SystemConfigInfo.ConfigStr)})
|
||||
}
|
||||
@@ -115,7 +114,7 @@ func GetSystemConfigDebug(c *gin.Context) {
|
||||
systemAppStatus += "Sync img: " + strconv.FormatBool(images) + "\n\t"
|
||||
|
||||
list := service.MyService.App().GetSystemAppList()
|
||||
for _, v := range *list {
|
||||
for _, v := range list {
|
||||
systemAppStatus += v.Image + ",\n\t"
|
||||
}
|
||||
|
||||
@@ -136,9 +135,6 @@ func GetSystemConfigDebug(c *gin.Context) {
|
||||
|
||||
c.JSON(http.StatusOK, model.Result{Success: oasis_err.SUCCESS, Message: oasis_err.GetMsg(oasis_err.SUCCESS), Data: bugContent})
|
||||
}
|
||||
func Sys(c *gin.Context) {
|
||||
service.DockerPull()
|
||||
}
|
||||
|
||||
//widget配置
|
||||
func GetWidgetConfig(c *gin.Context) {
|
||||
@@ -155,9 +151,7 @@ func GetWidgetConfig(c *gin.Context) {
|
||||
func PostSetWidgetConfig(c *gin.Context) {
|
||||
buf := make([]byte, 1024)
|
||||
n, _ := c.Request.Body.Read(buf)
|
||||
fmt.Println("错误", strconv.Itoa(n))
|
||||
service.MyService.System().UpSystemConfig("", string(buf[0:n]))
|
||||
fmt.Println("错误1", string(buf[0:n]))
|
||||
c.JSON(http.StatusOK,
|
||||
model.Result{
|
||||
Success: oasis_err.SUCCESS,
|
||||
@@ -187,11 +181,14 @@ func GetCasaOSPort(c *gin.Context) {
|
||||
// @Accept application/json
|
||||
// @Tags sys
|
||||
// @Security ApiKeyAuth
|
||||
// @Param port formData string true "port"
|
||||
// @Param port json string true "port"
|
||||
// @Success 200 {string} string "ok"
|
||||
// @Router /sys/port [put]
|
||||
func PutCasaOSPort(c *gin.Context) {
|
||||
port, err := strconv.Atoi(c.PostForm("port"))
|
||||
json := make(map[string]string)
|
||||
c.BindJSON(&json)
|
||||
portStr := json["port"]
|
||||
port, err := strconv.Atoi(portStr)
|
||||
if err != nil {
|
||||
c.JSON(http.StatusOK,
|
||||
model.Result{
|
||||
@@ -246,7 +243,7 @@ func GetGuideCheck(c *gin.Context) {
|
||||
// @Tags sys
|
||||
// @Security ApiKeyAuth
|
||||
// @Success 200 {string} string "ok"
|
||||
// @Router /sys/kill [post]
|
||||
// @Router /sys/restart [post]
|
||||
func PostKillCasaOS(c *gin.Context) {
|
||||
os.Exit(0)
|
||||
}
|
||||
@@ -257,10 +254,17 @@ func PostKillCasaOS(c *gin.Context) {
|
||||
// @Tags sys
|
||||
// @Security ApiKeyAuth
|
||||
// @Success 200 {string} string "ok"
|
||||
// @Router /sys/usg/off [put]
|
||||
func PutSystemOffUSBAutoMount(c *gin.Context) {
|
||||
// @Router /sys/usb/off [put]
|
||||
func PutSystemUSBAutoMount(c *gin.Context) {
|
||||
status := c.Param("status")
|
||||
if status == "on" {
|
||||
service.MyService.System().UpdateUSBAutoMount("True")
|
||||
service.MyService.System().ExecUSBAutoMountShell("True")
|
||||
} else {
|
||||
service.MyService.System().UpdateUSBAutoMount("False")
|
||||
service.MyService.System().ExecUSBAutoMountShell("False")
|
||||
}
|
||||
|
||||
c.JSON(http.StatusOK,
|
||||
model.Result{
|
||||
Success: oasis_err.SUCCESS,
|
||||
@@ -280,6 +284,7 @@ func GetSystemUSBAutoMount(c *gin.Context) {
|
||||
if config.ServerInfo.USBAutoMount == "False" {
|
||||
state = "False"
|
||||
}
|
||||
|
||||
c.JSON(http.StatusOK,
|
||||
model.Result{
|
||||
Success: oasis_err.SUCCESS,
|
||||
@@ -288,31 +293,33 @@ func GetSystemUSBAutoMount(c *gin.Context) {
|
||||
})
|
||||
}
|
||||
|
||||
// @Summary Turn off usb auto-mount
|
||||
// @Summary get system hardware info
|
||||
// @Produce application/json
|
||||
// @Accept application/json
|
||||
// @Tags sys
|
||||
// @Security ApiKeyAuth
|
||||
// @Success 200 {string} string "ok"
|
||||
// @Router /sys/usb/on [put]
|
||||
func PutSystemOnUSBAutoMount(c *gin.Context) {
|
||||
service.MyService.System().UpdateUSBAutoMount("True")
|
||||
service.MyService.System().ExecUSBAutoMountShell("True")
|
||||
// @Router /sys/hardware/info [get]
|
||||
func GetSystemHardwareInfo(c *gin.Context) {
|
||||
|
||||
data := make(map[string]string, 1)
|
||||
data["drive_model"] = service.MyService.ZiMa().GetDeviceTree()
|
||||
c.JSON(http.StatusOK,
|
||||
model.Result{
|
||||
Success: oasis_err.SUCCESS,
|
||||
Message: oasis_err.GetMsg(oasis_err.SUCCESS),
|
||||
Data: data,
|
||||
})
|
||||
}
|
||||
|
||||
// @Summary system info
|
||||
// @Summary system utilization
|
||||
// @Produce application/json
|
||||
// @Accept application/json
|
||||
// @Tags sys
|
||||
// @Security ApiKeyAuth
|
||||
// @Success 200 {string} string "ok"
|
||||
// @Router /sys/info [get]
|
||||
func Info(c *gin.Context) {
|
||||
// @Router /sys/utilization [get]
|
||||
func GetSystemUtilization(c *gin.Context) {
|
||||
var data = make(map[string]interface{}, 6)
|
||||
|
||||
list := service.MyService.Disk().LSBLK(true)
|
||||
@@ -411,18 +418,18 @@ func Info(c *gin.Context) {
|
||||
}
|
||||
}
|
||||
data["usb"] = usb
|
||||
cpu := service.MyService.ZiMa().GetCpuPercent()
|
||||
num := service.MyService.ZiMa().GetCpuCoreNum()
|
||||
cpu := service.MyService.System().GetCpuPercent()
|
||||
num := service.MyService.System().GetCpuCoreNum()
|
||||
cpuData := make(map[string]interface{})
|
||||
cpuData["percent"] = cpu
|
||||
cpuData["num"] = num
|
||||
data["cpu"] = cpuData
|
||||
data["mem"] = service.MyService.ZiMa().GetMemInfo()
|
||||
data["mem"] = service.MyService.System().GetMemInfo()
|
||||
|
||||
//拼装网络信息
|
||||
netList := service.MyService.ZiMa().GetNetInfo()
|
||||
netList := service.MyService.System().GetNetInfo()
|
||||
newNet := []model.IOCountersStat{}
|
||||
nets := service.MyService.ZiMa().GetNet(true)
|
||||
nets := service.MyService.System().GetNet(true)
|
||||
for _, n := range netList {
|
||||
for _, netCardName := range nets {
|
||||
if n.Name == netCardName {
|
||||
@@ -439,3 +446,88 @@ func Info(c *gin.Context) {
|
||||
|
||||
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.SUCCESS, Message: oasis_err2.GetMsg(oasis_err2.SUCCESS), Data: data})
|
||||
}
|
||||
|
||||
// @Summary Get notification port
|
||||
// @Produce application/json
|
||||
// @Accept application/json
|
||||
// @Tags sys
|
||||
// @Security ApiKeyAuth
|
||||
// @Success 200 {string} string "ok"
|
||||
// @Router /sys/socket/port [get]
|
||||
func GetSystemSocketPort(c *gin.Context) {
|
||||
|
||||
c.JSON(http.StatusOK,
|
||||
model.Result{
|
||||
Success: oasis_err.SUCCESS,
|
||||
Message: oasis_err.GetMsg(oasis_err.SUCCESS),
|
||||
Data: config.ServerInfo.SocketPort,
|
||||
})
|
||||
}
|
||||
|
||||
// @Summary get cpu info
|
||||
// @Produce application/json
|
||||
// @Accept application/json
|
||||
// @Tags sys
|
||||
// @Security ApiKeyAuth
|
||||
// @Success 200 {string} string "ok"
|
||||
// @Router /sys/cpu [get]
|
||||
func GetSystemCupInfo(c *gin.Context) {
|
||||
cpu := service.MyService.System().GetCpuPercent()
|
||||
num := service.MyService.System().GetCpuCoreNum()
|
||||
data := make(map[string]interface{})
|
||||
data["percent"] = cpu
|
||||
data["num"] = num
|
||||
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.SUCCESS, Message: oasis_err2.GetMsg(oasis_err2.SUCCESS), Data: data})
|
||||
|
||||
}
|
||||
|
||||
// @Summary get mem info
|
||||
// @Produce application/json
|
||||
// @Accept application/json
|
||||
// @Tags sys
|
||||
// @Security ApiKeyAuth
|
||||
// @Success 200 {string} string "ok"
|
||||
// @Router /sys/mem [get]
|
||||
func GetSystemMemInfo(c *gin.Context) {
|
||||
mem := service.MyService.System().GetMemInfo()
|
||||
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.SUCCESS, Message: oasis_err2.GetMsg(oasis_err2.SUCCESS), Data: mem})
|
||||
|
||||
}
|
||||
|
||||
// @Summary get disk info
|
||||
// @Produce application/json
|
||||
// @Accept application/json
|
||||
// @Tags sys
|
||||
// @Security ApiKeyAuth
|
||||
// @Success 200 {string} string "ok"
|
||||
// @Router /sys/disk [get]
|
||||
func GetSystemDiskInfo(c *gin.Context) {
|
||||
disk := service.MyService.ZiMa().GetDiskInfo()
|
||||
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.SUCCESS, Message: oasis_err2.GetMsg(oasis_err2.SUCCESS), Data: disk})
|
||||
}
|
||||
|
||||
// @Summary get Net info
|
||||
// @Produce application/json
|
||||
// @Accept application/json
|
||||
// @Tags sys
|
||||
// @Security ApiKeyAuth
|
||||
// @Success 200 {string} string "ok"
|
||||
// @Router /sys/net [get]
|
||||
func GetSystemNetInfo(c *gin.Context) {
|
||||
netList := service.MyService.System().GetNetInfo()
|
||||
|
||||
newNet := []model.IOCountersStat{}
|
||||
for _, n := range netList {
|
||||
for _, netCardName := range service.MyService.System().GetNet(true) {
|
||||
if n.Name == netCardName {
|
||||
item := *(*model.IOCountersStat)(unsafe.Pointer(&n))
|
||||
item.State = strings.TrimSpace(service.MyService.ZiMa().GetNetState(n.Name))
|
||||
item.Time = time.Now().Unix()
|
||||
newNet = append(newNet, item)
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.SUCCESS, Message: oasis_err2.GetMsg(oasis_err2.SUCCESS), Data: newNet})
|
||||
}
|
||||
|
||||
@@ -1,10 +1,17 @@
|
||||
/*
|
||||
* @Author: LinkLeong link@icewhale.com
|
||||
* @Date: 2021-09-30 18:18:14
|
||||
* @LastEditors: LinkLeong
|
||||
* @LastEditTime: 2022-06-13 15:20:56
|
||||
* @FilePath: /CasaOS/route/v1/zima_info.go
|
||||
* @Description:
|
||||
* @Website: https://www.casaos.io
|
||||
* Copyright (c) 2022 by icewhale, All Rights Reserved.
|
||||
*/
|
||||
package v1
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
"strings"
|
||||
"time"
|
||||
"unsafe"
|
||||
|
||||
"github.com/IceWhaleTech/CasaOS/model"
|
||||
oasis_err2 "github.com/IceWhaleTech/CasaOS/pkg/utils/oasis_err"
|
||||
@@ -12,77 +19,6 @@ import (
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
// @Summary 获取cpu信息
|
||||
// @Produce application/json
|
||||
// @Accept application/json
|
||||
// @Tags zima
|
||||
// @Security ApiKeyAuth
|
||||
// @Success 200 {string} string "ok"
|
||||
// @Router /zima/getcpuinfo [get]
|
||||
func CupInfo(c *gin.Context) {
|
||||
//检查参数是否正确
|
||||
cpu := service.MyService.ZiMa().GetCpuPercent()
|
||||
num := service.MyService.ZiMa().GetCpuCoreNum()
|
||||
data := make(map[string]interface{})
|
||||
data["percent"] = cpu
|
||||
data["num"] = num
|
||||
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.SUCCESS, Message: oasis_err2.GetMsg(oasis_err2.SUCCESS), Data: data})
|
||||
|
||||
}
|
||||
|
||||
// @Summary 获取内存信息
|
||||
// @Produce application/json
|
||||
// @Accept application/json
|
||||
// @Tags zima
|
||||
// @Security ApiKeyAuth
|
||||
// @Success 200 {string} string "ok"
|
||||
// @Router /zima/getmeminfo [get]
|
||||
func MemInfo(c *gin.Context) {
|
||||
|
||||
//检查参数是否正确
|
||||
mem := service.MyService.ZiMa().GetMemInfo()
|
||||
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.SUCCESS, Message: oasis_err2.GetMsg(oasis_err2.SUCCESS), Data: mem})
|
||||
|
||||
}
|
||||
|
||||
// @Summary 获取硬盘信息
|
||||
// @Produce application/json
|
||||
// @Accept application/json
|
||||
// @Tags zima
|
||||
// @Security ApiKeyAuth
|
||||
// @Success 200 {string} string "ok"
|
||||
// @Router /zima/getdiskinfo [get]
|
||||
func DiskInfo(c *gin.Context) {
|
||||
disk := service.MyService.ZiMa().GetDiskInfo()
|
||||
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.SUCCESS, Message: oasis_err2.GetMsg(oasis_err2.SUCCESS), Data: disk})
|
||||
}
|
||||
|
||||
// @Summary 获取网络信息
|
||||
// @Produce application/json
|
||||
// @Accept application/json
|
||||
// @Tags zima
|
||||
// @Security ApiKeyAuth
|
||||
// @Success 200 {string} string "ok"
|
||||
// @Router /zima/getnetinfo [get]
|
||||
func NetInfo(c *gin.Context) {
|
||||
netList := service.MyService.ZiMa().GetNetInfo()
|
||||
|
||||
newNet := []model.IOCountersStat{}
|
||||
for _, n := range netList {
|
||||
for _, netCardName := range service.MyService.ZiMa().GetNet(true) {
|
||||
if n.Name == netCardName {
|
||||
item := *(*model.IOCountersStat)(unsafe.Pointer(&n))
|
||||
item.State = strings.TrimSpace(service.MyService.ZiMa().GetNetState(n.Name))
|
||||
item.Time = time.Now().Unix()
|
||||
newNet = append(newNet, item)
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.SUCCESS, Message: oasis_err2.GetMsg(oasis_err2.SUCCESS), Data: newNet})
|
||||
}
|
||||
|
||||
// @Summary 获取信息系统信息
|
||||
// @Produce application/json
|
||||
// @Accept application/json
|
||||
|
||||
394
service/app.go
@@ -3,9 +3,11 @@ package service
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"runtime"
|
||||
"strconv"
|
||||
"strings"
|
||||
"sync"
|
||||
"time"
|
||||
@@ -13,164 +15,326 @@ import (
|
||||
"github.com/IceWhaleTech/CasaOS/model"
|
||||
"github.com/IceWhaleTech/CasaOS/pkg/config"
|
||||
"github.com/IceWhaleTech/CasaOS/pkg/utils/command"
|
||||
loger2 "github.com/IceWhaleTech/CasaOS/pkg/utils/loger"
|
||||
"github.com/IceWhaleTech/CasaOS/pkg/utils/loger"
|
||||
model2 "github.com/IceWhaleTech/CasaOS/service/model"
|
||||
"github.com/docker/docker/api/types"
|
||||
"github.com/docker/docker/api/types/filters"
|
||||
client2 "github.com/docker/docker/client"
|
||||
"github.com/pkg/errors"
|
||||
uuid "github.com/satori/go.uuid"
|
||||
"go.uber.org/zap"
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
|
||||
type AppService interface {
|
||||
GetMyList(index, size int, position bool) *[]model2.MyAppList
|
||||
CreateApplication(m model2.ApplicationModel) model2.ApplicationModel
|
||||
GetApplicationList() (m []model2.ApplicationModel)
|
||||
GetApplicationById(id string) (m model2.ApplicationModel)
|
||||
UpdateApplicationOrderById(id string, order int)
|
||||
GetMyList(index, size int, position bool) (*[]model2.MyAppList, *[]model2.MyAppList)
|
||||
GetCasaOSCount() int
|
||||
SaveContainer(m model2.AppListDBModel)
|
||||
GetUninstallInfo(id string) model2.AppListDBModel
|
||||
RemoveContainerById(id string)
|
||||
DeleteApp(id string)
|
||||
GetContainerInfo(name string) (types.Container, error)
|
||||
GetAppDBInfo(id string) model2.AppListDBModel
|
||||
UpdateApp(m model2.AppListDBModel)
|
||||
GetSimpleContainerInfo(name string) (types.Container, error)
|
||||
DelAppConfigDir(path string)
|
||||
GetSystemAppList() *[]model2.MyAppList
|
||||
GetSystemAppList() []types.Container
|
||||
GetHardwareUsageSteam()
|
||||
GetHardwareUsage() []model.DockerStatsModel
|
||||
GetAppStats(id string) string
|
||||
GetAllDBApps() []model2.AppListDBModel
|
||||
ImportApplications(casaApp bool)
|
||||
CheckNewImage()
|
||||
}
|
||||
|
||||
type appStruct struct {
|
||||
db *gorm.DB
|
||||
log loger2.OLog
|
||||
}
|
||||
|
||||
//获取我的应用列表
|
||||
func (a *appStruct) GetMyList(index, size int, position bool) *[]model2.MyAppList {
|
||||
//获取docker应用
|
||||
func (a *appStruct) GetApplicationById(id string) (m model2.ApplicationModel) {
|
||||
a.db.Where("id = ?", id).First(&m)
|
||||
return
|
||||
}
|
||||
|
||||
func (a *appStruct) UpdateApplicationOrderById(id string, order int) {
|
||||
a.db.Model(&model2.ApplicationModel{}).Where("id = ?", id).Update("order", order)
|
||||
}
|
||||
|
||||
func (a *appStruct) CreateApplication(m model2.ApplicationModel) model2.ApplicationModel {
|
||||
a.db.Create(&m)
|
||||
return m
|
||||
}
|
||||
func (a *appStruct) GetApplicationList() (m []model2.ApplicationModel) {
|
||||
a.db.Find(&m)
|
||||
return
|
||||
}
|
||||
|
||||
func (a *appStruct) CheckNewImage() {
|
||||
list := MyService.Docker().DockerContainerList()
|
||||
for _, v := range list {
|
||||
inspect, err := MyService.Docker().DockerImageInfo(strings.Split(v.Image, ":")[0])
|
||||
if err != nil {
|
||||
NewVersionApp[v.ID] = inspect.ID
|
||||
continue
|
||||
}
|
||||
if inspect.ID == v.ImageID {
|
||||
delete(NewVersionApp, v.ID)
|
||||
continue
|
||||
}
|
||||
NewVersionApp[v.ID] = inspect.ID
|
||||
}
|
||||
|
||||
}
|
||||
func (a *appStruct) ImportApplications(casaApp bool) {
|
||||
if casaApp {
|
||||
list := MyService.App().GetAllDBApps()
|
||||
for _, app := range list {
|
||||
info, err := MyService.Docker().DockerContainerInfo(app.CustomId)
|
||||
if err != nil {
|
||||
MyService.App().DeleteApp(app.CustomId)
|
||||
continue
|
||||
}
|
||||
//info.NetworkSettings
|
||||
info.Config.Labels["casaos"] = "casaos"
|
||||
info.Config.Labels["web"] = app.PortMap
|
||||
info.Config.Labels["icon"] = app.Icon
|
||||
info.Config.Labels["desc"] = app.Description
|
||||
info.Config.Labels["index"] = app.Index
|
||||
info.Config.Labels["custom_id"] = app.CustomId
|
||||
info.Name = app.Title
|
||||
container_id, err := MyService.Docker().DockerContainerCopyCreate(info)
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
continue
|
||||
}
|
||||
MyService.App().DeleteApp(app.CustomId)
|
||||
MyService.Docker().DockerContainerStop(app.CustomId)
|
||||
MyService.Docker().DockerContainerRemove(app.CustomId, false)
|
||||
MyService.Docker().DockerContainerStart(container_id)
|
||||
|
||||
}
|
||||
} else {
|
||||
list := MyService.Docker().DockerContainerList()
|
||||
for _, app := range list {
|
||||
info, err := MyService.Docker().DockerContainerInfo(app.ID)
|
||||
if err != nil || info.Config.Labels["casaos"] == "casaos" {
|
||||
continue
|
||||
}
|
||||
info.Config.Labels["casaos"] = "casaos"
|
||||
info.Config.Labels["web"] = ""
|
||||
info.Config.Labels["icon"] = ""
|
||||
info.Config.Labels["desc"] = ""
|
||||
info.Config.Labels["index"] = ""
|
||||
info.Config.Labels["custom_id"] = uuid.NewV4().String()
|
||||
|
||||
_, err = MyService.Docker().DockerContainerCopyCreate(info)
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
// allcontainer := MyService.Docker().DockerContainerList()
|
||||
// for _, app := range allcontainer {
|
||||
// info, err := MyService.Docker().DockerContainerInfo(app.ID)
|
||||
// if err != nil {
|
||||
// continue
|
||||
// }
|
||||
// MyService.Docker().DockerContainerStop(app.ID)
|
||||
// MyService.Docker().DockerContainerRemove(app.ID, false)
|
||||
// //info.NetworkSettings
|
||||
// info.Config.Labels["custom_id"] = uuid.NewV4().String()
|
||||
// container_id, err := MyService.Docker().DockerContainerCopyCreate(info)
|
||||
// if err != nil {
|
||||
// fmt.Println(err)
|
||||
// continue
|
||||
// }
|
||||
// MyService.Docker().DockerContainerStart(container_id)
|
||||
//}
|
||||
|
||||
}
|
||||
|
||||
func (a *appStruct) GetCasaOSCount() int {
|
||||
cli, err := client2.NewClientWithOpts(client2.FromEnv, client2.WithTimeout(time.Second*5))
|
||||
if err != nil {
|
||||
a.log.Error("初始化client失败", "app.getmylist", "line:36", err)
|
||||
loger.Error("Failed to init client", zap.Any("err", err))
|
||||
return 0
|
||||
}
|
||||
defer cli.Close()
|
||||
fts := filters.NewArgs()
|
||||
fts.Add("label", "origin")
|
||||
containers, err := cli.ContainerList(context.Background(), types.ContainerListOptions{All: true, Filters: fts})
|
||||
fts.Add("label", "casaos=casaos")
|
||||
//fts.Add("label", "casaos:casaos")
|
||||
|
||||
containers, err := cli.ContainerList(context.Background(), types.ContainerListOptions{Filters: fts, Limit: 200})
|
||||
if err != nil {
|
||||
a.log.Error("获取docker容器失败", "app.getmylist", "line:42", err)
|
||||
loger.Error("failed to get container_list", zap.Any("err", err))
|
||||
return 0
|
||||
}
|
||||
|
||||
systemApp := MyService.App().GetApplicationList()
|
||||
return len(containers) + len(systemApp)
|
||||
}
|
||||
|
||||
//获取我的应用列表
|
||||
func (a *appStruct) GetMyList(index, size int, position bool) (*[]model2.MyAppList, *[]model2.MyAppList) {
|
||||
cli, err := client2.NewClientWithOpts(client2.FromEnv, client2.WithTimeout(time.Second*5))
|
||||
if err != nil {
|
||||
loger.Error("Failed to init client", zap.Any("err", err))
|
||||
}
|
||||
defer cli.Close()
|
||||
// fts := filters.NewArgs()
|
||||
// fts.Add("label", "casaos=casaos")
|
||||
//fts.Add("label", "casaos")
|
||||
//fts.Add("casaos", "casaos")
|
||||
containers, err := cli.ContainerList(context.Background(), types.ContainerListOptions{All: true})
|
||||
if err != nil {
|
||||
loger.Error("Failed to get container_list", zap.Any("err", err))
|
||||
}
|
||||
//获取本地数据库应用
|
||||
|
||||
var lm []model2.AppListDBModel
|
||||
a.db.Table(model2.CONTAINERTABLENAME).Select("title,icon,port_map,`index`,container_id,position,label,slogan,image").Find(&lm)
|
||||
unTranslation := []model2.MyAppList{}
|
||||
|
||||
list := []model2.MyAppList{}
|
||||
lMap := make(map[string]interface{})
|
||||
for _, dbModel := range lm {
|
||||
if position {
|
||||
if dbModel.Position {
|
||||
lMap[dbModel.ContainerId] = dbModel
|
||||
}
|
||||
} else {
|
||||
lMap[dbModel.ContainerId] = dbModel
|
||||
}
|
||||
}
|
||||
for _, container := range containers {
|
||||
|
||||
if lMap[container.ID] != nil && container.Labels["origin"] != "system" {
|
||||
m := lMap[container.ID].(model2.AppListDBModel)
|
||||
if len(m.Label) == 0 {
|
||||
m.Label = m.Title
|
||||
}
|
||||
|
||||
// info, err := cli.ContainerInspect(context.Background(), container.ID)
|
||||
// var tm string
|
||||
// if err != nil {
|
||||
// tm = time.Now().String()
|
||||
// } else {
|
||||
// tm = info.State.StartedAt
|
||||
//}
|
||||
systemApp := MyService.App().GetApplicationList()
|
||||
for _, v := range systemApp {
|
||||
list = append(list, model2.MyAppList{
|
||||
Name: m.Label,
|
||||
Icon: m.Icon,
|
||||
State: container.State,
|
||||
CustomId: strings.ReplaceAll(container.Names[0], "/", ""),
|
||||
Port: m.PortMap,
|
||||
Index: m.Index,
|
||||
//UpTime: tm,
|
||||
Image: m.Image,
|
||||
Slogan: m.Slogan,
|
||||
//Rely: m.Rely,
|
||||
Name: v.Name,
|
||||
Icon: v.Icon,
|
||||
State: strconv.Itoa(v.State),
|
||||
Id: strconv.Itoa(v.Id),
|
||||
CustomId: strconv.Itoa(v.Id),
|
||||
Port: "",
|
||||
//Order: strconv.Itoa(v.Order),
|
||||
Index: "/",
|
||||
Image: "",
|
||||
Type: v.Type,
|
||||
Host: "",
|
||||
Protocol: "",
|
||||
NewVersion: false,
|
||||
})
|
||||
}
|
||||
|
||||
for _, m := range containers {
|
||||
if m.Labels["casaos"] == "casaos" {
|
||||
if m.Labels["origin"] == "system" {
|
||||
continue
|
||||
}
|
||||
_, newVersion := NewVersionApp[m.ID]
|
||||
list = append(list, model2.MyAppList{
|
||||
Name: strings.ReplaceAll(m.Names[0], "/", ""),
|
||||
Icon: m.Labels["icon"],
|
||||
State: m.State,
|
||||
CustomId: m.Labels["custom_id"],
|
||||
Id: m.ID,
|
||||
Port: m.Labels["web"],
|
||||
Index: m.Labels["index"],
|
||||
//Order: m.Labels["order"],
|
||||
Image: m.Image,
|
||||
NewVersion: newVersion,
|
||||
Type: m.Labels["origin"],
|
||||
//Slogan: m.Slogan,
|
||||
//Rely: m.Rely,
|
||||
Host: m.Labels["host"],
|
||||
Protocol: m.Labels["protocol"],
|
||||
})
|
||||
} else {
|
||||
unTranslation = append(unTranslation, model2.MyAppList{
|
||||
Name: strings.ReplaceAll(m.Names[0], "/", ""),
|
||||
Icon: "",
|
||||
State: m.State,
|
||||
CustomId: m.ID,
|
||||
Id: m.ID,
|
||||
Port: "",
|
||||
NewVersion: false,
|
||||
Host: "",
|
||||
Protocol: "",
|
||||
Image: m.Image,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
return &list
|
||||
//lMap := make(map[string]interface{})
|
||||
// for _, dbModel := range lm {
|
||||
// if position {
|
||||
// if dbModel.Position {
|
||||
// lMap[dbModel.ContainerId] = dbModel
|
||||
// }
|
||||
// } else {
|
||||
// lMap[dbModel.ContainerId] = dbModel
|
||||
// }
|
||||
// }
|
||||
// for _, container := range containers {
|
||||
|
||||
// if lMap[container.ID] != nil && container.Labels["origin"] != "system" {
|
||||
// m := lMap[container.ID].(model2.AppListDBModel)
|
||||
// if len(m.Label) == 0 {
|
||||
// m.Label = m.Title
|
||||
// }
|
||||
|
||||
// // info, err := cli.ContainerInspect(context.Background(), container.ID)
|
||||
// // var tm string
|
||||
// // if err != nil {
|
||||
// // tm = time.Now().String()
|
||||
// // } else {
|
||||
// // tm = info.State.StartedAt
|
||||
// //}
|
||||
// list = append(list, model2.MyAppList{
|
||||
// Name: m.Label,
|
||||
// Icon: m.Icon,
|
||||
// State: container.State,
|
||||
// CustomId: strings.ReplaceAll(container.Names[0], "/", ""),
|
||||
// Port: m.PortMap,
|
||||
// Index: m.Index,
|
||||
// //UpTime: tm,
|
||||
// Image: m.Image,
|
||||
// Slogan: m.Slogan,
|
||||
// //Rely: m.Rely,
|
||||
// })
|
||||
// }
|
||||
|
||||
// }
|
||||
|
||||
return &list, &unTranslation
|
||||
|
||||
}
|
||||
|
||||
//system application list
|
||||
func (a *appStruct) GetSystemAppList() *[]model2.MyAppList {
|
||||
func (a *appStruct) GetSystemAppList() []types.Container {
|
||||
//获取docker应用
|
||||
cli, err := client2.NewClientWithOpts(client2.FromEnv)
|
||||
if err != nil {
|
||||
a.log.Error("初始化client失败", "app.getmylist", "line:36", err)
|
||||
loger.Error("Failed to init client", zap.Any("err", err))
|
||||
}
|
||||
defer cli.Close()
|
||||
fts := filters.NewArgs()
|
||||
fts.Add("label", "origin=system")
|
||||
containers, err := cli.ContainerList(context.Background(), types.ContainerListOptions{All: true, Filters: fts})
|
||||
if err != nil {
|
||||
a.log.Error("获取docker容器失败", "app.sys", "line:123", err)
|
||||
loger.Error("Failed to get container_list", zap.Any("err", err))
|
||||
}
|
||||
|
||||
//获取本地数据库应用
|
||||
|
||||
var lm []model2.AppListDBModel
|
||||
a.db.Table(model2.CONTAINERTABLENAME).Select("title,icon,port_map,`index`,container_id,position,label,slogan,image,volumes").Find(&lm)
|
||||
// var lm []model2.AppListDBModel
|
||||
// a.db.Table(model2.CONTAINERTABLENAME).Select("title,icon,port_map,`index`,container_id,position,label,slogan,image,volumes").Find(&lm)
|
||||
|
||||
list := []model2.MyAppList{}
|
||||
lMap := make(map[string]interface{})
|
||||
for _, dbModel := range lm {
|
||||
lMap[dbModel.ContainerId] = dbModel
|
||||
}
|
||||
for _, container := range containers {
|
||||
//list := []model2.MyAppList{}
|
||||
//lMap := make(map[string]interface{})
|
||||
// for _, dbModel := range lm {
|
||||
// lMap[dbModel.ContainerId] = dbModel
|
||||
// }
|
||||
|
||||
if lMap[container.ID] != nil {
|
||||
m := lMap[container.ID].(model2.AppListDBModel)
|
||||
if len(m.Label) == 0 {
|
||||
m.Label = m.Title
|
||||
}
|
||||
|
||||
info, err := cli.ContainerInspect(context.Background(), container.ID)
|
||||
var tm string
|
||||
if err != nil {
|
||||
tm = time.Now().String()
|
||||
} else {
|
||||
tm = info.State.StartedAt
|
||||
}
|
||||
list = append(list, model2.MyAppList{
|
||||
Name: m.Label,
|
||||
Icon: m.Icon,
|
||||
State: container.State,
|
||||
CustomId: strings.ReplaceAll(container.Names[0], "/", ""),
|
||||
Port: m.PortMap,
|
||||
Index: m.Index,
|
||||
UpTime: tm,
|
||||
Image: m.Image,
|
||||
Slogan: m.Slogan,
|
||||
Volumes: m.Volumes,
|
||||
//Rely: m.Rely,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
return &list
|
||||
return containers
|
||||
|
||||
}
|
||||
func (a *appStruct) GetAllDBApps() []model2.AppListDBModel {
|
||||
var lm []model2.AppListDBModel
|
||||
a.db.Table(model2.CONTAINERTABLENAME).Select("custom_id,title,icon,container_id,label,slogan,image").Find(&lm)
|
||||
a.db.Table(model2.CONTAINERTABLENAME).Select("custom_id,title,icon,container_id,label,slogan,image,port_map").Find(&lm)
|
||||
return lm
|
||||
}
|
||||
|
||||
@@ -179,13 +343,13 @@ func (a *appStruct) GetContainerInfo(name string) (types.Container, error) {
|
||||
//获取docker应用
|
||||
cli, err := client2.NewClientWithOpts(client2.FromEnv)
|
||||
if err != nil {
|
||||
a.log.Error("初始化client失败", "app.getmylist", "line:36", err)
|
||||
loger.Error("Failed to init client", zap.Any("err", err))
|
||||
}
|
||||
filters := filters.NewArgs()
|
||||
filters.Add("name", name)
|
||||
containers, err := cli.ContainerList(context.Background(), types.ContainerListOptions{All: true, Filters: filters})
|
||||
if err != nil {
|
||||
a.log.Error("获取docker容器失败", "app.getcontainerinfo", "line:182", err)
|
||||
loger.Error("Failed to get container_list", zap.Any("err", err))
|
||||
}
|
||||
|
||||
if len(containers) > 0 {
|
||||
@@ -242,7 +406,7 @@ func (a *appStruct) DelAppConfigDir(path string) {
|
||||
command.OnlyExec("source " + config.AppInfo.ProjectPath + "/shell/helper.sh ;DelAppConfigDir " + path)
|
||||
}
|
||||
|
||||
func (a *appStruct) RemoveContainerById(id string) {
|
||||
func (a *appStruct) DeleteApp(id string) {
|
||||
a.db.Table(model2.CONTAINERTABLENAME).Where("custom_id = ?", id).Delete(&model2.AppListDBModel{})
|
||||
}
|
||||
|
||||
@@ -298,31 +462,29 @@ func (a *appStruct) GetHardwareUsageSteam() {
|
||||
ctx := context.Background()
|
||||
ctx, cancel := context.WithCancel(ctx)
|
||||
|
||||
var lm []model2.AppListDBModel
|
||||
a.db.Table(model2.CONTAINERTABLENAME).Select("label,title,icon,container_id").Where("origin != ?", "system").Find(&lm)
|
||||
fts := filters.NewArgs()
|
||||
fts.Add("label", "casaos=casaos")
|
||||
//fts.Add("label", "casaos")
|
||||
//fts.Add("casaos", "casaos")
|
||||
containers, err := cli.ContainerList(context.Background(), types.ContainerListOptions{All: true, Filters: fts})
|
||||
if err != nil {
|
||||
loger.Error("Failed to get container_list", zap.Any("err", err))
|
||||
}
|
||||
for i := 0; i < 100; i++ {
|
||||
if config.CasaOSGlobalVariables.AppChange {
|
||||
lm = []model2.AppListDBModel{}
|
||||
config.CasaOSGlobalVariables.AppChange = false
|
||||
a.db.Table(model2.CONTAINERTABLENAME).Select("label,title,icon,container_id").Where("origin != ?", "system").Find(&lm)
|
||||
dataApps := dataStats
|
||||
|
||||
dataStats.Range(func(key, value interface{}) bool {
|
||||
dataStats.Delete(key)
|
||||
return true
|
||||
})
|
||||
for _, v := range lm {
|
||||
m, _ := dataApps.Load(v.ContainerId)
|
||||
if m != nil {
|
||||
dataStats.Store(v.ContainerId, m)
|
||||
}
|
||||
}
|
||||
}
|
||||
var wg sync.WaitGroup
|
||||
for _, v := range lm {
|
||||
for _, v := range containers {
|
||||
wg.Add(1)
|
||||
go func(v model2.AppListDBModel, i int) {
|
||||
go func(v types.Container, i int) {
|
||||
defer wg.Done()
|
||||
stats, err := cli.ContainerStats(ctx, v.ContainerId, true)
|
||||
stats, err := cli.ContainerStats(ctx, v.ID, true)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
@@ -331,19 +493,15 @@ func (a *appStruct) GetHardwareUsageSteam() {
|
||||
if err := decode.Decode(&data); err == io.EOF {
|
||||
return
|
||||
}
|
||||
m, _ := dataStats.Load(v.ContainerId)
|
||||
m, _ := dataStats.Load(v.ID)
|
||||
dockerStats := model.DockerStatsModel{}
|
||||
if m != nil {
|
||||
dockerStats.Pre = m.(model.DockerStatsModel).Data
|
||||
}
|
||||
dockerStats.Data = data
|
||||
dockerStats.Icon = v.Icon
|
||||
if len(v.Label) > 0 {
|
||||
dockerStats.Title = v.Label
|
||||
} else {
|
||||
dockerStats.Title = v.Title
|
||||
}
|
||||
dataStats.Store(v.ContainerId, dockerStats)
|
||||
dockerStats.Icon = v.Labels["icon"]
|
||||
dockerStats.Title = strings.ReplaceAll(v.Names[0], "/", "")
|
||||
dataStats.Store(v.ID, dockerStats)
|
||||
if i == 99 {
|
||||
stats.Body.Close()
|
||||
}
|
||||
@@ -357,6 +515,6 @@ func (a *appStruct) GetHardwareUsageSteam() {
|
||||
cancel()
|
||||
}
|
||||
|
||||
func NewAppService(db *gorm.DB, logger loger2.OLog) AppService {
|
||||
return &appStruct{db: db, log: logger}
|
||||
func NewAppService(db *gorm.DB) AppService {
|
||||
return &appStruct{db: db}
|
||||
}
|
||||
|
||||
9
service/app_test.go
Normal file
@@ -0,0 +1,9 @@
|
||||
package service
|
||||
|
||||
import (
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestGetCasaOSCount(t *testing.T) {
|
||||
|
||||
}
|
||||
@@ -5,11 +5,13 @@ import (
|
||||
json2 "encoding/json"
|
||||
"fmt"
|
||||
"strconv"
|
||||
"time"
|
||||
|
||||
"github.com/IceWhaleTech/CasaOS/model"
|
||||
"github.com/IceWhaleTech/CasaOS/pkg/config"
|
||||
httper2 "github.com/IceWhaleTech/CasaOS/pkg/utils/httper"
|
||||
model2 "github.com/IceWhaleTech/CasaOS/service/model"
|
||||
"github.com/IceWhaleTech/CasaOS/types"
|
||||
"github.com/tidwall/gjson"
|
||||
)
|
||||
|
||||
@@ -77,24 +79,71 @@ func (o *casaService) GetServerList(index, size, tp, categoryId, key, language s
|
||||
json2.Unmarshal([]byte(gjson.Get(listS, "data.community").String()), &community)
|
||||
|
||||
if len(list) > 0 {
|
||||
Cache.SetDefault(keyName, listS)
|
||||
Cache.Set(keyName, listS, time.Hour*24)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func (o *casaService) GetServerCategoryList() []model.ServerCategoryList {
|
||||
func (o *casaService) GetServerCategoryList() (list []model.ServerCategoryList) {
|
||||
|
||||
keyName := fmt.Sprintf("category_list")
|
||||
if result, ok := Cache.Get(keyName); ok {
|
||||
res, ok := result.(string)
|
||||
if ok {
|
||||
json2.Unmarshal([]byte(gjson.Get(res, "data").String()), &list)
|
||||
return list
|
||||
}
|
||||
}
|
||||
|
||||
head := make(map[string]string)
|
||||
head["Authorization"] = GetToken()
|
||||
|
||||
listS := httper2.Get(config.ServerInfo.ServerApi+"/v2/app/category", head)
|
||||
|
||||
list := []model.ServerCategoryList{}
|
||||
|
||||
json2.Unmarshal([]byte(gjson.Get(listS, "data").String()), &list)
|
||||
|
||||
if len(list) > 0 {
|
||||
Cache.Set(keyName, listS, time.Hour*24)
|
||||
}
|
||||
return list
|
||||
}
|
||||
|
||||
// func (o *casaService) GetServerCategoryList() (list model.ServerCategoryList) {
|
||||
|
||||
// results := file.ReadFullFile(config.AppInfo.ProjectPath + "/conf/app_category.json")
|
||||
// err := json2.Unmarshal(results, &list)
|
||||
// if err != nil {
|
||||
// loger.Error("marshal error", zap.Any("err", err), zap.Any("content", string(results)))
|
||||
// }
|
||||
// return list
|
||||
// }
|
||||
|
||||
// func (o *casaService) AsyncGetServerCategoryList() {
|
||||
// list := model.ServerCategoryList{}
|
||||
// results := file.ReadFullFile(config.AppInfo.ProjectPath + "/conf/app_category.json")
|
||||
// err := json2.Unmarshal(results, &list)
|
||||
// if err != nil {
|
||||
// loger.Error("marshal error", zap.Any("err", err), zap.Any("content", string(results)))
|
||||
// }
|
||||
|
||||
// if list.Version == GetAppVersion() {
|
||||
// return
|
||||
// }
|
||||
// item := []model.CategoryList{}
|
||||
// head := make(map[string]string)
|
||||
// head["Authorization"] = GetToken()
|
||||
// listS := httper2.Get(config.ServerInfo.ServerApi+"/v2/app/category", head)
|
||||
// json2.Unmarshal([]byte(gjson.Get(listS, "data").String()), &item)
|
||||
// if len(item) > 0 {
|
||||
// list.Version = GetAppVersion()
|
||||
// list.Item = item
|
||||
// by, err := json.Marshal(list)
|
||||
// if err != nil {
|
||||
// loger.Error("marshal error", zap.Any("err", err))
|
||||
// }
|
||||
// file.WriteToPath(by, config.AppInfo.ProjectPath+"/conf", "app_category.json")
|
||||
// }
|
||||
// }
|
||||
|
||||
func (o *casaService) GetServerAppInfo(id, t string, language string) model.ServerAppList {
|
||||
|
||||
head := make(map[string]string)
|
||||
@@ -154,6 +203,7 @@ func (o *casaService) PushAppAnalyse(uuid, t string, name, language string) {
|
||||
m.Type = t
|
||||
m.Name = name
|
||||
m.Language = language
|
||||
m.Version = types.CURRENTVERSION
|
||||
b, _ := json.Marshal(m)
|
||||
|
||||
head := make(map[string]string)
|
||||
|
||||
@@ -11,10 +11,11 @@ import (
|
||||
"github.com/IceWhaleTech/CasaOS/model"
|
||||
"github.com/IceWhaleTech/CasaOS/pkg/config"
|
||||
command2 "github.com/IceWhaleTech/CasaOS/pkg/utils/command"
|
||||
loger2 "github.com/IceWhaleTech/CasaOS/pkg/utils/loger"
|
||||
"github.com/IceWhaleTech/CasaOS/pkg/utils/loger"
|
||||
model2 "github.com/IceWhaleTech/CasaOS/service/model"
|
||||
"github.com/shirou/gopsutil/v3/disk"
|
||||
"github.com/tidwall/gjson"
|
||||
"go.uber.org/zap"
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
|
||||
@@ -37,7 +38,6 @@ type DiskService interface {
|
||||
RemoveLSBLKCache()
|
||||
}
|
||||
type diskService struct {
|
||||
log loger2.OLog
|
||||
db *gorm.DB
|
||||
}
|
||||
|
||||
@@ -58,16 +58,16 @@ func (d *diskService) SmartCTL(path string) model.SmartctlA {
|
||||
var m model.SmartctlA
|
||||
str := command2.ExecSmartCTLByPath(path)
|
||||
if str == nil {
|
||||
d.log.Error("smartctl exec error,smartctl")
|
||||
loger.Error("failed to exec shell ", zap.Any("err", "smartctl exec error"))
|
||||
return m
|
||||
}
|
||||
|
||||
err := json2.Unmarshal([]byte(str), &m)
|
||||
if err != nil {
|
||||
d.log.Error("json ummarshal error", err)
|
||||
loger.Error("Failed to unmarshal json", zap.Any("err", err))
|
||||
}
|
||||
if !reflect.DeepEqual(m, model.SmartctlA{}) {
|
||||
Cache.Add(key, m, time.Second*10)
|
||||
Cache.Add(key, m, time.Hour*24)
|
||||
}
|
||||
return m
|
||||
}
|
||||
@@ -133,13 +133,13 @@ func (d *diskService) LSBLK(isUseCache bool) []model.LSBLKModel {
|
||||
|
||||
str := command2.ExecLSBLK()
|
||||
if str == nil {
|
||||
d.log.Error("lsblk exec error,lsblk")
|
||||
loger.Error("Failed to exec shell", zap.Any("err", "lsblk exec error"))
|
||||
return nil
|
||||
}
|
||||
var m []model.LSBLKModel
|
||||
err := json2.Unmarshal([]byte(gjson.Get(string(str), "blockdevices").String()), &m)
|
||||
if err != nil {
|
||||
d.log.Error("json ummarshal error", err)
|
||||
loger.Error("Failed to unmarshal json", zap.Any("err", err))
|
||||
}
|
||||
|
||||
var c []model.LSBLKModel
|
||||
@@ -172,7 +172,7 @@ func (d *diskService) LSBLK(isUseCache bool) []model.LSBLKModel {
|
||||
if fsused > 0 {
|
||||
i.UsedPercent, err = strconv.ParseFloat(fmt.Sprintf("%.4f", float64(fsused)/float64(i.Size)), 64)
|
||||
if err != nil {
|
||||
d.log.Fatal("diskservice_lsblk_fsused", err)
|
||||
loger.Error("Failed to parse float", zap.Any("err", err))
|
||||
}
|
||||
}
|
||||
n = append(n, i)
|
||||
@@ -190,15 +190,14 @@ func (d *diskService) LSBLK(isUseCache bool) []model.LSBLKModel {
|
||||
func (d *diskService) GetDiskInfo(path string) model.LSBLKModel {
|
||||
str := command2.ExecLSBLKByPath(path)
|
||||
if str == nil {
|
||||
d.log.Error("lsblk exec error,str")
|
||||
loger.Error("Failed to exec shell", zap.Any("err", "lsblk exec error"))
|
||||
return model.LSBLKModel{}
|
||||
}
|
||||
|
||||
var ml []model.LSBLKModel
|
||||
err := json2.Unmarshal([]byte(gjson.Get(string(str), "blockdevices").String()), &ml)
|
||||
if err != nil {
|
||||
d.log.Info(string(str))
|
||||
d.log.Error("json ummarshal error", err)
|
||||
loger.Error("Failed to unmarshal json", zap.Any("err", err))
|
||||
return model.LSBLKModel{}
|
||||
}
|
||||
|
||||
@@ -211,8 +210,7 @@ func (d *diskService) GetDiskInfo(path string) model.LSBLKModel {
|
||||
chiArr := make(map[string]string)
|
||||
chiList := command2.ExecResultStrArray("source " + config.AppInfo.ProjectPath + "/shell/helper.sh ;GetPartitionSectors " + m.Path)
|
||||
if len(chiList) == 0 {
|
||||
d.log.Error(m.Path, chiList)
|
||||
d.log.Error("chiList length error")
|
||||
loger.Error("chiList length error", zap.Any("err", "chiList length error"))
|
||||
}
|
||||
for i := 0; i < len(chiList); i++ {
|
||||
tempArr := strings.Split(chiList[i], ",")
|
||||
@@ -231,7 +229,7 @@ func (d *diskService) GetDiskInfo(path string) model.LSBLKModel {
|
||||
diskEndSector := command2.ExecResultStrArray("source " + config.AppInfo.ProjectPath + "/shell/helper.sh ;GetDiskSizeAndSectors " + m.Path)
|
||||
|
||||
if len(diskEndSector) < 2 {
|
||||
d.log.Error("diskEndSector length error")
|
||||
loger.Error("diskEndSector length error", zap.Any("err", "diskEndSector length error"))
|
||||
}
|
||||
diskEndSectorInt, _ := strconv.ParseUint(diskEndSector[len(diskEndSector)-1], 10, 64)
|
||||
if (diskEndSectorInt-maxSector)*m.MinIO/1024/1024 > 100 {
|
||||
@@ -275,6 +273,6 @@ func (d *diskService) GetSerialAll() []model2.SerialDisk {
|
||||
return m
|
||||
}
|
||||
|
||||
func NewDiskService(log loger2.OLog, db *gorm.DB) DiskService {
|
||||
return &diskService{log: log, db: db}
|
||||
func NewDiskService(db *gorm.DB) DiskService {
|
||||
return &diskService{db: db}
|
||||
}
|
||||
|
||||
@@ -7,22 +7,22 @@ import (
|
||||
"encoding/binary"
|
||||
json2 "encoding/json"
|
||||
"fmt"
|
||||
"reflect"
|
||||
"syscall"
|
||||
|
||||
model2 "github.com/IceWhaleTech/CasaOS/service/model"
|
||||
types2 "github.com/IceWhaleTech/CasaOS/types"
|
||||
"github.com/IceWhaleTech/CasaOS/model/notify"
|
||||
"github.com/containerd/containerd"
|
||||
"github.com/containerd/containerd/cio"
|
||||
"github.com/containerd/containerd/namespaces"
|
||||
"github.com/containerd/containerd/oci"
|
||||
"github.com/pkg/errors"
|
||||
"go.uber.org/zap"
|
||||
|
||||
"github.com/IceWhaleTech/CasaOS/model"
|
||||
"github.com/IceWhaleTech/CasaOS/pkg/docker"
|
||||
command2 "github.com/IceWhaleTech/CasaOS/pkg/utils/command"
|
||||
"github.com/IceWhaleTech/CasaOS/pkg/utils/env_helper"
|
||||
"github.com/IceWhaleTech/CasaOS/pkg/utils/file"
|
||||
loger2 "github.com/IceWhaleTech/CasaOS/pkg/utils/loger"
|
||||
"github.com/IceWhaleTech/CasaOS/pkg/utils/loger"
|
||||
|
||||
//"github.com/containerd/containerd/oci"
|
||||
"io"
|
||||
@@ -43,9 +43,10 @@ import (
|
||||
)
|
||||
|
||||
type DockerService interface {
|
||||
DockerPullImage(imageName string, m model2.AppNotify) error
|
||||
DockerPullImage(imageName string, icon, name string) error
|
||||
IsExistImage(imageName string) bool
|
||||
DockerContainerCreate(imageName string, containerDbId string, m model.CustomizationPostData, net string) (containerId string, err error)
|
||||
DockerContainerCreate(imageName string, m model.CustomizationPostData, net string) (containerId string, err error)
|
||||
DockerContainerCopyCreate(info *types.ContainerJSON) (containerId string, err error)
|
||||
DockerContainerStart(name string) error
|
||||
DockerContainerStats(name string) (string, error)
|
||||
DockerListByName(name string) (*types.Container, error)
|
||||
@@ -58,15 +59,28 @@ type DockerService interface {
|
||||
DockerContainerUpdate(m model.CustomizationPostData, id string) (err error)
|
||||
DockerContainerLog(name string) (string, error)
|
||||
DockerContainerCommit(name string)
|
||||
DockerContainerList() []types.Container
|
||||
DockerNetworkModelList() []types.NetworkResource
|
||||
DockerImageInfo(image string)
|
||||
DockerImageInfo(image string) (types.ImageInspect, error)
|
||||
GetNetWorkNameByNetWorkID(id string) (string, error)
|
||||
ContainerExecShell(container_id string) string
|
||||
}
|
||||
|
||||
type dockerService struct {
|
||||
rootDir string
|
||||
log loger2.OLog
|
||||
}
|
||||
|
||||
func (ds *dockerService) DockerContainerList() []types.Container {
|
||||
cli, err := client2.NewClientWithOpts(client2.FromEnv, client2.WithTimeout(time.Second*5))
|
||||
if err != nil {
|
||||
return nil
|
||||
}
|
||||
defer cli.Close()
|
||||
containers, err := cli.ContainerList(context.Background(), types.ContainerListOptions{All: true})
|
||||
if err != nil {
|
||||
return containers
|
||||
}
|
||||
return containers
|
||||
}
|
||||
|
||||
func (ds *dockerService) ContainerExecShell(container_id string) string {
|
||||
@@ -119,10 +133,7 @@ func DockerPull() {
|
||||
cli, _ := client2.NewClientWithOpts(client2.FromEnv)
|
||||
defer cli.Close()
|
||||
|
||||
authConfig := types.AuthConfig{
|
||||
Username: "cn-north-4@M4OW0IULZ3U6PCQPBUZC",
|
||||
Password: "7390181a1565f90927bbd98038436b57d6ebc66a3828d7a11dfda42b9c19d91d",
|
||||
}
|
||||
authConfig := types.AuthConfig{}
|
||||
encodedJSON, err := json2.Marshal(authConfig)
|
||||
fmt.Println(err)
|
||||
|
||||
@@ -174,18 +185,16 @@ func DockerEx() {
|
||||
//
|
||||
//}
|
||||
|
||||
func (ds *dockerService) DockerImageInfo(image string) {
|
||||
func (ds *dockerService) DockerImageInfo(image string) (types.ImageInspect, error) {
|
||||
cli, err := client2.NewClientWithOpts(client2.FromEnv)
|
||||
|
||||
//but := bytes.Buffer{}
|
||||
d, b, err := cli.ImageInspectWithRaw(context.Background(), image)
|
||||
st, _ := json2.Marshal(d.Config)
|
||||
fmt.Println(string(st))
|
||||
fmt.Println("换行")
|
||||
fmt.Println(string(b))
|
||||
if err != nil {
|
||||
fmt.Print(err)
|
||||
return types.ImageInspect{}, err
|
||||
}
|
||||
inspect, _, err := cli.ImageInspectWithRaw(context.Background(), image)
|
||||
if err != nil {
|
||||
return inspect, err
|
||||
}
|
||||
return inspect, nil
|
||||
}
|
||||
|
||||
func MsqlExec(container string) error {
|
||||
@@ -308,7 +317,7 @@ func (ds *dockerService) IsExistImage(imageName string) bool {
|
||||
}
|
||||
|
||||
//安装镜像
|
||||
func (ds *dockerService) DockerPullImage(imageName string, m model2.AppNotify) error {
|
||||
func (ds *dockerService) DockerPullImage(imageName string, icon, name string) error {
|
||||
cli, err := client2.NewClientWithOpts(client2.FromEnv)
|
||||
if err != nil {
|
||||
return err
|
||||
@@ -323,7 +332,8 @@ func (ds *dockerService) DockerPullImage(imageName string, m model2.AppNotify) e
|
||||
|
||||
return err
|
||||
}
|
||||
buf := make([]byte, 256)
|
||||
//io.Copy()
|
||||
buf := make([]byte, 2048*4)
|
||||
for {
|
||||
n, err := out.Read(buf)
|
||||
if err != nil {
|
||||
@@ -332,16 +342,33 @@ func (ds *dockerService) DockerPullImage(imageName string, m model2.AppNotify) e
|
||||
}
|
||||
break
|
||||
}
|
||||
if !reflect.DeepEqual(m, model2.AppNotify{}) {
|
||||
m.Type = types2.NOTIFY_TYPE_INSTALL_LOG
|
||||
m.State = 0
|
||||
m.Message = string(buf[:n])
|
||||
MyService.Notify().UpdateLog(m)
|
||||
if len(icon) > 0 && len(name) > 0 {
|
||||
notify := notify.Application{}
|
||||
notify.Icon = icon
|
||||
notify.Name = name
|
||||
notify.State = "PULLING"
|
||||
notify.Type = "INSTALL"
|
||||
notify.Finished = false
|
||||
notify.Success = true
|
||||
notify.Message = string(buf[:n])
|
||||
MyService.Notify().SendInstallAppBySocket(notify)
|
||||
}
|
||||
|
||||
}
|
||||
return err
|
||||
}
|
||||
func (ds *dockerService) DockerContainerCopyCreate(info *types.ContainerJSON) (containerId string, err error) {
|
||||
cli, err := client2.NewClientWithOpts(client2.FromEnv)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
defer cli.Close()
|
||||
container, err := cli.ContainerCreate(context.Background(), info.Config, info.HostConfig, &network.NetworkingConfig{info.NetworkSettings.Networks}, nil, info.Name)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
return container.ID, err
|
||||
}
|
||||
|
||||
//param imageName 镜像名称
|
||||
//param containerDbId 数据库的id
|
||||
@@ -349,7 +376,7 @@ func (ds *dockerService) DockerPullImage(imageName string, m model2.AppNotify) e
|
||||
//param mapPort 容器主端口映射到外部的端口
|
||||
//param tcp 容器其他tcp端口
|
||||
//param udp 容器其他udp端口
|
||||
func (ds *dockerService) DockerContainerCreate(imageName string, containerDbId string, m model.CustomizationPostData, net string) (containerId string, err error) {
|
||||
func (ds *dockerService) DockerContainerCreate(imageName string, m model.CustomizationPostData, net string) (containerId string, err error) {
|
||||
if len(net) == 0 {
|
||||
net = "bridge"
|
||||
}
|
||||
@@ -410,7 +437,10 @@ func (ds *dockerService) DockerContainerCreate(imageName string, containerDbId s
|
||||
}
|
||||
|
||||
var envArr []string
|
||||
var showENV []string
|
||||
showENV = append(showENV, "casaos")
|
||||
for _, e := range m.Envs {
|
||||
showENV = append(showENV, e.Name)
|
||||
if strings.HasPrefix(e.Value, "$") {
|
||||
envArr = append(envArr, e.Name+"="+env_helper.ReplaceDefaultENV(e.Value, MyService.System().GetTimeZone()))
|
||||
continue
|
||||
@@ -442,18 +472,18 @@ func (ds *dockerService) DockerContainerCreate(imageName string, containerDbId s
|
||||
for _, v := range m.Volumes {
|
||||
path := v.Path
|
||||
if len(path) == 0 {
|
||||
path = docker.GetDir(containerDbId, v.Path)
|
||||
path = docker.GetDir(m.Label, v.Path)
|
||||
if len(path) == 0 {
|
||||
continue
|
||||
}
|
||||
}
|
||||
path = strings.ReplaceAll(path, "$AppID", containerDbId)
|
||||
path = strings.ReplaceAll(path, "$AppID", m.Label)
|
||||
//reg1 := regexp.MustCompile(`([^<>/\\\|:""\*\?]+\.\w+$)`)
|
||||
//result1 := reg1.FindAllStringSubmatch(path, -1)
|
||||
//if len(result1) == 0 {
|
||||
err = file.IsNotExistMkDir(path)
|
||||
if err != nil {
|
||||
ds.log.Error("mkdir error", err)
|
||||
loger.Error("Failed to create a folder", zap.Any("err", err))
|
||||
continue
|
||||
}
|
||||
//}
|
||||
@@ -495,12 +525,22 @@ func (ds *dockerService) DockerContainerCreate(imageName string, containerDbId s
|
||||
}
|
||||
config := &container.Config{
|
||||
Image: imageName,
|
||||
Labels: map[string]string{"origin": m.Origin, m.Origin: m.Origin},
|
||||
Labels: map[string]string{"origin": m.Origin, m.Origin: m.Origin, "casaos": "casaos"},
|
||||
Env: envArr,
|
||||
// Healthcheck: health,
|
||||
Hostname: m.HostName,
|
||||
Cmd: m.Cmd,
|
||||
}
|
||||
|
||||
config.Labels["web"] = m.PortMap
|
||||
config.Labels["icon"] = m.Icon
|
||||
config.Labels["desc"] = m.Description
|
||||
config.Labels["index"] = m.Index
|
||||
config.Labels["custom_id"] = m.CustomId
|
||||
config.Labels["show_env"] = strings.Join(showENV, ",")
|
||||
config.Labels["protocol"] = m.Protocol
|
||||
config.Labels["host"] = m.Host
|
||||
//config.Labels["order"] = strconv.Itoa(MyService.App().GetCasaOSCount() + 1)
|
||||
hostConfig := &container.HostConfig{Resources: res, Mounts: volumes, RestartPolicy: rp, NetworkMode: container.NetworkMode(net), Privileged: m.Privileged, CapAdd: m.CapAdd}
|
||||
//if net != "host" {
|
||||
config.ExposedPorts = ports
|
||||
@@ -512,7 +552,7 @@ func (ds *dockerService) DockerContainerCreate(imageName string, containerDbId s
|
||||
hostConfig,
|
||||
&network.NetworkingConfig{EndpointsConfig: map[string]*network.EndpointSettings{net: {NetworkID: "", Aliases: []string{}}}},
|
||||
nil,
|
||||
containerDbId)
|
||||
m.Label)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
@@ -695,6 +735,9 @@ func (ds *dockerService) DockerListByName(name string) (*types.Container, error)
|
||||
if err != nil {
|
||||
return &types.Container{}, err
|
||||
}
|
||||
if len(containers) == 0 {
|
||||
return &types.Container{}, errors.New("not found")
|
||||
}
|
||||
return &containers[0], nil
|
||||
}
|
||||
|
||||
@@ -794,8 +837,8 @@ func (ds *dockerService) DockerNetworkModelList() []types.NetworkResource {
|
||||
networks, _ := cli.NetworkList(context.Background(), types.NetworkListOptions{})
|
||||
return networks
|
||||
}
|
||||
func NewDockerService(log loger2.OLog) DockerService {
|
||||
return &dockerService{rootDir: command2.ExecResultStr(`source ./shell/helper.sh ;GetDockerRootDir`), log: log}
|
||||
func NewDockerService() DockerService {
|
||||
return &dockerService{rootDir: command2.ExecResultStr(`source ./shell/helper.sh ;GetDockerRootDir`)}
|
||||
}
|
||||
|
||||
// ---------------------------------------test------------------------------------
|
||||
|
||||
33
service/down_record.go
Normal file
@@ -0,0 +1,33 @@
|
||||
package service
|
||||
|
||||
import (
|
||||
model2 "github.com/IceWhaleTech/CasaOS/service/model"
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
|
||||
type DownRecordService interface {
|
||||
AddDownRecord(m model2.PersonDownRecordDBModel)
|
||||
GetDownloadListByFrom(id string) []model2.PersonDownRecordDBModel
|
||||
GetDownloadListByPath(path string) (list []model2.PersonDownRecordDBModel)
|
||||
}
|
||||
type downRecordService struct {
|
||||
db *gorm.DB
|
||||
}
|
||||
|
||||
func (d *downRecordService) AddDownRecord(m model2.PersonDownRecordDBModel) {
|
||||
d.db.Create(&m)
|
||||
}
|
||||
|
||||
func (d *downRecordService) GetDownloadListByFrom(id string) []model2.PersonDownRecordDBModel {
|
||||
var m []model2.PersonDownRecordDBModel
|
||||
d.db.Model(m).Where("from = ?", id).Find(&m)
|
||||
return m
|
||||
}
|
||||
func (d *downRecordService) GetDownloadListByPath(path string) (list []model2.PersonDownRecordDBModel) {
|
||||
d.db.Where("path = ?", path).Find(&list)
|
||||
return
|
||||
}
|
||||
|
||||
func NewDownRecordService(db *gorm.DB) DownRecordService {
|
||||
return &downRecordService{db: db}
|
||||
}
|
||||
@@ -11,7 +11,7 @@ type DownloadService interface {
|
||||
SaveDownload(m model2.PersonDownloadDBModel)
|
||||
DelDownload(uuid string)
|
||||
GetDownloadById(uuid string) model2.PersonDownloadDBModel
|
||||
GetDownloadListByState(state string) []model2.PersonDownloadDBModel
|
||||
GetDownloadListByState(state string, t int) []model2.PersonDownloadDBModel
|
||||
SetDownloadError(m model2.PersonDownloadDBModel)
|
||||
GetDownloadListByPath(m model2.PersonDownloadDBModel) int
|
||||
}
|
||||
@@ -48,11 +48,11 @@ func (d *downloadService) GetDownloadById(uuid string) model2.PersonDownloadDBMo
|
||||
d.db.Model(m).Where("uuid = ?", uuid).First(&m)
|
||||
return m
|
||||
}
|
||||
func (d *downloadService) GetDownloadListByState(state string) (list []model2.PersonDownloadDBModel) {
|
||||
func (d *downloadService) GetDownloadListByState(state string, t int) (list []model2.PersonDownloadDBModel) {
|
||||
if len(state) == 0 {
|
||||
d.db.Find(&list)
|
||||
d.db.Where("type = ?", t).Find(&list)
|
||||
} else {
|
||||
d.db.Where("state = ?", state).Find(&list)
|
||||
d.db.Where("state = ? AND type= ?", state, t).Find(&list)
|
||||
}
|
||||
|
||||
return
|
||||
|
||||
142
service/file.go
@@ -1,38 +1,33 @@
|
||||
/*
|
||||
* @Author: LinkLeong link@icewhale.com
|
||||
* @Date: 2021-12-20 14:15:46
|
||||
* @LastEditors: LinkLeong
|
||||
* @LastEditTime: 2022-06-09 18:15:54
|
||||
* @FilePath: /CasaOS/service/file.go
|
||||
* @Description:
|
||||
* @Website: https://www.casaos.io
|
||||
* Copyright (c) 2022 by icewhale, All Rights Reserved.
|
||||
*/
|
||||
package service
|
||||
|
||||
import (
|
||||
"context"
|
||||
"io"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/IceWhaleTech/CasaOS/model"
|
||||
"github.com/IceWhaleTech/CasaOS/pkg/utils/file"
|
||||
"github.com/IceWhaleTech/CasaOS/pkg/utils/loger"
|
||||
"go.uber.org/zap"
|
||||
)
|
||||
|
||||
// type InteruptReader struct {
|
||||
// r io.Reader
|
||||
// interupt chan int
|
||||
// }
|
||||
var FileQueue sync.Map
|
||||
|
||||
// func NewInteruptReader(r io.Reader) InteruptReader {
|
||||
// return InteruptReader{
|
||||
// r,
|
||||
// make(chan int),
|
||||
// }
|
||||
// }
|
||||
|
||||
// func (r InteruptReader) Read(p []byte) (n int, err error) {
|
||||
// if r.r == nil {
|
||||
// return 0, io.EOF
|
||||
// }
|
||||
// select {
|
||||
// case <-r.interupt:
|
||||
// return r.r.Read(p)
|
||||
// default:
|
||||
// r.r = nil
|
||||
// return 0, io.EOF
|
||||
// }
|
||||
// }
|
||||
|
||||
// func (r InteruptReader) Cancel() {
|
||||
// r.interupt <- 0
|
||||
// }
|
||||
var OpStrArr []string
|
||||
|
||||
type reader struct {
|
||||
ctx context.Context
|
||||
@@ -83,3 +78,96 @@ func (w *writer) Write(p []byte) (n int, err error) {
|
||||
return w.w.Write(p)
|
||||
}
|
||||
}
|
||||
func FileOperate(k string) {
|
||||
|
||||
list, ok := FileQueue.Load(k)
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
|
||||
temp := list.(model.FileOperate)
|
||||
if temp.ProcessedSize > 0 {
|
||||
return
|
||||
}
|
||||
for i := 0; i < len(temp.Item); i++ {
|
||||
v := temp.Item[i]
|
||||
if temp.Type == "move" {
|
||||
lastPath := v.From[strings.LastIndex(v.From, "/")+1:]
|
||||
|
||||
if !file.CheckNotExist(temp.To + "/" + lastPath) {
|
||||
if temp.Style == "skip" {
|
||||
temp.Item[i].Finished = true
|
||||
continue
|
||||
} else {
|
||||
os.Remove(temp.To + "/" + lastPath)
|
||||
}
|
||||
}
|
||||
|
||||
err := os.Rename(v.From, temp.To+"/"+lastPath)
|
||||
if err != nil {
|
||||
loger.Debug("file move error", zap.Any("err", err))
|
||||
continue
|
||||
}
|
||||
} else if temp.Type == "copy" {
|
||||
err := file.CopyDir(v.From, temp.To, temp.Style)
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
} else {
|
||||
continue
|
||||
}
|
||||
|
||||
}
|
||||
temp.Finished = true
|
||||
FileQueue.Store(k, temp)
|
||||
}
|
||||
|
||||
func ExecOpFile() {
|
||||
len := len(OpStrArr)
|
||||
if len == 0 {
|
||||
return
|
||||
}
|
||||
if len > 1 {
|
||||
len = 1
|
||||
}
|
||||
for i := 0; i < len; i++ {
|
||||
go FileOperate(OpStrArr[i])
|
||||
}
|
||||
}
|
||||
|
||||
// file move or copy and send notify
|
||||
func CheckFileStatus() {
|
||||
for {
|
||||
if len(OpStrArr) == 0 {
|
||||
return
|
||||
}
|
||||
for _, v := range OpStrArr {
|
||||
var total int64 = 0
|
||||
item, ok := FileQueue.Load(v)
|
||||
if !ok {
|
||||
continue
|
||||
}
|
||||
temp := item.(model.FileOperate)
|
||||
for i := 0; i < len(temp.Item); i++ {
|
||||
|
||||
if !temp.Item[i].Finished {
|
||||
size, err := file.GetFileOrDirSize(temp.To + "/" + filepath.Base(temp.Item[i].From))
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
temp.Item[i].ProcessedSize = size
|
||||
if size == temp.Item[i].Size {
|
||||
temp.Item[i].Finished = true
|
||||
}
|
||||
total += size
|
||||
} else {
|
||||
total += temp.Item[i].ProcessedSize
|
||||
}
|
||||
|
||||
}
|
||||
temp.ProcessedSize = total
|
||||
FileQueue.Store(v, temp)
|
||||
}
|
||||
time.Sleep(time.Second * 3)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,9 +1,20 @@
|
||||
package service
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"net"
|
||||
"reflect"
|
||||
"strconv"
|
||||
"time"
|
||||
|
||||
"github.com/IceWhaleTech/CasaOS/model"
|
||||
"github.com/IceWhaleTech/CasaOS/pkg/config"
|
||||
"github.com/IceWhaleTech/CasaOS/pkg/quic_helper"
|
||||
model2 "github.com/IceWhaleTech/CasaOS/service/model"
|
||||
"github.com/IceWhaleTech/CasaOS/types"
|
||||
"github.com/lucas-clemente/quic-go"
|
||||
uuid "github.com/satori/go.uuid"
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
|
||||
@@ -11,17 +22,26 @@ type FriendService interface {
|
||||
AddFriend(m model2.FriendModel)
|
||||
DeleteFriend(m model2.FriendModel)
|
||||
EditFriendMark(m model2.FriendModel)
|
||||
EditFriendWrite(m model2.FriendModel)
|
||||
EditFriendBlock(m model2.FriendModel)
|
||||
GetFriendById(m model2.FriendModel) model2.FriendModel
|
||||
GetFriendList() (list []model2.FriendModel)
|
||||
GetFriendListRemote() (list []model2.FriendModel)
|
||||
UpdateAddFriendType(m model2.FriendModel)
|
||||
AgreeFrined(id string)
|
||||
GetFriendByToken(token string) model2.FriendModel
|
||||
UpdateOrCreate(m model2.FriendModel)
|
||||
InternalInspection(ips []string, token string)
|
||||
}
|
||||
|
||||
type friendService struct {
|
||||
db *gorm.DB
|
||||
}
|
||||
|
||||
func (p *friendService) AgreeFrined(id string) {
|
||||
var m model2.FriendModel
|
||||
p.db.Model(&m).Where("token = ?", id).Update("state", types.FRIENDSTATEDEFAULT)
|
||||
}
|
||||
func (p *friendService) AddFriend(m model2.FriendModel) {
|
||||
p.db.Create(&m)
|
||||
}
|
||||
@@ -31,6 +51,9 @@ func (p *friendService) DeleteFriend(m model2.FriendModel) {
|
||||
func (p *friendService) EditFriendMark(m model2.FriendModel) {
|
||||
p.db.Model(&m).Where("token = ?", m.Token).Update("mark", m.Mark)
|
||||
}
|
||||
func (p *friendService) EditFriendWrite(m model2.FriendModel) {
|
||||
p.db.Model(&m).Where("token = ?", m.Token).Update("write", m.Write)
|
||||
}
|
||||
func (p *friendService) EditFriendBlock(m model2.FriendModel) {
|
||||
p.db.Model(&m).Where("token = ?", m.Token).Update("block", m.Block)
|
||||
}
|
||||
@@ -43,7 +66,14 @@ func (p *friendService) GetFriendList() (list []model2.FriendModel) {
|
||||
p.db.Select("nick_name", "avatar", "profile", "token", "state", "mark", "block", "version").Find(&list)
|
||||
return list
|
||||
}
|
||||
|
||||
func (p *friendService) GetFriendListRemote() (list []model2.FriendModel) {
|
||||
p.db.Select("nick_name", "avatar", "profile", "token", "state", "mark", "block", "version").Where("internal_ip == '' OR internal_ip is null").Find(&list)
|
||||
return list
|
||||
}
|
||||
func (p *friendService) GetFriendListInternal() (list []model2.FriendModel) {
|
||||
p.db.Select("nick_name", "avatar", "profile", "token", "state", "mark", "block", "version").Where("internal_ip != ''").Find(&list)
|
||||
return list
|
||||
}
|
||||
func (p *friendService) UpdateOrCreate(m model2.FriendModel) {
|
||||
friend := model2.FriendModel{}
|
||||
p.db.Where("token = ?", m.Token).First(&friend)
|
||||
@@ -59,6 +89,67 @@ func (p *friendService) UpdateAddFriendType(m model2.FriendModel) {
|
||||
p.db.Model(&m).Updates(m)
|
||||
}
|
||||
|
||||
func (p *friendService) GetFriendByToken(token string) model2.FriendModel {
|
||||
var m model2.FriendModel
|
||||
p.db.Model(&m).Where("token = ?", token).First(&m)
|
||||
return m
|
||||
}
|
||||
|
||||
func (p *friendService) InternalInspection(ips []string, token string) {
|
||||
for _, v := range ips {
|
||||
fmt.Println("开始遍历 ip:", v)
|
||||
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
|
||||
defer cancel()
|
||||
|
||||
dstAddr, err := net.ResolveUDPAddr("udp", v)
|
||||
if err != nil {
|
||||
fmt.Println("1", err.Error())
|
||||
continue
|
||||
}
|
||||
port, err := strconv.Atoi(config.ServerInfo.UDPPort)
|
||||
if err != nil {
|
||||
fmt.Println("2", err)
|
||||
continue
|
||||
}
|
||||
srcAddr := &net.UDPAddr{
|
||||
IP: net.IPv4zero, Port: port}
|
||||
ticket := token
|
||||
session, err := quic.DialContext(ctx, UDPConn, dstAddr, srcAddr.String(), quic_helper.GetClientTlsConfig(ticket), quic_helper.GetQUICConfig())
|
||||
if err != nil {
|
||||
fmt.Println("3", err, v)
|
||||
continue
|
||||
}
|
||||
|
||||
stream, err := session.OpenStreamSync(ctx)
|
||||
if err != nil {
|
||||
fmt.Println("4", err)
|
||||
continue
|
||||
}
|
||||
uuid := uuid.NewV4().String()
|
||||
SayHello(stream, token)
|
||||
msg := model.MessageModel{
|
||||
Type: types.PERSONPING,
|
||||
Data: "",
|
||||
From: config.ServerInfo.Token,
|
||||
To: token,
|
||||
UUId: uuid,
|
||||
}
|
||||
|
||||
SendData(stream, msg)
|
||||
|
||||
go ReadContent(stream)
|
||||
result := <-Message
|
||||
fmt.Println("ping返回结果:", result, msg)
|
||||
stream.Close()
|
||||
if !reflect.DeepEqual(result, model.MessageModel{}) && result.Data.(string) == token && result.From == token {
|
||||
fmt.Println("获取到正确的ip", v)
|
||||
UDPAddressMap[result.From] = v
|
||||
p.db.Model(&model2.FriendModel{}).Where("token = ?", token).Update("internal_ip", v)
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func NewFriendService(db *gorm.DB) FriendService {
|
||||
return &friendService{db: db}
|
||||
}
|
||||
|
||||
20
service/model/o_application.go
Normal file
@@ -0,0 +1,20 @@
|
||||
package model
|
||||
|
||||
import (
|
||||
"time"
|
||||
)
|
||||
|
||||
type ApplicationModel struct {
|
||||
Id int `gorm:"column:id;primary_key" json:"id"`
|
||||
Name string `json:"name"`
|
||||
Icon string `json:"icon"`
|
||||
State int `json:"state"`
|
||||
Type string `json:"type"`
|
||||
Order int `json:"order"`
|
||||
CreatedAt time.Time `gorm:"<-:create" json:"created_at"`
|
||||
UpdatedAt time.Time `gorm:"<-:create;<-:update" json:"updated_at"`
|
||||
}
|
||||
|
||||
func (p *ApplicationModel) TableName() string {
|
||||
return "o_application"
|
||||
}
|
||||
@@ -1,11 +1,18 @@
|
||||
/*
|
||||
* @Author: LinkLeong link@icewhale.com
|
||||
* @Date: 2022-05-13 18:15:46
|
||||
* @LastEditors: LinkLeong
|
||||
* @LastEditTime: 2022-05-30 17:33:21
|
||||
* @FilePath: /CasaOS/service/model/o_container.go
|
||||
* @Description:
|
||||
* @Website: https://www.casaos.io
|
||||
* Copyright (c) 2022 by icewhale, All Rights Reserved.
|
||||
*/
|
||||
package model
|
||||
|
||||
import (
|
||||
"github.com/IceWhaleTech/CasaOS/model"
|
||||
)
|
||||
|
||||
const CONTAINERTABLENAME = "o_container"
|
||||
|
||||
//Soon to be removed
|
||||
type AppListDBModel struct {
|
||||
CustomId string `gorm:"column:custom_id;primary_key" json:"custom_id"`
|
||||
Title string `json:"title"`
|
||||
@@ -52,15 +59,21 @@ func (p *AppListDBModel) TableName() string {
|
||||
}
|
||||
|
||||
type MyAppList struct {
|
||||
Id string `json:"id"`
|
||||
Name string `json:"name"`
|
||||
Icon string `json:"icon"`
|
||||
State string `json:"state"`
|
||||
CustomId string `gorm:"column:custom_id;primary_key" json:"custom_id"`
|
||||
Index string `json:"index"`
|
||||
//Order string `json:"order"`
|
||||
Port string `json:"port"`
|
||||
UpTime string `json:"up_time"`
|
||||
Slogan string `json:"slogan"`
|
||||
Rely model.MapStrings `json:"rely"` //[{"mysql":"id"},{"mysql":"id"}]
|
||||
Type string `json:"type"`
|
||||
//Rely model.MapStrings `json:"rely"` //[{"mysql":"id"},{"mysql":"id"}]
|
||||
Image string `json:"image"`
|
||||
Volumes string `json:"volumes"`
|
||||
NewVersion bool `json:"new_version"`
|
||||
Host string `json:"host"`
|
||||
Protocol string `json:"protocol"`
|
||||
}
|
||||
|
||||
16
service/model/o_down_record.go
Normal file
@@ -0,0 +1,16 @@
|
||||
package model
|
||||
|
||||
type PersonDownRecordDBModel struct {
|
||||
UUID string `gorm:"column:uuid;primary_key" json:"uuid"`
|
||||
Name string `json:"name"` //file name
|
||||
Type int `json:"type"`
|
||||
Size int64 `json:"size"` //file size
|
||||
Downloader string `json:"downloader"` //Error message
|
||||
Path string `json:"path"`
|
||||
Created int64 `gorm:"autoCreateTime" json:"created"`
|
||||
Updated int64 `gorm:"autoCreateTime;autoUpdateTime" json:"updated"`
|
||||
}
|
||||
|
||||
func (p *PersonDownRecordDBModel) TableName() string {
|
||||
return "o_person_down_record"
|
||||
}
|
||||
@@ -3,7 +3,7 @@ package model
|
||||
type PersonDownloadDBModel struct {
|
||||
UUID string `gorm:"column:uuid;primary_key" json:"uuid"`
|
||||
State int `json:"state"` //
|
||||
Type int `json:"type"` //defult 1
|
||||
Type int `json:"type"` //defult 0
|
||||
Name string `json:"name"` //file name
|
||||
Size int64 `json:"size"` //file size
|
||||
BlockSize int `json:"block_size"` //Size of each file block
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
package model
|
||||
|
||||
type FriendModel struct {
|
||||
State int `json:"state"` //Reserved
|
||||
State int `json:"state"`
|
||||
CreatedAt int64 `gorm:"autoCreateTime" json:"created_at"`
|
||||
UpdatedAt int64 `gorm:"autoCreateTime;autoUpdateTime" json:"updated_at"`
|
||||
NickName string `json:"nick_name"`
|
||||
@@ -12,6 +12,8 @@ type FriendModel struct {
|
||||
Profile string `json:"profile"` //Description
|
||||
OnLine bool `json:"on_line" gorm:"-"`
|
||||
Version int `json:"version"`
|
||||
Write bool `json:"write"`
|
||||
LocalIP string `json:"local_ip"`
|
||||
}
|
||||
|
||||
func (p *FriendModel) TableName() string {
|
||||
|
||||
@@ -2,14 +2,23 @@ package service
|
||||
|
||||
import (
|
||||
json2 "encoding/json"
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
model2 "github.com/IceWhaleTech/CasaOS/model"
|
||||
"github.com/IceWhaleTech/CasaOS/model/notify"
|
||||
"github.com/IceWhaleTech/CasaOS/service/model"
|
||||
"github.com/IceWhaleTech/CasaOS/types"
|
||||
"github.com/ambelovsky/gosf"
|
||||
socketio "github.com/googollee/go-socket.io"
|
||||
"github.com/gorilla/websocket"
|
||||
"github.com/shirou/gopsutil/v3/mem"
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
|
||||
var NotifyMsg chan notify.Message
|
||||
var ClientCount int = 0
|
||||
|
||||
type NotifyServer interface {
|
||||
GetLog(id string) model.AppNotify
|
||||
AddLog(log model.AppNotify)
|
||||
@@ -18,13 +27,336 @@ type NotifyServer interface {
|
||||
DelLog(id string)
|
||||
GetList(c int) (list []model.AppNotify)
|
||||
MarkRead(id string, state int)
|
||||
SendText(m model.AppNotify)
|
||||
// SendText(m model.AppNotify)
|
||||
SendUninstallAppBySocket(app notify.Application)
|
||||
SendNetInfoBySocket(netList []model2.IOCountersStat)
|
||||
SendCPUInfoBySocket(cpu map[string]interface{})
|
||||
SendMemInfoBySocket(mem *mem.VirtualMemoryStat)
|
||||
SendUSBInfoBySocket(list []model2.DriveUSB)
|
||||
SendDiskInfoBySocket(disk model2.Summary)
|
||||
SendPersonStatusBySocket(status notify.Person)
|
||||
SendFileOperateNotify(nowSend bool)
|
||||
SendInstallAppBySocket(app notify.Application)
|
||||
SendAllHardwareStatusBySocket(disk model2.Summary, list []model2.DriveUSB, mem map[string]interface{}, cpu map[string]interface{}, netList []model2.IOCountersStat)
|
||||
}
|
||||
|
||||
type notifyServer struct {
|
||||
db *gorm.DB
|
||||
}
|
||||
|
||||
func (i *notifyServer) SendAllHardwareStatusBySocket(disk model2.Summary, list []model2.DriveUSB, mem map[string]interface{}, cpu map[string]interface{}, netList []model2.IOCountersStat) {
|
||||
|
||||
body := make(map[string]interface{})
|
||||
body["sys_disk"] = disk
|
||||
|
||||
body["sys_usb"] = list
|
||||
|
||||
body["sys_mem"] = mem
|
||||
|
||||
body["sys_cpu"] = cpu
|
||||
|
||||
body["sys_net"] = netList
|
||||
|
||||
msg := gosf.Message{}
|
||||
msg.Body = body
|
||||
msg.Success = true
|
||||
msg.Text = "sys_hardware_status"
|
||||
|
||||
notify := notify.Message{}
|
||||
notify.Path = "sys_hardware_status"
|
||||
notify.Msg = msg
|
||||
|
||||
NotifyMsg <- notify
|
||||
|
||||
}
|
||||
|
||||
// Send periodic broadcast messages
|
||||
func (i *notifyServer) SendFileOperateNotify(nowSend bool) {
|
||||
|
||||
if nowSend {
|
||||
|
||||
len := 0
|
||||
FileQueue.Range(func(k, v interface{}) bool {
|
||||
len++
|
||||
return true
|
||||
})
|
||||
|
||||
model := notify.NotifyModel{}
|
||||
listMsg := make(map[string]interface{})
|
||||
if len == 0 {
|
||||
model.Data = []string{}
|
||||
|
||||
listMsg["file_operate"] = model
|
||||
msg := gosf.Message{}
|
||||
msg.Success = true
|
||||
msg.Body = listMsg
|
||||
msg.Text = "file_operate"
|
||||
|
||||
notify := notify.Message{}
|
||||
notify.Path = "file_operate"
|
||||
notify.Msg = msg
|
||||
NotifyMsg <- notify
|
||||
return
|
||||
}
|
||||
|
||||
model.State = "NORMAL"
|
||||
list := []notify.File{}
|
||||
OpStrArrbak := OpStrArr
|
||||
|
||||
for _, v := range OpStrArrbak {
|
||||
tempItem, ok := FileQueue.Load(v)
|
||||
temp := tempItem.(model2.FileOperate)
|
||||
if !ok {
|
||||
continue
|
||||
}
|
||||
task := notify.File{}
|
||||
task.Id = v
|
||||
task.ProcessedSize = temp.ProcessedSize
|
||||
task.TotalSize = temp.TotalSize
|
||||
task.To = temp.To
|
||||
task.Type = temp.Type
|
||||
if task.ProcessedSize == 0 {
|
||||
task.Status = "STARTING"
|
||||
} else {
|
||||
task.Status = "PROCESSING"
|
||||
}
|
||||
|
||||
if temp.Finished || temp.ProcessedSize >= temp.TotalSize {
|
||||
|
||||
task.Finished = true
|
||||
task.Status = "FINISHED"
|
||||
FileQueue.Delete(v)
|
||||
OpStrArr = OpStrArr[1:]
|
||||
go ExecOpFile()
|
||||
list = append(list, task)
|
||||
continue
|
||||
}
|
||||
for _, v := range temp.Item {
|
||||
if v.Size != v.ProcessedSize {
|
||||
task.ProcessingPath = v.From
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
list = append(list, task)
|
||||
}
|
||||
model.Data = list
|
||||
|
||||
listMsg["file_operate"] = model
|
||||
|
||||
msg := gosf.Message{}
|
||||
msg.Success = true
|
||||
msg.Body = listMsg
|
||||
msg.Text = "file_operate"
|
||||
|
||||
notify := notify.Message{}
|
||||
notify.Path = "file_operate"
|
||||
notify.Msg = msg
|
||||
NotifyMsg <- notify
|
||||
} else {
|
||||
for {
|
||||
|
||||
len := 0
|
||||
FileQueue.Range(func(k, v interface{}) bool {
|
||||
len++
|
||||
return true
|
||||
})
|
||||
if len == 0 {
|
||||
return
|
||||
}
|
||||
listMsg := make(map[string]interface{})
|
||||
model := notify.NotifyModel{}
|
||||
model.State = "NORMAL"
|
||||
list := []notify.File{}
|
||||
OpStrArrbak := OpStrArr
|
||||
|
||||
for _, v := range OpStrArrbak {
|
||||
tempItem, ok := FileQueue.Load(v)
|
||||
temp := tempItem.(model2.FileOperate)
|
||||
if !ok {
|
||||
continue
|
||||
}
|
||||
task := notify.File{}
|
||||
task.Id = v
|
||||
task.ProcessedSize = temp.ProcessedSize
|
||||
task.TotalSize = temp.TotalSize
|
||||
task.To = temp.To
|
||||
task.Type = temp.Type
|
||||
if task.ProcessedSize == 0 {
|
||||
task.Status = "STARTING"
|
||||
} else {
|
||||
task.Status = "PROCESSING"
|
||||
}
|
||||
if temp.Finished || temp.ProcessedSize >= temp.TotalSize {
|
||||
|
||||
task.Finished = true
|
||||
task.Status = "FINISHED"
|
||||
FileQueue.Delete(v)
|
||||
OpStrArr = OpStrArr[1:]
|
||||
go ExecOpFile()
|
||||
list = append(list, task)
|
||||
continue
|
||||
}
|
||||
for _, v := range temp.Item {
|
||||
if v.Size != v.ProcessedSize {
|
||||
task.ProcessingPath = v.From
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
list = append(list, task)
|
||||
}
|
||||
model.Data = list
|
||||
|
||||
listMsg["file_operate"] = model
|
||||
|
||||
msg := gosf.Message{}
|
||||
msg.Success = true
|
||||
msg.Body = listMsg
|
||||
msg.Text = "file_operate"
|
||||
|
||||
notify := notify.Message{}
|
||||
notify.Path = "file_operate"
|
||||
notify.Msg = msg
|
||||
NotifyMsg <- notify
|
||||
time.Sleep(time.Second * 3)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
func (i *notifyServer) SendPersonStatusBySocket(status notify.Person) {
|
||||
body := make(map[string]interface{})
|
||||
body["data"] = status
|
||||
|
||||
msg := gosf.Message{}
|
||||
msg.Body = body
|
||||
msg.Success = true
|
||||
msg.Text = "person_status"
|
||||
|
||||
notify := notify.Message{}
|
||||
notify.Path = "person_status"
|
||||
notify.Msg = msg
|
||||
|
||||
NotifyMsg <- notify
|
||||
}
|
||||
|
||||
func (i *notifyServer) SendDiskInfoBySocket(disk model2.Summary) {
|
||||
body := make(map[string]interface{})
|
||||
body["data"] = disk
|
||||
|
||||
msg := gosf.Message{}
|
||||
msg.Body = body
|
||||
msg.Success = true
|
||||
msg.Text = "sys_disk"
|
||||
|
||||
notify := notify.Message{}
|
||||
notify.Path = "sys_disk"
|
||||
notify.Msg = msg
|
||||
|
||||
NotifyMsg <- notify
|
||||
}
|
||||
|
||||
func (i *notifyServer) SendUSBInfoBySocket(list []model2.DriveUSB) {
|
||||
body := make(map[string]interface{})
|
||||
body["data"] = list
|
||||
|
||||
msg := gosf.Message{}
|
||||
msg.Body = body
|
||||
msg.Success = true
|
||||
msg.Text = "sys_usb"
|
||||
|
||||
notify := notify.Message{}
|
||||
notify.Path = "sys_usb"
|
||||
notify.Msg = msg
|
||||
|
||||
NotifyMsg <- notify
|
||||
}
|
||||
|
||||
func (i *notifyServer) SendMemInfoBySocket(mem *mem.VirtualMemoryStat) {
|
||||
body := make(map[string]interface{})
|
||||
body["data"] = mem
|
||||
|
||||
msg := gosf.Message{}
|
||||
msg.Body = body
|
||||
msg.Success = true
|
||||
msg.Text = "sys_mem"
|
||||
|
||||
notify := notify.Message{}
|
||||
notify.Path = "sys_mem"
|
||||
notify.Msg = msg
|
||||
|
||||
NotifyMsg <- notify
|
||||
}
|
||||
|
||||
func (i *notifyServer) SendInstallAppBySocket(app notify.Application) {
|
||||
body := make(map[string]interface{})
|
||||
body["data"] = app
|
||||
|
||||
msg := gosf.Message{}
|
||||
msg.Body = body
|
||||
msg.Success = true
|
||||
msg.Text = "app_install"
|
||||
|
||||
notify := notify.Message{}
|
||||
notify.Path = "app_install"
|
||||
notify.Msg = msg
|
||||
|
||||
NotifyMsg <- notify
|
||||
}
|
||||
|
||||
func (i *notifyServer) SendCPUInfoBySocket(cpu map[string]interface{}) {
|
||||
body := make(map[string]interface{})
|
||||
body["data"] = cpu
|
||||
|
||||
msg := gosf.Message{}
|
||||
msg.Body = body
|
||||
msg.Success = true
|
||||
msg.Text = "sys_cpu"
|
||||
|
||||
notify := notify.Message{}
|
||||
notify.Path = "sys_cpu"
|
||||
notify.Msg = msg
|
||||
|
||||
NotifyMsg <- notify
|
||||
}
|
||||
func (i *notifyServer) SendNetInfoBySocket(netList []model2.IOCountersStat) {
|
||||
body := make(map[string]interface{})
|
||||
body["data"] = netList
|
||||
|
||||
msg := gosf.Message{}
|
||||
msg.Body = body
|
||||
msg.Success = true
|
||||
msg.Text = "sys_net"
|
||||
|
||||
notify := notify.Message{}
|
||||
notify.Path = "sys_net"
|
||||
notify.Msg = msg
|
||||
|
||||
NotifyMsg <- notify
|
||||
}
|
||||
|
||||
func (i *notifyServer) SendUninstallAppBySocket(app notify.Application) {
|
||||
body := make(map[string]interface{})
|
||||
body["data"] = app
|
||||
|
||||
msg := gosf.Message{}
|
||||
msg.Body = body
|
||||
msg.Success = true
|
||||
msg.Text = "app_uninstall"
|
||||
|
||||
notify := notify.Message{}
|
||||
notify.Path = "app_uninstall"
|
||||
notify.Msg = msg
|
||||
|
||||
NotifyMsg <- notify
|
||||
}
|
||||
|
||||
func (i *notifyServer) SSR() {
|
||||
server := socketio.NewServer(nil)
|
||||
fmt.Println(server)
|
||||
}
|
||||
|
||||
func (i notifyServer) GetList(c int) (list []model.AppNotify) {
|
||||
i.db.Where("class = ?", c).Where(i.db.Where("state = ?", types.NOTIFY_DYNAMICE).Or("state = ?", types.NOTIFY_UNREAD)).Find(&list)
|
||||
return
|
||||
@@ -103,25 +435,25 @@ func SendMeg() {
|
||||
// }
|
||||
}
|
||||
|
||||
func (i notifyServer) SendText(m model.AppNotify) {
|
||||
list := []model.AppNotify{}
|
||||
list = append(list, m)
|
||||
json, _ := json2.Marshal(list)
|
||||
var temp []*websocket.Conn
|
||||
for _, v := range WebSocketConns {
|
||||
// func (i notifyServer) SendText(m model.AppNotify) {
|
||||
// list := []model.AppNotify{}
|
||||
// list = append(list, m)
|
||||
// json, _ := json2.Marshal(list)
|
||||
// var temp []*websocket.Conn
|
||||
// for _, v := range WebSocketConns {
|
||||
|
||||
err := v.WriteMessage(1, json)
|
||||
if err == nil {
|
||||
temp = append(temp, v)
|
||||
}
|
||||
}
|
||||
WebSocketConns = temp
|
||||
// err := v.WriteMessage(1, json)
|
||||
// if err == nil {
|
||||
// temp = append(temp, v)
|
||||
// }
|
||||
// }
|
||||
// WebSocketConns = temp
|
||||
|
||||
if len(WebSocketConns) == 0 {
|
||||
SocketRun = false
|
||||
}
|
||||
// if len(WebSocketConns) == 0 {
|
||||
// SocketRun = false
|
||||
// }
|
||||
|
||||
}
|
||||
// }
|
||||
|
||||
func NewNotifyService(db *gorm.DB) NotifyServer {
|
||||
return ¬ifyServer{db: db}
|
||||
|
||||
@@ -15,8 +15,10 @@ import (
|
||||
"github.com/IceWhaleTech/CasaOS/model"
|
||||
"github.com/IceWhaleTech/CasaOS/pkg/config"
|
||||
"github.com/IceWhaleTech/CasaOS/pkg/quic_helper"
|
||||
"github.com/IceWhaleTech/CasaOS/pkg/utils"
|
||||
"github.com/IceWhaleTech/CasaOS/pkg/utils/file"
|
||||
httper2 "github.com/IceWhaleTech/CasaOS/pkg/utils/httper"
|
||||
"github.com/IceWhaleTech/CasaOS/pkg/utils/ip_helper"
|
||||
port2 "github.com/IceWhaleTech/CasaOS/pkg/utils/port"
|
||||
model2 "github.com/IceWhaleTech/CasaOS/service/model"
|
||||
"github.com/IceWhaleTech/CasaOS/types"
|
||||
@@ -26,6 +28,7 @@ import (
|
||||
|
||||
type PersonService interface {
|
||||
GetPersionInfo(token string) (m model.PersionModel, err error)
|
||||
GetPersionNetWorkTypeDetection() string
|
||||
}
|
||||
|
||||
type personService struct {
|
||||
@@ -34,11 +37,12 @@ type personService struct {
|
||||
|
||||
var IpInfo model.PersionModel
|
||||
var CancelList map[string]string
|
||||
var InternalInspection map[string][]string
|
||||
|
||||
func PushIpInfo(token string) {
|
||||
|
||||
m := model.PersionModel{}
|
||||
m.Ips = GetDeviceAllIP()
|
||||
m.Ips = ip_helper.GetDeviceAllIP("")
|
||||
m.Token = token
|
||||
b, _ := json.Marshal(m)
|
||||
|
||||
@@ -54,6 +58,16 @@ func (p *personService) GetPersionInfo(token string) (m model.PersionModel, err
|
||||
err = json.Unmarshal([]byte(infoS), &m)
|
||||
return
|
||||
}
|
||||
func (p *personService) GetPersionNetWorkTypeDetection() string {
|
||||
data := make(chan string)
|
||||
list := []string{"stun.l.google.com", "stun1.l.google.com", "stun2.l.google.com", "stun.sipgate.net"}
|
||||
for _, v := range list {
|
||||
go utils.GetNetWorkTypeDetection(data, v)
|
||||
}
|
||||
result := <-data
|
||||
close(data)
|
||||
return result
|
||||
}
|
||||
|
||||
func NewPersonService(db *gorm.DB) PersonService {
|
||||
return &personService{db: db}
|
||||
@@ -193,6 +207,11 @@ func ProcessingContent(stream quic.Stream) {
|
||||
} else {
|
||||
list = []model.Path{}
|
||||
}
|
||||
if rFriend.Write {
|
||||
for i := 0; i < len(list); i++ {
|
||||
list[i].Write = true
|
||||
}
|
||||
}
|
||||
m.To = m.From
|
||||
m.Data = list
|
||||
m.From = config.ServerInfo.Token
|
||||
@@ -200,10 +219,9 @@ func ProcessingContent(stream quic.Stream) {
|
||||
break
|
||||
} else if m.Type == types.PERSONDOWNLOAD {
|
||||
|
||||
SendFileData(stream, m.Data.(string), m.From, m.UUId)
|
||||
SendFileData(stream, m.Data.(string), m.From, m.UUId, types.PERSONDOWNLOAD)
|
||||
break
|
||||
} else if m.Type == types.PERSONADDFRIEND {
|
||||
fmt.Println("有用户来请求加好友", m)
|
||||
friend := model2.FriendModel{}
|
||||
dataModelByte, _ := json.Marshal(m.Data)
|
||||
err := json.Unmarshal(dataModelByte, &friend)
|
||||
@@ -225,6 +243,7 @@ func ProcessingContent(stream quic.Stream) {
|
||||
break
|
||||
} else if m.Type == types.PERSONCONNECTION {
|
||||
if len(m.Data.(string)) > 0 {
|
||||
fmt.Println("设置ip", m.Data.(string))
|
||||
UDPAddressMap[m.From] = m.Data.(string)
|
||||
} else {
|
||||
delete(UDPAddressMap, m.From)
|
||||
@@ -236,14 +255,18 @@ func ProcessingContent(stream quic.Stream) {
|
||||
// mi.Token = config.ServerInfo.Token
|
||||
|
||||
user := MyService.Casa().GetUserInfoByShareId(m.From)
|
||||
|
||||
//好友申请 //不是好友
|
||||
friend := model2.FriendModel{}
|
||||
friend.Token = m.From
|
||||
friend.Avatar = user.Avatar
|
||||
friend.Block = false
|
||||
friend.NickName = user.NickName
|
||||
friend.Profile = user.Avatar
|
||||
friend.Write = false
|
||||
friend.Version = user.Version
|
||||
if len(config.UserInfo.Public) > 0 {
|
||||
friend.State = types.FRIENDSTATEREQUEST
|
||||
}
|
||||
MyService.Friend().AddFriend(friend)
|
||||
|
||||
msg := model.MessageModel{}
|
||||
@@ -254,10 +277,96 @@ func ProcessingContent(stream quic.Stream) {
|
||||
msg.UUId = m.UUId
|
||||
Dial(msg, false)
|
||||
|
||||
//agree user
|
||||
if len(config.UserInfo.Public) == 0 {
|
||||
msg.Type = types.PERSONAGREEFRIEND
|
||||
msg.Data = ""
|
||||
msg.To = m.From
|
||||
msg.From = config.ServerInfo.Token
|
||||
msg.UUId = m.UUId
|
||||
Dial(msg, true)
|
||||
}
|
||||
break
|
||||
} else if m.Type == types.PERSONAGREEFRIEND {
|
||||
MyService.Friend().AgreeFrined(m.From)
|
||||
break
|
||||
} else if m.Type == types.PERSONCANCEL {
|
||||
CancelList[m.UUId] = "cancel"
|
||||
break
|
||||
} else if m.Type == types.PERSONSUMMARY {
|
||||
Summary(m, "upload")
|
||||
continue
|
||||
} else if m.Type == types.PERSONUPLOAD {
|
||||
//TODO:检查是否存在如果存在直接结束
|
||||
task := model2.PersonDownloadDBModel{}
|
||||
task.UUID = m.UUId
|
||||
task.LocalPath = m.Data.(string)
|
||||
MyService.Download().AddDownloadTask(task)
|
||||
friend := MyService.Friend().GetFriendById(model2.FriendModel{Token: m.From})
|
||||
if friend.Write {
|
||||
continue
|
||||
} else {
|
||||
break
|
||||
}
|
||||
} else if m.Type == types.PERSONUPLOADDATA {
|
||||
r := SaveFile(m, stream)
|
||||
if r {
|
||||
break
|
||||
}
|
||||
continue
|
||||
} else if m.Type == types.PERSONINTERNALINSPECTION {
|
||||
fmt.Println("内网测试")
|
||||
var ips []string
|
||||
dataModelByte, _ := json.Marshal(m.Data)
|
||||
err := json.Unmarshal(dataModelByte, &ips)
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
break
|
||||
}
|
||||
|
||||
go MyService.Friend().InternalInspection(ips, m.From)
|
||||
|
||||
} else if m.Type == types.PERSONPING {
|
||||
fmt.Println("来自", m.From, "的ping", m.Data)
|
||||
msg := m
|
||||
m.To = m.From
|
||||
m.Data = config.ServerInfo.Token
|
||||
m.From = config.ServerInfo.Token
|
||||
SendData(stream, m)
|
||||
|
||||
var ips []string
|
||||
dataModelByte, _ := json.Marshal(msg.Data)
|
||||
err := json.Unmarshal(dataModelByte, &ips)
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
break
|
||||
}
|
||||
backIP := false
|
||||
if v, ok := UDPAddressMap[msg.From]; ok {
|
||||
for _, ip := range ips {
|
||||
if ip == v {
|
||||
backIP = true
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
if !backIP {
|
||||
fmt.Println("检测需要查询ip", msg.From)
|
||||
go MyService.Friend().InternalInspection(ips, msg.From)
|
||||
}
|
||||
|
||||
break
|
||||
} else if m.Type == types.PERSONIMAGETHUMBNAIL {
|
||||
m.To = m.From
|
||||
|
||||
if data, err := file.GetImage(m.Data.(string), 100, 0); err == nil {
|
||||
m.Data = data
|
||||
} else {
|
||||
m.Data = ""
|
||||
}
|
||||
m.From = config.ServerInfo.Token
|
||||
SendData(stream, m)
|
||||
break
|
||||
} else {
|
||||
//不应有不做返回的数据
|
||||
//ServiceMessage <- m
|
||||
@@ -269,7 +378,7 @@ func ProcessingContent(stream quic.Stream) {
|
||||
}
|
||||
|
||||
//文件分片发送
|
||||
func SendFileData(stream quic.Stream, filePath, to, uuid string) error {
|
||||
func SendFileData(stream quic.Stream, filePath, to, uuid, t string) error {
|
||||
summary := model.FileSummaryModel{}
|
||||
|
||||
msg := model.MessageModel{}
|
||||
@@ -341,7 +450,7 @@ func SendFileData(stream quic.Stream, filePath, to, uuid string) error {
|
||||
tran.Length = length
|
||||
|
||||
fileMsg := model.MessageModel{}
|
||||
fileMsg.Type = types.PERSONDOWNLOAD
|
||||
fileMsg.Type = t
|
||||
fileMsg.Data = tran
|
||||
fileMsg.From = config.ServerInfo.Token
|
||||
fileMsg.To = to
|
||||
@@ -356,5 +465,18 @@ func SendFileData(stream quic.Stream, filePath, to, uuid string) error {
|
||||
}
|
||||
stream.Write(data)
|
||||
}
|
||||
record := model2.PersonDownRecordDBModel{}
|
||||
record.UUID = uuid
|
||||
record.Name = f.Name()
|
||||
record.Downloader = to
|
||||
record.Path = filePath
|
||||
record.Size = fStat.Size()
|
||||
record.Type = types.PERSONFILEDOWNLOAD
|
||||
if t == types.PERSONUPLOADDATA {
|
||||
record.Type = types.PERSONFILEUPLOAD
|
||||
}
|
||||
|
||||
MyService.DownRecord().AddDownRecord(record)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -1,7 +1,16 @@
|
||||
/*
|
||||
* @Author: LinkLeong link@icewhale.com
|
||||
* @Date: 2021-09-30 18:18:14
|
||||
* @LastEditors: LinkLeong
|
||||
* @LastEditTime: 2022-06-02 18:00:57
|
||||
* @FilePath: /CasaOS/service/rely.go
|
||||
* @Description:
|
||||
* @Website: https://www.casaos.io
|
||||
* Copyright (c) 2022 by icewhale, All Rights Reserved.
|
||||
*/
|
||||
package service
|
||||
|
||||
import (
|
||||
loger2 "github.com/IceWhaleTech/CasaOS/pkg/utils/loger"
|
||||
model2 "github.com/IceWhaleTech/CasaOS/service/model"
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
@@ -14,7 +23,6 @@ type RelyService interface {
|
||||
|
||||
type relyService struct {
|
||||
db *gorm.DB
|
||||
log loger2.OLog
|
||||
}
|
||||
|
||||
func (r *relyService) Create(rely model2.RelyDBModel) {
|
||||
@@ -35,6 +43,6 @@ func (r *relyService) Delete(id string) {
|
||||
r.db.Where("custom_id = ?", id).Delete(&c)
|
||||
}
|
||||
|
||||
func NewRelyService(db *gorm.DB, log loger2.OLog) RelyService {
|
||||
return &relyService{db: db, log: log}
|
||||
func NewRelyService(db *gorm.DB) RelyService {
|
||||
return &relyService{db: db}
|
||||
}
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
package service
|
||||
|
||||
import (
|
||||
loger2 "github.com/IceWhaleTech/CasaOS/pkg/utils/loger"
|
||||
"github.com/gorilla/websocket"
|
||||
"github.com/patrickmn/go-cache"
|
||||
"gorm.io/gorm"
|
||||
@@ -12,7 +11,7 @@ var Cache *cache.Cache
|
||||
var MyService Repository
|
||||
|
||||
var WebSocketConns []*websocket.Conn
|
||||
|
||||
var NewVersionApp map[string]string
|
||||
var SocketRun bool
|
||||
|
||||
type Repository interface {
|
||||
@@ -34,29 +33,30 @@ type Repository interface {
|
||||
Person() PersonService
|
||||
Friend() FriendService
|
||||
Download() DownloadService
|
||||
DownRecord() DownRecordService
|
||||
}
|
||||
|
||||
func NewService(db *gorm.DB, log loger2.OLog) Repository {
|
||||
func NewService(db *gorm.DB) Repository {
|
||||
|
||||
return &store{
|
||||
app: NewAppService(db, log),
|
||||
ddns: NewDDNSService(db, log),
|
||||
app: NewAppService(db),
|
||||
user: NewUserService(),
|
||||
docker: NewDockerService(log),
|
||||
docker: NewDockerService(),
|
||||
//redis: NewRedisService(rp),
|
||||
zima: NewZiMaService(),
|
||||
casa: NewCasaService(),
|
||||
disk: NewDiskService(log, db),
|
||||
disk: NewDiskService(db),
|
||||
notify: NewNotifyService(db),
|
||||
shareDirectory: NewShareDirService(db, log),
|
||||
task: NewTaskService(db, log),
|
||||
rely: NewRelyService(db, log),
|
||||
system: NewSystemService(log),
|
||||
shareDirectory: NewShareDirService(db),
|
||||
task: NewTaskService(db),
|
||||
rely: NewRelyService(db),
|
||||
system: NewSystemService(),
|
||||
shortcuts: NewShortcutsService(db),
|
||||
search: NewSearchService(),
|
||||
person: NewPersonService(db),
|
||||
friend: NewFriendService(db),
|
||||
download: NewDownloadService(db),
|
||||
downrecord: NewDownRecordService(db),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -79,6 +79,11 @@ type store struct {
|
||||
person PersonService
|
||||
friend FriendService
|
||||
download DownloadService
|
||||
downrecord DownRecordService
|
||||
}
|
||||
|
||||
func (c *store) DownRecord() DownRecordService {
|
||||
return c.downrecord
|
||||
}
|
||||
|
||||
func (c *store) Download() DownloadService {
|
||||
|
||||
@@ -1,13 +1,15 @@
|
||||
package service
|
||||
|
||||
import (
|
||||
"github.com/IceWhaleTech/CasaOS/pkg/config"
|
||||
"github.com/IceWhaleTech/CasaOS/pkg/utils/command"
|
||||
loger2 "github.com/IceWhaleTech/CasaOS/pkg/utils/loger"
|
||||
"github.com/IceWhaleTech/CasaOS/service/model"
|
||||
"gorm.io/gorm"
|
||||
"os"
|
||||
"strconv"
|
||||
|
||||
"github.com/IceWhaleTech/CasaOS/pkg/config"
|
||||
"github.com/IceWhaleTech/CasaOS/pkg/utils/command"
|
||||
"github.com/IceWhaleTech/CasaOS/pkg/utils/loger"
|
||||
"github.com/IceWhaleTech/CasaOS/service/model"
|
||||
"go.uber.org/zap"
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
|
||||
type ShareDirService interface {
|
||||
@@ -21,7 +23,6 @@ type ShareDirService interface {
|
||||
|
||||
type shareDirService struct {
|
||||
db *gorm.DB
|
||||
log loger2.OLog
|
||||
}
|
||||
|
||||
func (s *shareDirService) List(desc bool) []model.ShareDirDBModel {
|
||||
@@ -305,7 +306,7 @@ func (s *shareDirService) UpConfig() {
|
||||
// /etc/samba/smb.conf
|
||||
f, err := os.OpenFile("/etc/samba/smb.conf", os.O_WRONLY|os.O_TRUNC|os.O_CREATE, 0644)
|
||||
if err != nil {
|
||||
s.log.Error("file create failed. err: " + err.Error())
|
||||
loger.Error("Failed to create file", zap.Any("err", err))
|
||||
} else {
|
||||
defer f.Close()
|
||||
f.WriteString(str)
|
||||
@@ -318,6 +319,6 @@ func (s *shareDirService) Info(id string) model.ShareDirDBModel {
|
||||
return m
|
||||
}
|
||||
|
||||
func NewShareDirService(db *gorm.DB, log loger2.OLog) ShareDirService {
|
||||
return &shareDirService{db: db, log: log}
|
||||
func NewShareDirService(db *gorm.DB) ShareDirService {
|
||||
return &shareDirService{db: db}
|
||||
}
|
||||
|
||||
@@ -1,13 +1,19 @@
|
||||
package service
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"net"
|
||||
net2 "net"
|
||||
"os"
|
||||
"strconv"
|
||||
|
||||
"github.com/IceWhaleTech/CasaOS/pkg/config"
|
||||
command2 "github.com/IceWhaleTech/CasaOS/pkg/utils/command"
|
||||
"github.com/IceWhaleTech/CasaOS/pkg/utils/file"
|
||||
"github.com/IceWhaleTech/CasaOS/pkg/utils/loger"
|
||||
"github.com/shirou/gopsutil/v3/cpu"
|
||||
"github.com/shirou/gopsutil/v3/mem"
|
||||
"github.com/shirou/gopsutil/v3/net"
|
||||
)
|
||||
|
||||
type SystemService interface {
|
||||
@@ -20,11 +26,47 @@ type SystemService interface {
|
||||
GetTimeZone() string
|
||||
UpdateUSBAutoMount(state string)
|
||||
ExecUSBAutoMountShell(state string)
|
||||
UpAppOrderFile(str string)
|
||||
GetAppOrderFile() []byte
|
||||
GetNet(physics bool) []string
|
||||
GetNetInfo() []net.IOCountersStat
|
||||
GetCpuCoreNum() int
|
||||
GetCpuPercent() float64
|
||||
GetMemInfo() *mem.VirtualMemoryStat
|
||||
}
|
||||
type systemService struct {
|
||||
log loger.OLog
|
||||
}
|
||||
|
||||
func (c *systemService) GetMemInfo() *mem.VirtualMemoryStat {
|
||||
memInfo, _ := mem.VirtualMemory()
|
||||
memInfo.UsedPercent, _ = strconv.ParseFloat(fmt.Sprintf("%.1f", memInfo.UsedPercent), 64)
|
||||
return memInfo
|
||||
}
|
||||
|
||||
func (c *systemService) GetCpuPercent() float64 {
|
||||
percent, _ := cpu.Percent(0, false)
|
||||
value, _ := strconv.ParseFloat(fmt.Sprintf("%.1f", percent[0]), 64)
|
||||
return value
|
||||
}
|
||||
|
||||
func (c *systemService) GetCpuCoreNum() int {
|
||||
count, _ := cpu.Counts(false)
|
||||
return count
|
||||
}
|
||||
|
||||
func (c *systemService) GetNetInfo() []net.IOCountersStat {
|
||||
parts, _ := net.IOCounters(true)
|
||||
return parts
|
||||
}
|
||||
func (c *systemService) GetNet(physics bool) []string {
|
||||
t := "1"
|
||||
if physics {
|
||||
t = "2"
|
||||
}
|
||||
return command2.ExecResultStrArray("source " + config.AppInfo.ProjectPath + "/shell/helper.sh ;GetNetCard " + t)
|
||||
}
|
||||
|
||||
func (s *systemService) UpdateSystemVersion(version string) {
|
||||
//command2.OnlyExec(config.AppInfo.ProjectPath + "/shell/tool.sh -r " + version)
|
||||
//s.log.Error(config.AppInfo.ProjectPath + "/shell/tool.sh -r " + version)
|
||||
@@ -62,9 +104,15 @@ func (s *systemService) UpSystemConfig(str string, widget string) {
|
||||
}
|
||||
config.Cfg.SaveTo(config.SystemConfigInfo.ConfigPath)
|
||||
}
|
||||
func (s *systemService) UpAppOrderFile(str string) {
|
||||
file.WriteToPath([]byte(str), config.AppInfo.ProjectPath+"/conf", "app_order.json")
|
||||
}
|
||||
func (s *systemService) GetAppOrderFile() []byte {
|
||||
return file.ReadFullFile(config.AppInfo.ProjectPath + "/conf/app_order.json")
|
||||
}
|
||||
func (s *systemService) UpdateUSBAutoMount(state string) {
|
||||
config.ServerInfo.USBAutoMount = state
|
||||
config.Cfg.Section("system").Key("USBAutoMount").SetValue(state)
|
||||
config.Cfg.Section("server").Key("USBAutoMount").SetValue(state)
|
||||
config.Cfg.SaveTo(config.SystemConfigInfo.ConfigPath)
|
||||
}
|
||||
func (s *systemService) UpSystemPort(port string) {
|
||||
@@ -90,12 +138,12 @@ func (s *systemService) GetCasaOSLogs(lineNumber int) string {
|
||||
|
||||
func GetDeviceAllIP() []string {
|
||||
var address []string
|
||||
addrs, err := net.InterfaceAddrs()
|
||||
addrs, err := net2.InterfaceAddrs()
|
||||
if err != nil {
|
||||
return address
|
||||
}
|
||||
for _, a := range addrs {
|
||||
if ipNet, ok := a.(*net.IPNet); ok && !ipNet.IP.IsLoopback() {
|
||||
if ipNet, ok := a.(*net2.IPNet); ok && !ipNet.IP.IsLoopback() {
|
||||
if ipNet.IP.To16() != nil {
|
||||
address = append(address, ipNet.IP.String())
|
||||
}
|
||||
@@ -103,6 +151,6 @@ func GetDeviceAllIP() []string {
|
||||
}
|
||||
return address
|
||||
}
|
||||
func NewSystemService(log loger.OLog) SystemService {
|
||||
return &systemService{log: log}
|
||||
func NewSystemService() SystemService {
|
||||
return &systemService{}
|
||||
}
|
||||
|
||||
@@ -6,7 +6,6 @@ import (
|
||||
|
||||
"github.com/IceWhaleTech/CasaOS/pkg/config"
|
||||
httper2 "github.com/IceWhaleTech/CasaOS/pkg/utils/httper"
|
||||
loger2 "github.com/IceWhaleTech/CasaOS/pkg/utils/loger"
|
||||
"github.com/IceWhaleTech/CasaOS/service/model"
|
||||
"github.com/IceWhaleTech/CasaOS/types"
|
||||
"github.com/tidwall/gjson"
|
||||
@@ -25,7 +24,6 @@ type TaskService interface {
|
||||
|
||||
type taskService struct {
|
||||
db *gorm.DB
|
||||
log loger2.OLog
|
||||
}
|
||||
|
||||
func (s *taskService) List(desc bool) []model.TaskDBModel {
|
||||
@@ -141,6 +139,6 @@ func SyncTask(db *gorm.DB) {
|
||||
}
|
||||
}(list)
|
||||
}
|
||||
func NewTaskService(db *gorm.DB, log loger2.OLog) TaskService {
|
||||
return &taskService{db: db, log: log}
|
||||
func NewTaskService(db *gorm.DB) TaskService {
|
||||
return &taskService{db: db}
|
||||
}
|
||||
|
||||
@@ -11,13 +11,17 @@ import (
|
||||
"net"
|
||||
"os"
|
||||
path2 "path"
|
||||
"reflect"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/IceWhaleTech/CasaOS/model"
|
||||
"github.com/IceWhaleTech/CasaOS/model/notify"
|
||||
"github.com/IceWhaleTech/CasaOS/pkg/config"
|
||||
"github.com/IceWhaleTech/CasaOS/pkg/quic_helper"
|
||||
"github.com/IceWhaleTech/CasaOS/pkg/utils/file"
|
||||
"github.com/IceWhaleTech/CasaOS/pkg/utils/ip_helper"
|
||||
model2 "github.com/IceWhaleTech/CasaOS/service/model"
|
||||
"github.com/IceWhaleTech/CasaOS/types"
|
||||
"github.com/lucas-clemente/quic-go"
|
||||
@@ -29,7 +33,7 @@ var PeopleMap map[string]quic.Stream
|
||||
var Message chan model.MessageModel
|
||||
var UDPAddressMap map[string]string
|
||||
|
||||
func Dial(msg model.MessageModel, server bool) (m model.MessageModel, err error) {
|
||||
func UDPSendData(msg model.MessageModel, localFilePath string) error {
|
||||
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
|
||||
defer cancel()
|
||||
Message = make(chan model.MessageModel)
|
||||
@@ -44,6 +48,65 @@ func Dial(msg model.MessageModel, server bool) (m model.MessageModel, err error)
|
||||
IP: net.IPv4zero, Port: p} //注意端口必须固定
|
||||
addr := UDPAddressMap[msg.To]
|
||||
ticket := msg.To
|
||||
dstAddr, err := net.ResolveUDPAddr("udp", addr)
|
||||
|
||||
session, err := quic.DialContext(ctx, UDPConn, dstAddr, srcAddr.String(), quic_helper.GetClientTlsConfig(ticket), quic_helper.GetQUICConfig())
|
||||
if err != nil {
|
||||
if msg.Type == types.PERSONDOWNLOAD {
|
||||
task := MyService.Download().GetDownloadById(msg.UUId)
|
||||
task.Error = err.Error()
|
||||
task.State = types.DOWNLOADERROR
|
||||
MyService.Download().SetDownloadError(task)
|
||||
}
|
||||
if config.SystemConfigInfo.Analyse != "False" {
|
||||
go MyService.Casa().PushConnectionStatus(msg.UUId, err.Error(), msg.From, msg.To, msg.Type)
|
||||
}
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
stream, err := session.OpenStreamSync(ctx)
|
||||
if err != nil {
|
||||
if msg.Type == types.PERSONDOWNLOAD {
|
||||
task := MyService.Download().GetDownloadById(msg.UUId)
|
||||
task.Error = err.Error()
|
||||
task.State = types.DOWNLOADERROR
|
||||
MyService.Download().SetDownloadError(task)
|
||||
}
|
||||
if config.SystemConfigInfo.Analyse != "False" {
|
||||
go MyService.Casa().PushConnectionStatus(msg.UUId, err.Error(), msg.From, msg.To, msg.Type)
|
||||
}
|
||||
session.CloseWithError(1, err.Error())
|
||||
return err
|
||||
}
|
||||
|
||||
SayHello(stream, msg.To)
|
||||
//TODO:发送
|
||||
SendData(stream, msg)
|
||||
SendFileData(stream, localFilePath, msg.To, msg.UUId, types.PERSONUPLOADDATA)
|
||||
|
||||
stream.Close()
|
||||
if config.SystemConfigInfo.Analyse != "False" {
|
||||
go MyService.Casa().PushConnectionStatus(msg.UUId, "OK", msg.From, msg.To, msg.Type)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func Dial(msg model.MessageModel, server bool) (m model.MessageModel, err error) {
|
||||
ctx, cancel := context.WithTimeout(context.Background(), 100*time.Second)
|
||||
defer cancel()
|
||||
Message = make(chan model.MessageModel)
|
||||
_, port, err := net.SplitHostPort(UDPConn.LocalAddr().String())
|
||||
if config.ServerInfo.UDPPort != port {
|
||||
config.ServerInfo.UDPPort = port
|
||||
config.Cfg.Section("server").Key("UDPPort").SetValue(port)
|
||||
config.Cfg.SaveTo(config.SystemConfigInfo.ConfigPath)
|
||||
}
|
||||
p, err := strconv.Atoi(port)
|
||||
srcAddr := &net.UDPAddr{
|
||||
IP: net.IPv4zero, Port: p} //注意端口必须固定
|
||||
addr := UDPAddressMap[msg.To]
|
||||
ticket := msg.To
|
||||
if server {
|
||||
addr = config.ServerInfo.Handshake + ":9527"
|
||||
ticket = "bench"
|
||||
@@ -142,44 +205,245 @@ func ReadContent(stream quic.Stream) {
|
||||
}
|
||||
m := model.MessageModel{}
|
||||
err = json.Unmarshal(messageByte, &m)
|
||||
fmt.Println("客户端", m)
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
break
|
||||
}
|
||||
|
||||
if m.Type == types.PERSONDOWNLOAD {
|
||||
r := SaveFile(m, stream)
|
||||
if r {
|
||||
break
|
||||
}
|
||||
} else if m.Type == types.PERSONSUMMARY {
|
||||
Summary(m, "download")
|
||||
} else if m.Type == types.PERSONCONNECTION {
|
||||
if len(m.Data.(string)) > 0 {
|
||||
UDPAddressMap[m.From] = m.Data.(string)
|
||||
} else {
|
||||
delete(UDPAddressMap, m.From)
|
||||
}
|
||||
// mi := model2.FriendModel{}
|
||||
// mi.Avatar = config.UserInfo.Avatar
|
||||
// mi.Profile = config.UserInfo.Description
|
||||
// mi.NickName = config.UserInfo.NickName
|
||||
// mi.Token = config.ServerInfo.Token
|
||||
msg := model.MessageModel{}
|
||||
msg.Type = types.PERSONHELLO
|
||||
msg.Data = ""
|
||||
msg.To = m.From
|
||||
msg.From = config.ServerInfo.Token
|
||||
msg.UUId = m.UUId
|
||||
go Dial(msg, false)
|
||||
Message <- m
|
||||
break
|
||||
} else if m.Type == types.PERSONGETIP {
|
||||
notify := notify.Person{}
|
||||
notify.ShareId = m.From
|
||||
if len(m.Data.(string)) == 0 {
|
||||
if _, ok := UDPAddressMap[m.From]; ok {
|
||||
notify.Type = "OFFLINE"
|
||||
go MyService.Notify().SendPersonStatusBySocket(notify)
|
||||
}
|
||||
delete(UDPAddressMap, m.From)
|
||||
Message <- m
|
||||
break
|
||||
}
|
||||
if _, ok := UDPAddressMap[m.From]; !ok {
|
||||
notify.Type = "ONLINE"
|
||||
go MyService.Notify().SendPersonStatusBySocket(notify)
|
||||
}
|
||||
UDPAddressMap[m.From] = m.Data.(string)
|
||||
if config.ServerInfo.Token != m.From && strings.Split(m.Data.(string), ":")[0] == strings.Split(UDPAddressMap[config.ServerInfo.Token], ":")[0] {
|
||||
msg := model.MessageModel{}
|
||||
msg.Type = types.PERSONINTERNALINSPECTION
|
||||
msg.Data = ip_helper.GetDeviceAllIP(config.ServerInfo.UDPPort)
|
||||
msg.To = m.From
|
||||
msg.From = config.ServerInfo.Token
|
||||
msg.UUId = m.UUId
|
||||
go Dial(msg, true)
|
||||
}
|
||||
|
||||
Message <- m
|
||||
break
|
||||
} else if m.Type == types.PERSONINTERNALINSPECTION {
|
||||
fmt.Println("接收到反验证")
|
||||
var ips []string
|
||||
dataModelByte, _ := json.Marshal(m.Data)
|
||||
err := json.Unmarshal(dataModelByte, &ips)
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
break
|
||||
}
|
||||
go MyService.Friend().InternalInspection(ips, m.From)
|
||||
Message <- m
|
||||
break
|
||||
} else {
|
||||
|
||||
Message <- m
|
||||
}
|
||||
}
|
||||
Message <- model.MessageModel{}
|
||||
}
|
||||
|
||||
func SendIPToServer() {
|
||||
msg := model.MessageModel{}
|
||||
msg.Type = types.PERSONHELLO
|
||||
msg.Data = ""
|
||||
msg.From = config.ServerInfo.Token
|
||||
msg.To = config.ServerInfo.Token
|
||||
msg.UUId = uuid.NewV4().String()
|
||||
|
||||
Dial(msg, true)
|
||||
}
|
||||
|
||||
func LoopFriend() {
|
||||
list := MyService.Friend().GetFriendList()
|
||||
msg := model.MessageModel{}
|
||||
msg.Type = types.PERSONGETIP
|
||||
msg.Data = ""
|
||||
msg.From = config.ServerInfo.Token
|
||||
msg.To = config.ServerInfo.Token
|
||||
msg.UUId = uuid.NewV4().String()
|
||||
Dial(msg, true)
|
||||
|
||||
for i := 0; i < len(list); i++ {
|
||||
if _, ok := UDPAddressMap[list[i].Token]; !ok {
|
||||
msg := model.MessageModel{}
|
||||
msg.Type = types.PERSONGETIP
|
||||
msg.Data = ""
|
||||
msg.From = config.ServerInfo.Token
|
||||
msg.To = list[i].Token
|
||||
msg.UUId = uuid.NewV4().String()
|
||||
Dial(msg, true)
|
||||
}
|
||||
|
||||
msg.Type = types.PERSONPING
|
||||
msg.Data = ""
|
||||
msg.From = config.ServerInfo.Token
|
||||
msg.To = list[i].Token
|
||||
msg.UUId = uuid.NewV4().String()
|
||||
|
||||
if v, ok := UDPAddressMap[list[i].Token]; ok {
|
||||
if ip_helper.HasLocalIP(net.ParseIP(strings.Split(v, ":")[0])) {
|
||||
msg.Data = ip_helper.GetDeviceAllIP(config.ServerInfo.UDPPort)
|
||||
}
|
||||
oldIP := UDPAddressMap[list[i].Token]
|
||||
data, err := Dial(msg, false)
|
||||
if err != nil || reflect.DeepEqual(data, model.MessageModel{}) || len(data.Data.(string)) == 0 {
|
||||
if oldIP == UDPAddressMap[list[i].Token] {
|
||||
notify := notify.Person{}
|
||||
notify.ShareId = data.From
|
||||
notify.Type = "LEAVE"
|
||||
go MyService.Notify().SendPersonStatusBySocket(notify)
|
||||
|
||||
delete(UDPAddressMap, list[i].Token)
|
||||
|
||||
msg := model.MessageModel{}
|
||||
msg.Type = types.PERSONGETIP
|
||||
msg.Data = ""
|
||||
msg.From = config.ServerInfo.Token
|
||||
msg.To = list[i].Token
|
||||
msg.UUId = uuid.NewV4().String()
|
||||
Dial(msg, true)
|
||||
}
|
||||
}
|
||||
}
|
||||
go func(shareId string) {
|
||||
user := MyService.Casa().GetUserInfoByShareId(shareId)
|
||||
m := model2.FriendModel{}
|
||||
m.Token = shareId
|
||||
friend := MyService.Friend().GetFriendById(m)
|
||||
if friend.Version != user.Version {
|
||||
friend.Avatar = user.Avatar
|
||||
friend.NickName = user.NickName
|
||||
friend.Profile = user.Desc
|
||||
friend.Version = user.Version
|
||||
MyService.Friend().UpdateOrCreate(friend)
|
||||
}
|
||||
}(list[i].Token)
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
//file summary
|
||||
func Summary(m model.MessageModel, t string) {
|
||||
dataModel := model.FileSummaryModel{}
|
||||
dataModelByte, _ := json.Marshal(m.Data)
|
||||
err := json.Unmarshal(dataModelByte, &dataModel)
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
}
|
||||
|
||||
task := MyService.Download().GetDownloadById(m.UUId)
|
||||
|
||||
task.State = types.DOWNLOADING
|
||||
fullPath := path2.Join(task.LocalPath, task.Name)
|
||||
|
||||
if len(dataModel.Message) > 0 {
|
||||
task.State = types.DOWNLOADERROR
|
||||
task.Error = dataModel.Message
|
||||
}
|
||||
//The file already exists and the file is the same, no need to download
|
||||
if t != "upload" && file.Exists(fullPath) && file.GetHashByPath(fullPath) == dataModel.Hash {
|
||||
task.State = types.DOWNLOADFINISHED
|
||||
go func(from, uuid string) {
|
||||
m := model.MessageModel{}
|
||||
m.Data = ""
|
||||
m.From = config.ServerInfo.Token
|
||||
m.To = from
|
||||
m.Type = types.PERSONCANCEL
|
||||
m.UUId = uuid
|
||||
CancelList[uuid] = uuid
|
||||
Dial(m, false)
|
||||
}(task.From, task.UUID)
|
||||
|
||||
}
|
||||
task.UUID = m.UUId
|
||||
task.Name = dataModel.Name
|
||||
task.Length = dataModel.Length
|
||||
task.Size = dataModel.Size
|
||||
task.BlockSize = dataModel.BlockSize
|
||||
task.Hash = dataModel.Hash
|
||||
task.Type = types.PERSONFILEDOWNLOAD
|
||||
task.From = m.From
|
||||
if t == "upload" {
|
||||
task.Type = types.PERSONFILERECEIVEUPLOAD
|
||||
}
|
||||
MyService.Download().SaveDownload(task)
|
||||
}
|
||||
|
||||
//Save file fragment
|
||||
func SaveFile(m model.MessageModel, stream quic.Stream) bool {
|
||||
dataModelByte, _ := json.Marshal(m.Data)
|
||||
dataModel := model.TranFileModel{}
|
||||
err := json.Unmarshal(dataModelByte, &dataModel)
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
continue
|
||||
return false
|
||||
}
|
||||
|
||||
dataLengthByte := make([]byte, 8)
|
||||
_, err = io.ReadFull(stream, dataLengthByte)
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
continue
|
||||
return false
|
||||
}
|
||||
dataLength, err := strconv.Atoi(string(dataLengthByte))
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
continue
|
||||
return false
|
||||
}
|
||||
dataByte := make([]byte, dataLength)
|
||||
_, err = io.ReadFull(stream, dataByte)
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
continue
|
||||
return false
|
||||
}
|
||||
sum := md5.Sum(dataByte)
|
||||
hash := hex.EncodeToString(sum[:])
|
||||
if dataModel.Hash != hash {
|
||||
fmt.Println("hash不匹配", hash, dataModel.Hash)
|
||||
continue
|
||||
return false
|
||||
}
|
||||
tempPath := config.AppInfo.RootPath + "/temp" + "/" + m.UUId
|
||||
file.IsNotExistMkDir(tempPath)
|
||||
@@ -213,7 +477,7 @@ func ReadContent(stream quic.Stream) {
|
||||
files, err := ioutil.ReadDir(tempPath)
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
continue
|
||||
return false
|
||||
}
|
||||
if len(files) >= dataModel.Length {
|
||||
summary := MyService.Download().GetDownloadById(m.UUId)
|
||||
@@ -233,138 +497,7 @@ func ReadContent(stream quic.Stream) {
|
||||
MyService.Download().SetDownloadError(summary)
|
||||
}
|
||||
|
||||
break
|
||||
}
|
||||
} else if m.Type == types.PERSONSUMMARY {
|
||||
|
||||
dataModel := model.FileSummaryModel{}
|
||||
dataModelByte, _ := json.Marshal(m.Data)
|
||||
err := json.Unmarshal(dataModelByte, &dataModel)
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
}
|
||||
|
||||
task := MyService.Download().GetDownloadById(m.UUId)
|
||||
fullPath := path2.Join(task.LocalPath, task.Name)
|
||||
task.State = types.DOWNLOADING
|
||||
if len(dataModel.Message) > 0 {
|
||||
task.State = types.DOWNLOADERROR
|
||||
task.Error = dataModel.Message
|
||||
}
|
||||
if file.Exists(fullPath) && file.GetHashByPath(fullPath) == dataModel.Hash {
|
||||
task.State = types.DOWNLOADFINISHED
|
||||
go func(from, uuid string) {
|
||||
m := model.MessageModel{}
|
||||
m.Data = ""
|
||||
m.From = config.ServerInfo.Token
|
||||
m.To = from
|
||||
m.Type = types.PERSONCANCEL
|
||||
m.UUId = uuid
|
||||
CancelList[uuid] = uuid
|
||||
Dial(m, false)
|
||||
}(task.From, task.UUID)
|
||||
|
||||
}
|
||||
task.UUID = m.UUId
|
||||
task.Name = dataModel.Name
|
||||
task.Length = dataModel.Length
|
||||
task.Size = dataModel.Size
|
||||
task.BlockSize = dataModel.BlockSize
|
||||
task.Hash = dataModel.Hash
|
||||
task.Type = 0
|
||||
task.From = m.From
|
||||
MyService.Download().SaveDownload(task)
|
||||
|
||||
} else if m.Type == types.PERSONCONNECTION {
|
||||
if len(m.Data.(string)) > 0 {
|
||||
UDPAddressMap[m.From] = m.Data.(string)
|
||||
} else {
|
||||
delete(UDPAddressMap, m.From)
|
||||
}
|
||||
// mi := model2.FriendModel{}
|
||||
// mi.Avatar = config.UserInfo.Avatar
|
||||
// mi.Profile = config.UserInfo.Description
|
||||
// mi.NickName = config.UserInfo.NickName
|
||||
// mi.Token = config.ServerInfo.Token
|
||||
msg := model.MessageModel{}
|
||||
msg.Type = types.PERSONHELLO
|
||||
msg.Data = ""
|
||||
msg.To = m.From
|
||||
msg.From = config.ServerInfo.Token
|
||||
msg.UUId = m.UUId
|
||||
go Dial(msg, false)
|
||||
Message <- m
|
||||
break
|
||||
} else if m.Type == "get_ip" {
|
||||
notify := model2.AppNotify{}
|
||||
notify.CustomId = m.From
|
||||
if len(m.Data.(string)) == 0 {
|
||||
if _, ok := UDPAddressMap[m.From]; ok {
|
||||
notify.Type = types.NOTIFY_TYPE_PERSION_FIRNED_LEAVE
|
||||
go MyService.Notify().SendText(notify)
|
||||
}
|
||||
delete(UDPAddressMap, m.From)
|
||||
Message <- m
|
||||
break
|
||||
}
|
||||
if _, ok := UDPAddressMap[m.From]; !ok {
|
||||
notify.Type = types.NOTIFY_TYPE_PERSION_FIRNED_LIVE
|
||||
go MyService.Notify().SendText(notify)
|
||||
}
|
||||
UDPAddressMap[m.From] = m.Data.(string)
|
||||
Message <- m
|
||||
break
|
||||
} else {
|
||||
Message <- m
|
||||
}
|
||||
}
|
||||
Message <- model.MessageModel{}
|
||||
}
|
||||
|
||||
func SendIPToServer() {
|
||||
msg := model.MessageModel{}
|
||||
msg.Type = types.PERSONHELLO
|
||||
msg.Data = ""
|
||||
msg.From = config.ServerInfo.Token
|
||||
msg.To = config.ServerInfo.Token
|
||||
msg.UUId = uuid.NewV4().String()
|
||||
|
||||
Dial(msg, true)
|
||||
}
|
||||
|
||||
func LoopFriend() {
|
||||
list := MyService.Friend().GetFriendList()
|
||||
for i := 0; i < len(list); i++ {
|
||||
msg := model.MessageModel{}
|
||||
msg.Type = "get_ip"
|
||||
msg.Data = ""
|
||||
msg.From = config.ServerInfo.Token
|
||||
msg.To = list[i].Token
|
||||
msg.UUId = uuid.NewV4().String()
|
||||
|
||||
Dial(msg, true)
|
||||
|
||||
msg.Type = types.PERSONHELLO
|
||||
msg.Data = ""
|
||||
msg.From = config.ServerInfo.Token
|
||||
msg.To = list[i].Token
|
||||
msg.UUId = uuid.NewV4().String()
|
||||
if _, ok := UDPAddressMap[list[i].Token]; ok {
|
||||
go Dial(msg, false)
|
||||
}
|
||||
go func(shareId string) {
|
||||
user := MyService.Casa().GetUserInfoByShareId(shareId)
|
||||
m := model2.FriendModel{}
|
||||
m.Token = shareId
|
||||
friend := MyService.Friend().GetFriendById(m)
|
||||
if friend.Version != user.Version {
|
||||
friend.Avatar = user.Avatar
|
||||
friend.NickName = user.NickName
|
||||
friend.Profile = user.Desc
|
||||
friend.Version = user.Version
|
||||
MyService.Friend().UpdateOrCreate(friend)
|
||||
}
|
||||
}(list[i].Token)
|
||||
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
@@ -9,7 +9,6 @@ import (
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
"unsafe"
|
||||
|
||||
"github.com/IceWhaleTech/CasaOS/model"
|
||||
"github.com/IceWhaleTech/CasaOS/pkg/config"
|
||||
@@ -19,18 +18,12 @@ import (
|
||||
"github.com/shirou/gopsutil/v3/cpu"
|
||||
"github.com/shirou/gopsutil/v3/disk"
|
||||
"github.com/shirou/gopsutil/v3/host"
|
||||
"github.com/shirou/gopsutil/v3/mem"
|
||||
"github.com/shirou/gopsutil/v3/net"
|
||||
)
|
||||
|
||||
//系统信息
|
||||
type ZiMaService interface {
|
||||
GetCpuPercent() float64
|
||||
GetCpuCoreNum() int
|
||||
GetMemInfo() *mem.VirtualMemoryStat
|
||||
GetDiskInfo() *disk.UsageStat
|
||||
GetNetInfo() []net.IOCountersStat
|
||||
GetNet(physics bool) []string
|
||||
|
||||
GetNetState(name string) string
|
||||
GetSysInfo() host.InfoStat
|
||||
GetDirPath(path string) []model.Path
|
||||
@@ -39,6 +32,7 @@ type ZiMaService interface {
|
||||
CreateFile(path string) (int, error)
|
||||
RenameFile(oldF, newF string) (int, error)
|
||||
GetCpuInfo() []cpu.InfoStat
|
||||
GetDeviceTree() string
|
||||
}
|
||||
|
||||
var NetArray [][]model.IOCountersStat
|
||||
@@ -46,32 +40,12 @@ var NetArray [][]model.IOCountersStat
|
||||
type zima struct {
|
||||
}
|
||||
|
||||
//获取cpu占用率
|
||||
func (c *zima) GetCpuPercent() float64 {
|
||||
percent, _ := cpu.Percent(0, false)
|
||||
value, _ := strconv.ParseFloat(fmt.Sprintf("%.1f", percent[0]), 64)
|
||||
return value
|
||||
}
|
||||
|
||||
//获取物理核心数
|
||||
func (c *zima) GetCpuCoreNum() int {
|
||||
count, _ := cpu.Counts(false)
|
||||
return count
|
||||
}
|
||||
|
||||
//cpu详情
|
||||
func (c *zima) GetCpuInfo() []cpu.InfoStat {
|
||||
info, _ := cpu.Info()
|
||||
return info
|
||||
}
|
||||
|
||||
//获取内存详情
|
||||
func (c *zima) GetMemInfo() *mem.VirtualMemoryStat {
|
||||
memInfo, _ := mem.VirtualMemory()
|
||||
memInfo.UsedPercent, _ = strconv.ParseFloat(fmt.Sprintf("%.1f", memInfo.UsedPercent), 64)
|
||||
return memInfo
|
||||
}
|
||||
|
||||
//获取硬盘详情
|
||||
func (c *zima) GetDiskInfo() *disk.UsageStat {
|
||||
path := "/"
|
||||
@@ -86,6 +60,16 @@ func (c *zima) GetDiskInfo() *disk.UsageStat {
|
||||
|
||||
//获取硬盘目录
|
||||
func (c *zima) GetDirPath(path string) []model.Path {
|
||||
if path == "/DATA" {
|
||||
sysType := runtime.GOOS
|
||||
if sysType == "windows" {
|
||||
path = "C:\\CasaOS\\DATA"
|
||||
}
|
||||
if sysType == "darwin" {
|
||||
path = "./CasaOS/DATA"
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
ls, _ := ioutil.ReadDir(path)
|
||||
dirs := []model.Path{}
|
||||
@@ -130,13 +114,8 @@ func (c *zima) GetSysInfo() host.InfoStat {
|
||||
return *info
|
||||
}
|
||||
|
||||
//shell脚本参数 {1:虚拟网卡 2:物理网卡}
|
||||
func (c *zima) GetNet(physics bool) []string {
|
||||
t := "1"
|
||||
if physics {
|
||||
t = "2"
|
||||
}
|
||||
return command2.ExecResultStrArray("source " + config.AppInfo.ProjectPath + "/shell/helper.sh ;GetNetCard " + t)
|
||||
func (c *zima) GetDeviceTree() string {
|
||||
return command2.ExecResultStr("source " + config.AppInfo.ProjectPath + "/shell/helper.sh ;GetDeviceTree")
|
||||
}
|
||||
|
||||
//shell脚本参数 { 网卡名称 }
|
||||
@@ -144,13 +123,6 @@ func (c *zima) GetNetState(name string) string {
|
||||
return command2.ExecResultStr("source " + config.AppInfo.ProjectPath + "/shell/helper.sh ;CatNetCardState " + name)
|
||||
}
|
||||
|
||||
//网络信息
|
||||
func (c *zima) GetNetInfo() []net.IOCountersStat {
|
||||
parts, _ := net.IOCounters(true)
|
||||
//fmt.Println(net.ConntrackStatsWithContext(true))
|
||||
return parts
|
||||
}
|
||||
|
||||
//mkdir
|
||||
func (c *zima) MkdirAll(path string) (int, error) {
|
||||
_, err := os.Stat(path)
|
||||
@@ -204,40 +176,40 @@ func NewZiMaService() ZiMaService {
|
||||
return &zima{}
|
||||
}
|
||||
|
||||
func LoopNet() {
|
||||
netList := MyService.ZiMa().GetNetInfo()
|
||||
// func LoopNet() {
|
||||
// netList := MyService.ZiMa().GetNetInfo()
|
||||
|
||||
nets := MyService.ZiMa().GetNet(true)
|
||||
num := 0
|
||||
for i := 0; i < len(netList); i++ {
|
||||
// nets := MyService.ZiMa().GetNet(true)
|
||||
// num := 0
|
||||
// for i := 0; i < len(netList); i++ {
|
||||
|
||||
for _, netCardName := range nets {
|
||||
// for _, netCardName := range nets {
|
||||
|
||||
if netList[i].Name == netCardName {
|
||||
var netArray []model.IOCountersStat
|
||||
if len(NetArray) < (num + 1) {
|
||||
netArray = []model.IOCountersStat{}
|
||||
} else {
|
||||
netArray = NetArray[num]
|
||||
}
|
||||
item := *(*model.IOCountersStat)(unsafe.Pointer(&netList[i]))
|
||||
item.State = strings.TrimSpace(MyService.ZiMa().GetNetState(netList[i].Name))
|
||||
item.Time = time.Now().Unix()
|
||||
// if netList[i].Name == netCardName {
|
||||
// var netArray []model.IOCountersStat
|
||||
// if len(NetArray) < (num + 1) {
|
||||
// netArray = []model.IOCountersStat{}
|
||||
// } else {
|
||||
// netArray = NetArray[num]
|
||||
// }
|
||||
// item := *(*model.IOCountersStat)(unsafe.Pointer(&netList[i]))
|
||||
// item.State = strings.TrimSpace(MyService.ZiMa().GetNetState(netList[i].Name))
|
||||
// item.Time = time.Now().Unix()
|
||||
|
||||
if len(netArray) >= 60 {
|
||||
netArray = netArray[1:]
|
||||
}
|
||||
netArray = append(netArray, item)
|
||||
if len(NetArray) < (num + 1) {
|
||||
NetArray = append(NetArray, []model.IOCountersStat{})
|
||||
}
|
||||
// if len(netArray) >= 60 {
|
||||
// netArray = netArray[1:]
|
||||
// }
|
||||
// netArray = append(netArray, item)
|
||||
// if len(NetArray) < (num + 1) {
|
||||
// NetArray = append(NetArray, []model.IOCountersStat{})
|
||||
// }
|
||||
|
||||
NetArray[num] = netArray
|
||||
// NetArray[num] = netArray
|
||||
|
||||
num++
|
||||
break
|
||||
}
|
||||
}
|
||||
// num++
|
||||
// break
|
||||
// }
|
||||
// }
|
||||
|
||||
}
|
||||
}
|
||||
// }
|
||||
// }
|
||||
|
||||
@@ -32,7 +32,7 @@ GetNetCard() {
|
||||
|
||||
|
||||
GetTimeZone(){
|
||||
timedatectl | grep "Time zone" | awk '{print $3}'
|
||||
timedatectl | grep "Time zone" | awk '{printf $3}'
|
||||
}
|
||||
|
||||
#查看网卡状态
|
||||
@@ -342,3 +342,7 @@ USB_Remove_File() {
|
||||
$sudo_cmd rm -fr /etc/udev/rules.d/11-usb-mount.rules
|
||||
$sudo_cmd rm -fr /etc/systemd/system/usb-mount@.service
|
||||
}
|
||||
|
||||
GetDeviceTree(){
|
||||
cat /proc/device-tree/model
|
||||
}
|
||||
|
||||
@@ -1 +0,0 @@
|
||||
package types
|
||||
7
types/friend.go
Normal file
@@ -0,0 +1,7 @@
|
||||
package types
|
||||
|
||||
const (
|
||||
FRIENDSTATEDEFAULT = iota
|
||||
FRIENDSTATEWAIT
|
||||
FRIENDSTATEREQUEST
|
||||
)
|
||||
@@ -12,6 +12,7 @@ const (
|
||||
NOTIFY_TYPE_INSTALL_LOG
|
||||
NOTIFY_TYPE_PERSION_FIRNED_LEAVE
|
||||
NOTIFY_TYPE_PERSION_FIRNED_LIVE
|
||||
NOTIFY_TYPE_HEALTH_CHECK
|
||||
)
|
||||
|
||||
const (
|
||||
|
||||
@@ -1,9 +1,24 @@
|
||||
package types
|
||||
|
||||
const PERSONADDFRIEND = "add_user"
|
||||
const PERSONAGREEFRIEND = "agree_user"
|
||||
const PERSONDOWNLOAD = "file_data"
|
||||
const PERSONSUMMARY = "summary"
|
||||
const PERSONGETIP = "get_ip"
|
||||
const PERSONCONNECTION = "connection"
|
||||
const PERSONDIRECTORY = "directory"
|
||||
const PERSONHELLO = "hello"
|
||||
const PERSONSHAREID = "share_id"
|
||||
const PERSONUPLOAD = "upload"
|
||||
const PERSONUPLOADDATA = "upload_data"
|
||||
const PERSONINTERNALINSPECTION = "internal_inspection"
|
||||
const PERSONPING = "ping"
|
||||
const PERSONIMAGETHUMBNAIL = "image_thumbnail"
|
||||
|
||||
const PERSONCANCEL = "cancel" // Cancel Download
|
||||
|
||||
const (
|
||||
PERSONFILEDOWNLOAD = iota //default state
|
||||
PERSONFILEUPLOAD
|
||||
PERSONFILERECEIVEUPLOAD //receive upload file
|
||||
)
|
||||
|
||||
@@ -1,5 +1,15 @@
|
||||
/*
|
||||
* @Author: LinkLeong link@icewhale.com
|
||||
* @Date: 2022-02-17 18:53:22
|
||||
* @LastEditors: LinkLeong
|
||||
* @LastEditTime: 2022-06-13 19:24:15
|
||||
* @FilePath: /CasaOS/types/system.go
|
||||
* @Description:
|
||||
* @Website: https://www.casaos.io
|
||||
* Copyright (c) 2022 by icewhale, All Rights Reserved.
|
||||
*/
|
||||
package types
|
||||
|
||||
const CURRENTVERSION = "0.3.0"
|
||||
const CURRENTVERSION = "0.3.2.1"
|
||||
|
||||
const BODY = "<li>Add CasaConnect function, now you can share private files peer-to-peer with your friends.</li><li>Add a widget for network traffic monitoring</li><li>Updated the initial directory of Files to the Root directory</li><li>Fix the application ipv6 opening problem</li>"
|
||||
const BODY = ""
|
||||
|
||||
BIN
web/fonts/materialdesignicons-webfont.0fb040cb.woff2
Normal file
BIN
web/fonts/materialdesignicons-webfont.1514bb9f.ttf
Normal file
BIN
web/fonts/materialdesignicons-webfont.5a409f9f.woff
Normal file
BIN
web/fonts/materialdesignicons-webfont.ff90567b.eot
Normal file
|
Before Width: | Height: | Size: 6.7 KiB After Width: | Height: | Size: 6.7 KiB |
|
Before Width: | Height: | Size: 5.8 KiB After Width: | Height: | Size: 5.8 KiB |
@@ -1,17 +0,0 @@
|
||||
<svg width="64" height="64" version="1.1" viewBox="0 0 64 64" xmlns="http://www.w3.org/2000/svg">
|
||||
<defs>
|
||||
<linearGradient id="a" x1="49.571" x2="51.714" y1="52.714" y2="54.857" gradientTransform="matrix(2.3333,0,0,2.3333,-68.667,-72.001)" gradientUnits="userSpaceOnUse">
|
||||
<stop offset="0"/>
|
||||
<stop stop-opacity="0" offset="1"/>
|
||||
</linearGradient>
|
||||
</defs>
|
||||
<g transform="scale(1)">
|
||||
<rect x="8" y="4" width="48" height="56" ry="5" fill="#9fda1e" style="paint-order:stroke fill markers"/>
|
||||
<path d="m56 46-14 14h9c2.77 0 5-2.23 5-5z" fill="url(#a)" fill-rule="evenodd" opacity=".15" stroke-width="8.8191" style="paint-order:stroke fill markers"/>
|
||||
</g>
|
||||
<g transform="matrix(3.7796 0 0 3.7796 -89.043 4.424)" fill="#fff" opacity=".75">
|
||||
<path d="m34.671 7.0315v1.7198c0 0.07329 0.059 0.13229 0.13229 0.13229h0.79374c0.07329 0 0.13229-0.059 0.13229-0.13229v-1.7198zm0.26458 1.0583h0.52916v0.52916h-0.52916z" color="#000000"/>
|
||||
<path d="m35.2-0.11215v0.52916h0.52916v-0.52916zm0 0.52916h-0.52916v0.52916h0.52916zm0 0.52916v0.52916h0.52916v-0.52916zm0 0.52916h-0.52916v0.52916h0.52916zm0 0.52916v0.52916h0.52916v-0.52916zm0 0.52916h-0.52916v0.52916h0.52916zm0 0.52916v0.52916h0.52916v-0.52916zm0 0.52916h-0.52916v0.52916h0.52916zm0 0.52916v0.52916h0.52916v-0.52916zm0 0.52916h-0.52916v0.52916h0.52916zm0 0.52916v0.52916h0.52916v-0.52916zm0 0.52916h-0.52916v0.52916h0.52916zm0 0.52916v0.52916h0.52916v-0.52916z" color="#000000"/>
|
||||
</g>
|
||||
<path d="m32.883 44.933 2.1667-2.1667c0.33333-0.33333 0.33333-0.85 0-1.1833-0.33333-0.33333-0.85-0.33333-1.1833 0l-2.4667 2.4667c-1.3166-0.66667-2.8166-1.05-4.4-1.05-1.6 0-3.1001 0.38333-4.4332 1.05l-2.4833-2.4667c-0.33333-0.33333-0.85-0.33333-1.1833 0-0.33333 0.33333-0.33333 0.85 0 1.1833l2.1833 2.1833c-2.4667 1.8167-4.0833 4.7334-4.0833 8.05h20c0-3.3166-1.6167-6.2501-4.1168-8.0667zm-9.4547 4.4953h-1.4286v-1.4286h1.4286zm8.5713 0h-1.4286v-1.4286h1.4286z" enable-background="new" fill="#fff" opacity=".75" stroke-width="1.6667"/>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 1.9 KiB |
@@ -1,17 +0,0 @@
|
||||
<svg width="64" height="64" version="1.1" viewBox="0 0 16.933 16.933" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
|
||||
<defs>
|
||||
<linearGradient id="a" x1="49.571" x2="51.714" y1="52.714" y2="54.857" gradientTransform="matrix(2.3333 0 0 2.3333 -68.667 -72.001)" gradientUnits="userSpaceOnUse">
|
||||
<stop offset="0"/>
|
||||
<stop stop-opacity="0" offset="1"/>
|
||||
</linearGradient>
|
||||
</defs>
|
||||
<g transform="scale(.26458)">
|
||||
<rect x="8" y="4" width="48" height="56" ry="5" fill="#84c835" style="paint-order:stroke fill markers"/>
|
||||
<path d="m56 46-14 14h9c2.77 0 5-2.23 5-5z" fill="url(#a)" fill-rule="evenodd" opacity=".15" stroke-width="8.8191" style="paint-order:stroke fill markers"/>
|
||||
</g>
|
||||
<g transform="translate(-14.713 -.1522)">
|
||||
<path d="m22.651 6.7667v1.7198c0 0.073288 0.059 0.13229 0.13229 0.13229h0.79374c0.07329 0 0.13229-0.059001 0.13229-0.13229v-1.7198zm0.26458 1.0583h0.52916v0.52916h-0.52916z" color="#000000" fill="#fff"/>
|
||||
<path d="m23.18 1.2105h-0.52916v0.52916h0.52916zm0 0.52916v0.52916h0.52916v-0.52916zm0 0.52916h-0.52916v0.52916h0.52916zm0 0.52916v0.52916h0.52916v-0.52916zm0 0.52916h-0.52916v0.52916h0.52916zm0 0.52916v0.52916h0.52916v-0.52916zm0 0.52916h-0.52916v0.52916h0.52916zm0 0.52916v0.52916h0.52916v-0.52916zm0 0.52916h-0.52916v0.52916h0.52916zm0 0.52916v0.52916h0.52916v-0.52916z" color="#000000" fill="#fff"/>
|
||||
<path d="m25.359 10.922 0.80255-0.80255c0.12347-0.12347 0.12347-0.31485 0-0.43832s-0.31485-0.12347-0.43832 0l-0.91368 0.91368c-0.4877-0.24694-1.0433-0.38893-1.6298-0.38893-0.59266 0-1.1483 0.14199-1.6421 0.38893l-0.91985-0.91368c-0.12347-0.12347-0.31485-0.12347-0.43832 0s-0.12347 0.31485 0 0.43832l0.80873 0.80873c-0.91368 0.67291-1.5125 1.7533-1.5125 2.9818h7.4082c0-1.2285-0.59883-2.3151-1.5249-2.988zm-3.5021 1.6651h-0.52916v-0.52916h0.52916zm3.1749 0h-0.52916v-0.52916h0.52916z" enable-background="new" fill="#0c2809" opacity=".5" stroke-width=".61735"/>
|
||||
</g>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 1.9 KiB |
@@ -1,21 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<svg width="64" height="64" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:cc="http://creativecommons.org/ns#" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#">
|
||||
<metadata>
|
||||
<rdf:RDF>
|
||||
<cc:Work rdf:about="">
|
||||
<dc:format>image/svg+xml</dc:format>
|
||||
<dc:type rdf:resource="http://purl.org/dc/dcmitype/StillImage"/>
|
||||
<dc:title/>
|
||||
</cc:Work>
|
||||
</rdf:RDF>
|
||||
</metadata>
|
||||
<defs>
|
||||
<linearGradient id="a" x1="49.571" x2="51.714" y1="52.714" y2="54.857" gradientTransform="matrix(2.3333 0 0 2.3333 -68.667 -72.001)" gradientUnits="userSpaceOnUse">
|
||||
<stop offset="0"/>
|
||||
<stop stop-opacity="0" offset="1"/>
|
||||
</linearGradient>
|
||||
</defs>
|
||||
<rect x="8" y="4" width="48" height="56" ry="5" fill="#f55" style="paint-order:stroke fill markers"/>
|
||||
<path d="m56 46-14 14h9c2.77 0 5-2.23 5-5z" fill="url(#a)" fill-rule="evenodd" opacity=".15" stroke-width="8.8191" style="paint-order:stroke fill markers"/>
|
||||
<path d="m30.662 18.545-1.291 1.666-2.0508-0.4668-0.55664 2.0293-2.0742 0.35547 0.26367 2.0879-1.7812 1.123 1.0449 1.8281-1.2168 1.7188 1.6621 1.2891-0.46289 2.0527 2.0293 0.55469 0.35547 2.0742 0.8125-0.10352v10.404l4.5938-3.3418 4.5938 3.3418v-9.832l0.09766 0.02344 0.55664-2.0293 2.0742-0.35742-0.26562-2.0879 1.7812-1.1211-1.043-1.8301 1.2148-1.7168-1.6621-1.291 0.46484-2.0508-2.0293-0.55664-0.35547-2.0723-2.0879 0.26367-1.123-1.7812-1.8281 1.043zm1.3379 4.3066a5 5 0 0 1 5 5 5 5 0 0 1-5 5 5 5 0 0 1-5-5 5 5 0 0 1 5-5z" color="#4d4d4d" color-rendering="auto" fill="#fff" fill-rule="evenodd" image-rendering="auto" shape-rendering="auto" solid-color="#000000" style="isolation:auto;mix-blend-mode:normal"/>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 1.7 KiB |
|
Before Width: | Height: | Size: 5.9 KiB |
@@ -1,13 +0,0 @@
|
||||
<svg width="64" height="64" version="1.1" viewBox="0 0 16.933 16.933" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
|
||||
<defs>
|
||||
<linearGradient id="a" x1="49.571" x2="51.714" y1="52.714" y2="54.857" gradientTransform="matrix(2.3333 0 0 2.3333 -68.667 -72.001)" gradientUnits="userSpaceOnUse">
|
||||
<stop offset="0"/>
|
||||
<stop stop-opacity="0" offset="1"/>
|
||||
</linearGradient>
|
||||
</defs>
|
||||
<g transform="scale(.26458)">
|
||||
<rect x="8" y="4" width="48" height="56" ry="5" fill="#84c835" style="paint-order:stroke fill markers"/>
|
||||
<path d="m56 46-14 14h9c2.77 0 5-2.23 5-5z" fill="url(#a)" fill-rule="evenodd" opacity=".15" stroke-width="8.8191" style="paint-order:stroke fill markers"/>
|
||||
</g>
|
||||
<path d="m8.4664 10.961-2.4942-2.4944 2.4942-2.4941 0.83147 0.83132-1.6629 1.6627 0.83142 0.83147 2.4942-2.4941-2.1727-2.1727c-0.17742-0.17757-0.4652-0.17757-0.64277 0l-3.5142 3.5142c-0.17742 0.17742-0.17742 0.4652 0 0.64277l3.5142 3.5141c0.17757 0.17757 0.46535 0.17757 0.64277 0l3.5142-3.5141c0.17742-0.17757 0.17742-0.46535 0-0.64277l-0.51016-0.51001z" enable-background="new" fill="#fff" stroke-width=".050576"/>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 1.1 KiB |
@@ -1,13 +0,0 @@
|
||||
<svg width="64" height="64" version="1.1" viewBox="0 0 16.933 16.933" xmlns="http://www.w3.org/2000/svg">
|
||||
<defs>
|
||||
<linearGradient id="a" x1="49.571" x2="51.714" y1="52.714" y2="54.857" gradientTransform="matrix(2.3333,0,0,2.3333,-68.667,-72.001)" gradientUnits="userSpaceOnUse">
|
||||
<stop offset="0"/>
|
||||
<stop stop-opacity="0" offset="1"/>
|
||||
</linearGradient>
|
||||
</defs>
|
||||
<g transform="scale(.26458)">
|
||||
<rect x="8" y="4" width="48" height="56" ry="5" fill="#341c05" style="paint-order:stroke fill markers"/>
|
||||
<path d="m56 46-14 14h9c2.77 0 5-2.23 5-5z" fill="url(#a)" fill-rule="evenodd" opacity=".5" stroke-width="8.8191" style="paint-order:stroke fill markers"/>
|
||||
</g>
|
||||
<path class="st1" d="m6.8166 9.7034-0.3832 1.4552c-0.0097 0.03881-0.02425 0.0485-0.07276 0.0485h-0.71304c-0.04851 0-0.05821-0.01455-0.04851-0.07276l1.3776-4.8215c0.02425-0.08731 0.0388-0.16492 0.04851-0.4026 0-0.03395 0.01455-0.0485 0.0388-0.0485h1.0186c0.03395 0 0.04851 0.0097 0.05821 0.0485l1.5425 5.2338c0.0097 0.03881 0 0.06306-0.0388 0.06306h-0.8052c-0.0388 0-0.06306-0.0097-0.07276-0.04366l-0.4026-1.46zm1.3485-0.7858c-0.13582-0.53842-0.45596-1.7123-0.57722-2.2798h-0.0097c-0.10186 0.56752-0.35894 1.5279-0.56267 2.2798zm2.1828-2.6969c0-0.31044 0.21828-0.49476 0.49476-0.49476 0.29589 0 0.49476 0.19887 0.49476 0.49476 0 0.32014-0.20858 0.49476-0.50446 0.49476-0.28134 0-0.48506-0.17462-0.48506-0.49476zm0.05821 1.1011c0-0.0388 0.01455-0.05821 0.05821-0.05821h0.76154c0.0388 0 0.05821 0.01455 0.05821 0.05821v3.8271c0 0.0388-0.0097 0.05821-0.05821 0.05821h-0.75185c-0.04851 0-0.06306-0.02425-0.06306-0.06306v-3.8223z" enable-background="new" fill="#ff7c00" stroke-width=".048506"/>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 1.6 KiB |
@@ -1,22 +0,0 @@
|
||||
<svg width="64" height="64" version="1.1" viewBox="0 0 16.933 16.933" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
|
||||
<defs>
|
||||
<linearGradient id="b" x1="-666.12" x2="-553.27" y1="413.04" y2="525.91" gradientTransform="matrix(.99884 0 0 .9987 689.01 -388.84)" gradientUnits="userSpaceOnUse" xlink:href="#a"/>
|
||||
<linearGradient id="a">
|
||||
<stop stop-color="#3b3b3b" offset="0"/>
|
||||
<stop stop-color="#fff" offset="1"/>
|
||||
</linearGradient>
|
||||
<linearGradient id="c" x1="-553.27" x2="-666.12" y1="525.91" y2="413.05" gradientTransform="matrix(.99884 0 0 .9987 689.01 -388.84)" gradientUnits="userSpaceOnUse" xlink:href="#a"/>
|
||||
<linearGradient id="d" x1="49.571" x2="51.714" y1="52.714" y2="54.857" gradientTransform="matrix(2.3333,0,0,2.3333,-68.667,-72.001)" gradientUnits="userSpaceOnUse">
|
||||
<stop offset="0"/>
|
||||
<stop stop-opacity="0" offset="1"/>
|
||||
</linearGradient>
|
||||
</defs>
|
||||
<g transform="scale(.26458)">
|
||||
<rect x="8" y="4" width="48" height="56" ry="5" fill="#f4f4f4" style="paint-order:stroke fill markers"/>
|
||||
<path d="m56 46-14 14h9c2.77 0 5-2.23 5-5z" fill="url(#d)" fill-rule="evenodd" opacity=".1" stroke-width="8.8191" style="paint-order:stroke fill markers"/>
|
||||
</g>
|
||||
<g transform="matrix(.049608 0 0 .049608 4.4978 4.4978)" enable-background="new" fill-rule="evenodd">
|
||||
<path d="m79.865 119.1c35.398 48.255 70.04-13.469 69.989-50.587-0.0602-43.886-44.541-68.414-70.018-68.414-40.892 0-79.836 33.796-79.836 80.036 0 51.396 44.64 79.865 79.836 79.865-7.9645-1.1468-34.506-6.834-34.863-67.967-0.23987-41.347 13.488-57.866 34.805-50.599 0.47743 0.17707 23.514 9.2645 23.514 38.951 0 29.56-23.427 38.715-23.427 38.715z" color="#000000" fill="url(#b)"/>
|
||||
<path d="m79.823 41.401c-23.39-8.0619-52.043 11.216-52.043 49.829 0 63.048 46.721 68.77 52.384 68.77 40.892 0 79.836-33.796 79.836-80.036 0-51.396-44.64-79.865-79.836-79.865 9.7481-1.35 52.541 10.55 52.541 69.037 0 38.141-31.953 58.905-52.735 50.033-0.47743-0.17707-23.514-9.2645-23.514-38.951 0-29.56 23.367-38.818 23.367-38.818z" color="#000000" fill="url(#c)"/>
|
||||
</g>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 2.0 KiB |
@@ -1,13 +0,0 @@
|
||||
<svg width="64" height="64" version="1.1" viewBox="0 0 64 64" xmlns="http://www.w3.org/2000/svg">
|
||||
<defs>
|
||||
<linearGradient id="a" x1="49.571" x2="51.714" y1="52.714" y2="54.857" gradientTransform="matrix(2.3333,0,0,2.3333,-68.667,-72.001)" gradientUnits="userSpaceOnUse">
|
||||
<stop offset="0"/>
|
||||
<stop stop-opacity="0" offset="1"/>
|
||||
</linearGradient>
|
||||
</defs>
|
||||
<g transform="scale(1)">
|
||||
<rect x="8" y="4" width="48" height="56" ry="5" fill="#994b91" style="paint-order:stroke fill markers"/>
|
||||
<path d="m56 46-14 14h9c2.77 0 5-2.23 5-5z" fill="url(#a)" fill-rule="evenodd" opacity=".15" stroke-width="8.8191" style="paint-order:stroke fill markers"/>
|
||||
</g>
|
||||
<path d="m22 21c-0.554 0-1 0.446-1 1v20c0 0.554 0.446 1 1 1h18c0.554 0 1-0.446 1-1v-1h1c0.554 0 1-0.446 1-1v-4c0-0.186-0.064344-0.351-0.15234-0.5 0.088-0.149 0.15234-0.314 0.15234-0.5v-4c0-0.186-0.064344-0.351-0.15234-0.5 0.088-0.149 0.15234-0.314 0.15234-0.5v-4c0-0.554-0.446-1-1-1h-1v-3c0-0.554-0.446-1-1-1h-18zm1 3h7v1h-7v-1zm9 0h7v1h-7v-1zm9 2h1v4h-1v-4zm-18 1h7v1h-7v-1zm9 0h7v1h-7v-1zm-9 3h7v1h-7v-1zm9 0h7v1h-7v-1zm9 1h1v4h-1v-4zm-18 2h7v1h-7v-1zm9 0h7v1h-7v-1zm-9 3h7v1h-7v-1zm9 0h7v1h-7v-1zm9 0h1v4h-1v-4zm-18 3h7v1h-7v-1zm9 0h7v1h-7v-1z" color="#000000" color-rendering="auto" fill="#fff" image-rendering="auto" opacity=".75" shape-rendering="auto" solid-color="#000000" style="isolation:auto;mix-blend-mode:normal"/>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 1.4 KiB |
@@ -1,18 +0,0 @@
|
||||
<svg width="64" height="64" version="1.1" viewBox="0 0 64 64" xmlns="http://www.w3.org/2000/svg">
|
||||
<defs>
|
||||
<linearGradient id="a" x1="49.571" x2="51.714" y1="52.714" y2="54.857" gradientTransform="matrix(2.3333,0,0,2.3333,-68.667,-72.001)" gradientUnits="userSpaceOnUse">
|
||||
<stop offset="0"/>
|
||||
<stop stop-opacity="0" offset="1"/>
|
||||
</linearGradient>
|
||||
</defs>
|
||||
<g transform="scale(1)">
|
||||
<rect x="8" y="4" width="48" height="56" ry="5" fill="#576dab" style="paint-order:stroke fill markers"/>
|
||||
<path d="m56 46-14 14h9c2.77 0 5-2.23 5-5z" fill="url(#a)" fill-rule="evenodd" opacity=".15" stroke-width="8.8191" style="paint-order:stroke fill markers"/>
|
||||
</g>
|
||||
<g transform="translate(-52.837 -2.8601)">
|
||||
<path transform="translate(52.837 2.8601)" d="m32 17.301-13.363 10.025c-0.02875 0.0187-0.054801 0.0418-0.082031 0.0625l-0.015626 0.011719v0.001953c-0.3259 0.2559-0.53906 0.64931-0.53906 1.0977v12.199c2e-6 2 1.5771 2 2 2h24s2 0 2-2v-12.199c0-0.45851-0.22189-0.86016-0.56055-1.1152l0.005859-0.007813-13.445-10.076zm0 6.3984a5 5 0 0 1 5 5v1.5c0 0.831-0.669 1.5-1.5 1.5-0.61296 0-1.1359-0.36612-1.3691-0.89062a3 3 0 0 1-2.1309 0.89062 3 3 0 0 1-3-3 3 3 0 0 1 3-3 3 3 0 0 1 3 3v1.5c0 0.277 0.223 0.5 0.5 0.5s0.5-0.223 0.5-0.5v-1.5a4 4 0 0 0-4-4 4 4 0 0 0-4 4 4 4 0 0 0 4 4h3.5c0.277 0 0.5 0.223 0.5 0.5s-0.223 0.5-0.5 0.5h-3.5a5 5 0 0 1-5-5 5 5 0 0 1 5-5zm0 3a2 2 0 0 0-2 2 2 2 0 0 0 2 2 2 2 0 0 0 2-2 2 2 0 0 0-2-2z" enable-background="new" fill="#fff" opacity=".75"/>
|
||||
<path transform="translate(52.837 2.8601)" d="m22.5 20.699c-0.831 0-1.5 0.66967-1.5 1.5v15.002c0 0.83033 0.669 1.498 1.5 1.498h19c0.831 0 1.5-0.66772 1.5-1.498v-15.002c0-0.83033-0.669-1.5-1.5-1.5h-19zm9.5 3a5 5 0 0 1 5 5v1.5c0 0.831-0.669 1.5-1.5 1.5-0.61296 0-1.1359-0.36612-1.3691-0.89062a3 3 0 0 1-2.1309 0.89062 3 3 0 0 1-3-3 3 3 0 0 1 3-3 3 3 0 0 1 3 3v1.5c0 0.277 0.223 0.5 0.5 0.5s0.5-0.223 0.5-0.5v-1.5a4 4 0 0 0-4-4 4 4 0 0 0-4 4 4 4 0 0 0 4 4h3.5c0.277 0 0.5 0.223 0.5 0.5s-0.223 0.5-0.5 0.5h-3.5a5 5 0 0 1-5-5 5 5 0 0 1 5-5zm0 3a2 2 0 0 0-2 2 2 2 0 0 0 2 2 2 2 0 0 0 2-2 2 2 0 0 0-2-2z" enable-background="new" fill="#fff"/>
|
||||
<path d="m70.837 31.36 26.6 18.2-24.6-2e-4c-1 0-2-0.5-2-2z" enable-background="new" fill="#e8ebf0"/>
|
||||
<path d="m96.837 49.56c2-2e-5 2-2 2-2l-1e-5 -16.2-26.6 18.2z" enable-background="new" fill="#f2f2fa"/>
|
||||
</g>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 2.3 KiB |
@@ -1,16 +0,0 @@
|
||||
<svg width="64" height="64" version="1.1" viewBox="0 0 64 64" xmlns="http://www.w3.org/2000/svg">
|
||||
<defs>
|
||||
<linearGradient id="a" x1="49.571" x2="51.714" y1="52.714" y2="54.857" gradientTransform="matrix(2.3333,0,0,2.3333,-68.667,-72.001)" gradientUnits="userSpaceOnUse">
|
||||
<stop offset="0"/>
|
||||
<stop stop-opacity="0" offset="1"/>
|
||||
</linearGradient>
|
||||
</defs>
|
||||
<g transform="scale(1)">
|
||||
<rect x="8" y="4" width="48" height="56" ry="5" fill="#4747b5" style="paint-order:stroke fill markers"/>
|
||||
<path d="m56 46-14 14h9c2.77 0 5-2.23 5-5z" fill="url(#a)" fill-rule="evenodd" opacity=".15" stroke-width="8.8191" style="paint-order:stroke fill markers"/>
|
||||
</g>
|
||||
<g transform="matrix(3.7796 0 0 3.7796 -75.6 4.949)" fill="#fff" stroke-width=".088193">
|
||||
<path d="m28.768 3.453c-1.2902 0.22976-2.5811 0.53461-3.8713 0.76016 0 1.9626-8.5e-4 3.9261 0 5.8896 1.2835 0.22471 2.5677 0.52447 3.8486 0.75844h0.38441v-7.4082zm-0.49905 2.3996-0.5944 2.4951-0.48788-0.03847c-0.11193-0.55714-0.24233-1.1109-0.34248-1.6706-0.09847 0.54368-0.2265 1.0823-0.33928 1.6226-0.16159-0.0084-0.32392-0.01852-0.48635-0.02946-0.13971-0.74062-0.30388-1.4762-0.43432-2.2185 0.14392-0.0067 0.28868-0.01258 0.4326-0.01763 0.08668 0.53611 0.18512 1.0697 0.26087 1.6066 0.11867-0.55041 0.23994-1.1008 0.35777-1.6512 0.15991-0.0093 0.31979-0.01599 0.47969-0.02441 0.11193 0.56809 0.22634 1.1352 0.34753 1.7008 0.0951-0.58408 0.20033-1.1664 0.30217-1.7496 0.16832-0.0059 0.33662-0.01517 0.5041-0.02527z" enable-background="new"/>
|
||||
<path d="m29.395 4.5113h2.6458v5.2916h-2.6458v-0.52916h2.1166v-0.26458h-2.1166v-0.52916h2.1166v-0.26458h-2.1166v-0.52916h2.1166v-0.26458h-2.1166v-0.52916h2.1166v-0.26458h-2.1166v-0.52823h2.1166v-0.2655h-2.1166v-0.52916h2.1166v-0.26458h-2.1166z" enable-background="new"/>
|
||||
</g>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 1.7 KiB |