Skip to content

Commit

Permalink
add autostart feature for linux&win - fix clipboard on win and add ic…
Browse files Browse the repository at this point in the history
…on to .exe
  • Loading branch information
mc51 committed May 17, 2021
1 parent 5a8aa40 commit ca1867e
Show file tree
Hide file tree
Showing 10 changed files with 311 additions and 80 deletions.
6 changes: 5 additions & 1 deletion .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,8 @@ jobs:
ASSET_MIME: application/zip # application/octet-stream
- os: windows-latest
TARGET: windows
CMD_BUILD: go mod tidy && go build -o build/clipster_win.exe && cd build && powershell Compress-Archive clipster_win.exe clipster_win.zip
CMD_PRE_BUILD: go get github.com/akavel/rsrc && rsrc -ico assets/clipster_icon_64.ico
CMD_BUILD: go mod tidy && go build -ldflags -H=windowsgui -o build/clipster_win.exe && cd build && powershell Compress-Archive clipster_win.exe clipster_win.zip
OUT_FILE_NAME: clipster_win.zip
ASSET_MIME: application/zip # application/vnd.microsoft.portable-executable
steps:
Expand All @@ -75,6 +76,9 @@ jobs:
go-version: ${{ matrix.go-version }}
- name: Checkout repo
uses: actions/checkout@v2
- name: Pre build for ${{matrix.TARGET}}
run: ${{matrix.CMD_PRE_BUILD}}
if: runner.os == 'Windows'
- name: Build Go for ${{matrix.TARGET}}
run: ${{matrix.CMD_BUILD}}
- name: Post build for ${{matrix.TARGET}}
Expand Down
32 changes: 17 additions & 15 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,29 +19,29 @@ There is an alternative [Clipster-Desktop](https://github.com/mc51/Clipster-Desk
### Linux

Download [`clipster_linux.zip`](https://github.com/mc51/Clipster-Desktop/releases/latest/download/clipster_linux.zip) from the latest release, extract and start it.

Clipster depends on gtk-3.0. To install it on
Ubuntu/Debian:
To have Clipster auto start, right click on the systray menu and select `Autostart Clipster`.

Clipster depends on gtk-3.0. To install it on
Ubuntu/Debian:
`sudo apt-get install libgtk-3-0`

CentOS/RHEL:
`sudo yum install gtk3-devel`
CentOS/RHEL:
`sudo yum install gtk3-devel`

### Windows

Download [`clipster_win.zip`](https://github.com/mc51/Clipster-Desktop/releases/latest/download/clipster_win.zip) from the latest release, extract and start it. To have Clipster auto start for the current user, open the startup folder by opening Explorer and typing `shell:startup`. Copy `clipster_win.exe` there.
Download [`clipster_win.zip`](https://github.com/mc51/Clipster-Desktop/releases/latest/download/clipster_win.zip) from the latest release, extract and start it.
To have Clipster auto start, right click on the systray menu and select `Autostart Clipster`.

### MacOS (>=10.13 High Sierra)

Download [`clipster_mac.zip`](https://github.com/mc51/Clipster-Desktop/releases/latest/download/clipster_mac.zip) from the latest release, extract, move it to `Applications` and start it via right-click -> open. You might get a warning message, that you need to ignore. If that fails:
Download [`clipster_mac.zip`](https://github.com/mc51/Clipster-Desktop/releases/latest/download/clipster_mac.zip) from the latest release, extract, move it to `Applications` and start it via `right-click -> open`. You might get a warning message, that you need to ignore. If that fails:
Go to `System Preferences --> Security & Privacy`. In the `General` Tab the App will be listed and you can start it from there.

To automatically start Clipster, right click on the icon in your Dock and click on `Options --> Open at Login`.

*Notice*: M1 processors (ARM architecture) are not (yet) supported.

Now, you can [use](#usage) clipster!
To have Clipster auto start, right click on the icon in your dock and select `Options --> Open at Login`.

*Notice*: M1 processors (ARM architecture) are not (yet) supported.

## Usage

On the first startup, you can register a new account or enter your existing credentials for the login. Your credentials will be stored in your `HOMEPATH` in `./config/clipster/config.yaml`.
Expand All @@ -50,15 +50,16 @@ Clipster will add an Icon to your system tray which you can click for opening up
`Get all Clips` will fetch all shared Clips from the server and display them to you.
`Share Clip` will share your current clipboard. Then, it's available for all your devices.
`Edit Credentials` allows you to register a new account or change your login credentials.
`Quit` will terminate the app.
`Quit` will terminate the app.

## Roadmap

- [x] Encrypt / Decrypt clipboard locally and only transmit encrypted data to server
- [x] Add clipboard history: share multiple Clips
- [x] Create Go version
- [x] Add auto start feature
- [ ] Support image sharing

## Contributions

Contributions are very welcome. If you come across a bug, please open an issue. The same thing goes for feature requests.
Expand All @@ -69,4 +70,5 @@ Contributions are very welcome. If you come across a bug, please open an issue.
- [Systray](https://pkg.go.dev/github.com/getlantern/systray) for tray icon and menu
- Notifications using [beep](https://github.com/gen2brain/beeep)
- Config by [Viper](https://github.com/spf13/viper)
- Crypto using [PBKDF2](https://pkg.go.dev/golang.org/x/crypto/pbkdf2) and [Fernet](https://github.com/fernet/fernet-go)
- Crypto using [PBKDF2](https://pkg.go.dev/golang.org/x/crypto/pbkdf2) and [Fernet](https://github.com/fernet/fernet-go)
- [Clipboard](https://github.com/golang-design/clipboard)
8 changes: 4 additions & 4 deletions build/bundle/Info-clipster.plist
Original file line number Diff line number Diff line change
Expand Up @@ -7,21 +7,21 @@
<key>CFBundleExecutable</key>
<string>clipster_mac</string>
<key>CFBundleGetInfoString</key>
<string>0.1.2 (C) 2021 MC51 https://github.com/mc51</string>
<string>0.2.0 (C) 2021 MC51 https://github.com/mc51</string>
<key>CFBundleIdentifier</key>
<string>org.data-dive.com</string>
<key>CFBundleIconFile</key>
<string>clipster.icns</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>0.1.2</string>
<string>0.2.0</string>
<key>CFBundlePackageType</key>
<string>APPL</string>
<key>CFBundleShortVersionString</key>
<string>0.1.2</string>
<string>0.2.0</string>
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleVersion</key>
<string>0.1.2</string>
<string>0.2.0</string>
<key>NSHumanReadableCopyright</key>
<string>Copyright 2021 MC51, MIT License</string>
<key>LSMinimumSystemVersion</key>
Expand Down
210 changes: 210 additions & 0 deletions clipster/autostart.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,210 @@
// Deal with enabling and disabling auto start of Clipter on Desktop startup
package clipster

import (
"bytes"
"log"
"os"
"os/exec"
"path/filepath"
"runtime"
"strings"
)

type PowerShell struct {
powerShell string
}

var (
LINUX_DESKTOP_ENTRY = `[Desktop Entry]
Type=Application
Name=Clipster-Desktop
Comment=A multi Platform Cloud Clipboard - Desktop Client (Go)
Exec=PLACEHOLDER
Terminal=false
`
WIN_CREATE_SHORTCUT = `$WshShell = New-Object -comObject WScript.Shell
$Shortcut = $WshShell.CreateShortcut("$HOME\AppData\Roaming\Microsoft\Windows\Start Menu\Programs\Startup\clipster.lnk")
$Shortcut.TargetPath = "PLACEHOLDER"
$Shortcut.Save()`
)

// getAutostartDirAndFile returns the absolute path to auto startup directory and file
// for different OSes
func getAutostartDirAndFile() (string, string) {
homedir, err := os.UserHomeDir()
if err != nil {
log.Panicln("Error", err)
return "", ""
}
log.Println("Homedir is: ", homedir)

if runtime.GOOS == "linux" {
path_dir := filepath.Join(homedir, ".config", "autostart")
path_file := filepath.Join(path_dir, "clipster.desktop")
return path_dir, path_file
} else if runtime.GOOS == "windows" {
path_dir := filepath.Join(homedir,
"AppData/Roaming/Microsoft/Windows/Start Menu/Programs/Startup")
path_file := filepath.Join(path_dir, "clipster.lnk")
return path_dir, path_file
} else {
return "", ""
}
}

// isAutostartEnabled checks if an autostart file exists and returns its absolute path
func isAutostartEnabled() (bool, string) {
_, file := getAutostartDirAndFile()
if fileExists(file) {
log.Println("Ok: Autostart file exists", file)
return true, file
} else {
log.Println("Warning: No Autostart file exists", file)
return false, ""
}
}

// enableAutostartLinux checks if autostart folder exists on Linux
// if it does, creates a clipster.desktop file there for auto startup on X-Session
// pointing to current executable
func enableAutostartLinux() {
startup_dir, startup_file := getAutostartDirAndFile()
exec_path, err := os.Executable()
if err != nil {
log.Panicln("Error", err)
}
log.Println("Executable is: ", exec_path)
LINUX_DESKTOP_ENTRY = strings.Replace(LINUX_DESKTOP_ENTRY, "PLACEHOLDER",
exec_path, 1)

if fileExists(startup_dir) {
log.Println("Config file folder exists", startup_dir)
if err := os.WriteFile(startup_file,
[]byte(LINUX_DESKTOP_ENTRY), 0664); err != nil {
log.Println("Error: could not write autostart file", err)
} else {
log.Println("Ok: written autostart file", startup_file)
ShowNotification("Clipster", "Added Clipster to autostart by creating "+
startup_file+"\nWhich points to "+exec_path)
}
} else {
// Probabily no supported session manager
log.Println("Error: No autostart folder exists")
ShowNotification("Clipster", "Could not add Clipster to autostart. Folder "+
startup_dir+" does not exist.")
}
}

// enableAutostartWin creates a shortcut to clipster in the shell:startup folder
func enableAutostartWin() {
_, startup_file := getAutostartDirAndFile()
ps := New()
exec_path, err := os.Executable()
if err != nil {
log.Panicln("Error", err)
}
log.Println("Executable is: ", exec_path)
WIN_CREATE_SHORTCUT = strings.Replace(WIN_CREATE_SHORTCUT, "PLACEHOLDER", exec_path, 1)
_, _, err = ps.execute(WIN_CREATE_SHORTCUT)
if err != nil {
log.Println("Error: could not create shortcut in startup folder", err)
} else {
log.Println("Ok: shortcut created")
ShowNotification("Clipster", "Added Clipster to autostart by creating "+
startup_file+"\nWhich points to "+exec_path)
}
}

// disableAutostartLinux removes autostart file and show status in Notification
func disableAutostartLinux() {
if ok, file := isAutostartEnabled(); ok {
if err := os.Remove(file); err != nil {
log.Println("Error: could not remove autostart file", file)
ShowNotification("Clipster", "Could not remove autostart file "+
file+"\n"+err.Error())
} else {
log.Println("Ok: removed autostart file " + file)
ShowNotification("Clipster", "Removed autostart file "+file)
}
}
}

// disableAutostartWin removes autostart file and show status in Notification
func disableAutostartWin() {
if ok, file := isAutostartEnabled(); ok {
if err := os.Remove(file); err != nil {
log.Println("Error: could not remove autostart file", file)
ShowNotification("Clipster", "Could not remove autostart file "+
file+"\n"+err.Error())
} else {
log.Println("Ok: removed autostart file " + file)
ShowNotification("Clipster", "Removed autostart file "+file)
}
}
}

// enableAutostart deals with autostart of Clipster on different OSes
func enableAutostart() {
if runtime.GOOS == "linux" {
enableAutostartLinux()
} else if runtime.GOOS == "darwin" {
ShowNotification("Clipster", "To autostart Clipster, right click on the dock"+
" icon and select\n`Options --> Open at Login`.")
} else if runtime.GOOS == "windows" {
enableAutostartWin()
}
}

// disableAutostart deals with disabling autostart of Clipster on different OSes
func disableAutostart() {
if runtime.GOOS == "linux" {
disableAutostartLinux()
} else if runtime.GOOS == "darwin" {
log.Println("RemoveAutostart not implemented on MacOS")
} else if runtime.GOOS == "windows" {
disableAutostartWin()
}
}

// IsAutostartEnabled checks if autostart is enabled on different OSes
func IsAutostartEnabled() bool {
if runtime.GOOS == "linux" || runtime.GOOS == "windows" {
ok, _ := isAutostartEnabled()
return ok
} else {
return false
}
}

// ToggleAutostart enable or disable autostart
func ToggleAutostart() {
if IsAutostartEnabled() {
disableAutostart()
} else {
enableAutostart()
}
}

// New create new session
func New() *PowerShell {
ps, _ := exec.LookPath("powershell.exe")
return &PowerShell{
powerShell: ps,
}
}

// execute command on powershell and return outputs
func (p *PowerShell) execute(args ...string) (stdOut string, stdErr string, err error) {
args = append([]string{"-NoProfile", "-NonInteractive", "-WindowStyle", "Hidden"}, args...)
cmd := exec.Command(p.powerShell, args...)

var stdout bytes.Buffer
var stderr bytes.Buffer
cmd.Stdout = &stdout
cmd.Stderr = &stderr

err = cmd.Run()
stdOut, stdErr = stdout.String(), stderr.String()
return
}
1 change: 1 addition & 0 deletions clipster/clipboard.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,5 +16,6 @@ func GetClipboard() string {
}

func SetClipboard(clip string) {
log.Println("Set Clipboard:", clip)
clipboard.Write(clipboard.FmtText, []byte(clip))
}
Loading

0 comments on commit ca1867e

Please sign in to comment.