Skip to content

Commit

Permalink
v1.0.0 is here.
Browse files Browse the repository at this point in the history
  • Loading branch information
daviidwang committed Jan 18, 2024
1 parent 4465fd9 commit f4f7656
Show file tree
Hide file tree
Showing 73 changed files with 5,989 additions and 1,417 deletions.
31 changes: 31 additions & 0 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
name: build

on:
push:
tags:
- "v[0-9].[0-9]+.[0-9]+"

jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3

- name: Variables
run: |
echo "REGISTRY=registry.cn-beijing.aliyuncs.com" >> $GITHUB_ENV
echo "GIT_TAG=${GITHUB_REF#refs/tags/}" >> $GITHUB_ENV
- name: Build server image
run: |
IMAGE=${{ env.REGISTRY }}/llaoj/gcopy-server:${{ env.GIT_TAG }}
docker build -t $IMAGE -f build/server/Dockerfile .
docker login -u ${{ secrets.REGISTRY_USERNAME }} -p ${{ secrets.REGISTRY_PASSWORD }} ${{ env.REGISTRY }}
docker push $IMAGE
- name: Build frontend image
run: |
IMAGE=${{ env.REGISTRY }}/llaoj/gcopy-frontend:${{ env.GIT_TAG }}
docker build -t $IMAGE -f build/frontend/Dockerfile .
docker login -u ${{ secrets.REGISTRY_USERNAME }} -p ${{ secrets.REGISTRY_PASSWORD }} ${{ env.REGISTRY }}
docker push $IMAGE
34 changes: 0 additions & 34 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
@@ -1,35 +1 @@
# .github/workflows/release.yml
name: goreleaser

on:
push:
# run only against tags
tags:
- "*"

permissions:
contents: write
# packages: write
# issues: write

jobs:
goreleaser:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
with:
fetch-depth: 0
- run: git fetch --force --tags
- uses: actions/setup-go@v4
with:
go-version: stable
# More assembly might be required: Docker logins, GPG, etc.
# It all depends on your needs.
- run: docker login -u ${{ secrets.REGISTRY_USERNAME }} -p ${{ secrets.REGISTRY_PASSWORD }} registry.cn-beijing.aliyuncs.com
- uses: goreleaser/goreleaser-action@v5
with:
distribution: goreleaser
version: latest
args: release --clean
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
56 changes: 0 additions & 56 deletions .goreleaser.yaml

This file was deleted.

8 changes: 0 additions & 8 deletions Makefile

This file was deleted.

83 changes: 27 additions & 56 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,85 +5,56 @@

---

[中文文档](docs/intro.md)
[中文文档](docs/zh-CN/README.md)

A clipboard synchronization tool that powered by Golang.

This is a tool to synchronize clipboards between different operating systems.
A clipboard synchronization service between different operating systems.

`Text`, `Screenshot` & `File` are supported.


![](docs/gcopy-usage.gif)
GCopy values your data privacy, it does not persistently store your data; it is all kept in memory.

## Usage

GCopy has two modes, the first mode is more easy to use:

### server&client <> clients

This mode requires one device to simultaneously act as both the server and client. These devices must be on the same LAN and should be able to access each other.

If you have two device, they are in the same LAN.

On first device:

```
/path/to/gcopy --role=server,client
```

On the other devices:
![screanshot](docs/screenshot.png)

```
/path/to/gcopy --role=client --token=<output-token> --server=<server-ip>:3375
```
Steps:

![](docs/mode1.png)
1. Open the website [https://gcopy.rutron.net](https://gcopy.rutron.net) on two devices, A and B, using a browser and log in with the same email.
2. On device A, copy (e.g., `Ctrl+C`) and then click the button on the right side of the page.
3. Switch to device B, click the button again, and the data will be synchronized. Now, go ahead and paste (`Ctrl+V`)!

### clients <> server <> clients
## Background

In this mode, it is more flexible but requires a minimum of three devices, with one of them serving as the server. Clients do not need to be able to access each other, but it is required that clients can access the server.
In our daily office routines, especially for software developers, we often find ourselves working with more than two computers.

On server:
If you need to operate both a Windows PC and a MacOS device simultaneously, exchanging information between these two devices becomes quite troublesome. For various reasons, I couldn't find a good tool to share the clipboard between devices with different operating systems. When I copy a piece of text, pasting it on another computer usually proves to be quite challenging.

```
$ /path/to/gcopy --role=server
Current tools typically only support text, excluding screenshots and files. Additionally, they often require devices to be on the same local network and accessible to each other, not to mention some of them come with a fee.

__ _ ___ ___ _ __ _ _
/ _ |/ __/ _ \| '_ \| | | |
| (_| | (_| (_) | |_) | |_| |
\__, |\___\___/| .__/ \__, |
__/ | | | __/ |
|___/ |_| |___/
This is not ideal!

Therefore, I developed GCopy to address these issues. Currently, you can share the clipboard between Windows and MacOS computers, supporting text, screenshots, and files. It has low network requirements, allowing different devices to be on the same local network or not.

The Server has started, start the clients:
/path/to/gcopy --role=client --server=192.168.137.146:3375 --token=helloworld
...
```

The Clients' command will be printed in the outputs. Run them on the Clients.

![](docs/mode2.png)


## Read more

- [The work mechanism](docs/mechanism.md)
Initially, I used Git as the backend storage and utilized scripts like PowerShell and osascript to synchronize the clipboard between different devices. However, due to its dependence on Git, it was not user-friendly for non-technical users. So, I replaced Git with Golang to serve as a data transfer service between different devices, but it still required users to download and run the GCopy client on their devices, creating a barrier to entry. That led to the development of the current version, 'GCopy v1.0', as a web service. You can directly access the website [https://gcopy.rutron.net](https://gcopy.rutron.net) without worrying about data leakage.

## Limitations

- Only tested on windows 10 & macOS Monterey
- It can only synchronize one file at a time
- Due to browser limitations, reading and setting files directly in the clipboard are not supported. Therefore, file synchronization is achieved through uploading and downloading, ensuring a smooth user experience.
- At any given time, only one file can be synchronized.
- Due to limited server memory, the size of the files you synchronize must not exceed 10 MB.

## Community

You have questions, need support or just want to talk about GCopy?
Welcome to join GCopy, whether you're a user or a contributor!

If you have any questions or need support related to GCopy, you can contact me through the following channels:

### Email

Here are ways to get in touch with the community:
Feel free to reach out to my personal email: [email protected]. If you have any questions, you can drop me a message.

Email: [email protected]
### Discord

Wechat:
Here, some interesting discussions are happening.

<img width="200" src="docs/wechat-lllaoj.png">
Server link: https://discord.gg/pyTrT3aAaC
6 changes: 1 addition & 5 deletions build/Dockerfile
Original file line number Diff line number Diff line change
@@ -1,5 +1 @@
From alpine
WORKDIR /app/
COPY gcopy .
COPY internal/server/templates/index.tmpl internal/server/templates/index.tmpl
ENTRYPOINT ["/app/gcopy"]

29 changes: 29 additions & 0 deletions build/frontend/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
FROM node:18-alpine AS base

FROM base AS deps
RUN apk add --no-cache libc6-compat
WORKDIR /app
COPY frontend/package.json frontend/package-lock.json* ./
RUN npm config delete proxy
RUN npm ci

FROM base AS builder
WORKDIR /app
COPY --from=deps /app/node_modules ./node_modules
COPY frontend/. .
COPY frontend/.env.sample .env.production
RUN npm run build

FROM base AS runner
WORKDIR /app
ENV NODE_ENV=production
RUN addgroup -g 1001 -S nodejs
RUN adduser -S nextjs -u 1001
COPY --from=builder /app/public ./public
COPY --from=builder --chown=nextjs:nodejs /app/.next/standalone ./
COPY --from=builder --chown=nextjs:nodejs /app/.next/static ./.next/static
USER nextjs
EXPOSE 3375
ENV PORT 3375
ENV HOSTNAME=0.0.0.0
CMD ["node", "server.js"]
18 changes: 18 additions & 0 deletions build/server/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
FROM golang

WORKDIR /app
COPY . .

RUN go mod download
RUN go mod verify

RUN CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -o /gcopy ./cmd

From alpine

WORKDIR /
COPY --from=0 /gcopy .

EXPOSE 3375

ENTRYPOINT ["/gcopy"]
23 changes: 1 addition & 22 deletions cmd/gcopy.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,7 @@ package main
import (
"fmt"
"os"
"strings"
"sync"
"time"

"github.com/llaoj/gcopy/internal/client"
"github.com/llaoj/gcopy/internal/config"
"github.com/llaoj/gcopy/internal/server"
"github.com/sirupsen/logrus"
Expand All @@ -33,22 +29,5 @@ func main() {
log.SetLevel(logrus.InfoLevel)
}
log.Debugf("config: %+v", cfg)

var wg sync.WaitGroup
if strings.Contains(cfg.Role, "server") {
wg.Add(1)
go server.NewServer(log).Run(&wg)
time.Sleep(time.Second)
}

if strings.Contains(cfg.Role, "client") {
cli, err := client.NewClient(log)
if err != nil {
log.Fatal(err)
}
wg.Add(1)
go cli.Run(&wg)
}

wg.Wait()
server.NewServer(log).Run()
}
18 changes: 18 additions & 0 deletions deploy/docker-compose.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
version: '3.8'
services:
gcopy-server:
container_name: gcopy-server
image: registry.cn-beijing.aliyuncs.com/llaoj/gcopy-server:v1.0.0
restart: always

gcopy-frontend:
container_name: gcopy-frontend
image: registry.cn-beijing.aliyuncs.com/llaoj/gcopy-frontend:v1.0.0
restart: always
ports:
- "3375:3375"
volumes:
- ./frontend/.env.production:/app/.env.production
depends_on:
- gcopy-server

36 changes: 36 additions & 0 deletions deploy/nginx-example.conf
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
upstream upstream_gcopy {
server 172.10.10.10:3375 weight=1 max_fails=3 fail_timeout=30s;
}

server {
listen 80;
server_name gcopy.example.com;
return 301 https://$host$request_uri;
}

server {
listen 443 ssl http2;
listen [::]:443 ssl http2;
server_name gcopy.example.com;

client_max_body_size 0;

ssl_certificate /path/to/cert.pem;
ssl_certificate_key /path/to/key.pem;
ssl_session_timeout 5m;
ssl_ciphers ECDHE-RSA-AES128-GCM-SHA256:ECDHE:ECDH:AES:HIGH:!NULL:!aNULL:!MD5:!ADH:!RC4:!DH:!DHE;
ssl_protocols TLSv1.1 TLSv1.2 TLSv1.3;
ssl_prefer_server_ciphers on;

proxy_connect_timeout 180;
proxy_send_timeout 180;
proxy_read_timeout 180;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;

location / {
proxy_pass http://upstream_gcopy;
}
}
Binary file removed docs/client.png
Binary file not shown.
Binary file removed docs/clipboard-struct.png
Binary file not shown.
Binary file removed docs/gcopy-usage.gif
Binary file not shown.
Loading

0 comments on commit f4f7656

Please sign in to comment.