非常钟搭建一个跨平台剪贴板同步方案—— SyncClipboard!支持Windows/Linu ...

打印 上一主题 下一主题

主题 1938|帖子 1938|积分 5814

1. 唠嗑

咕咕目前重要用的都是苹果生态的设备,登录了同一个Apple账号之后,是可以实现电脑复制,手机粘贴内容的,反之亦然。信托安卓也有类似的功能。
但是仍有不少小伙伴是安卓和苹果混用的,乃至是windows和Linux混用的,有没有一个方案可以也实现跨设备之间也粘贴同步呢?
本日先容的SyncClipboard就是要实现这个功能的,感谢@chin的保举。

2. SyncClipboard重要功能(抄来自官方GitHub)



  • 剪贴板同步,支持文字、图片和文件。服务器/客户端架构,可以使用客户端内置服务器、独立部署服务器,也可以使用支持WebDAV的网盘作为服务器
  • 优化图片类型的剪贴板,功能有:

    • 从任意位置复制图片时,可以直接向文件体系粘贴图片文件,反之亦然
    • 从欣赏器复制图片后,后台下载原图到本地,解决无法从欣赏器拷贝动态图的问题(大多网站有认证,适用范围有限,支持bilibili动态图片)
    • 从文件体系复制较新格式类型的图片文件时(webp/heic等),在剪贴板内储存gif或jpg格式,用于直接向支持图片的文本框粘贴图片

3. 相关地址

官方GitHub地址:https://github.com/Jeric-X/SyncClipboard (全新项目,目前1.9个star,接待各人去给项目点星星!)
4. 搭建情况



  • 服务器:咕咕这边用的腾讯云轻量应用服务器,建议服务器内存1G以上,固然你也可以选择其他高性价比的服务器。
  • 体系:Debian 11 (DD 脚本 非必需 DD,用原来的体系也 OK,之后教程都是用 Debian 或者 Ubuntu 搭建~)
  • 安装好 Docker、Docker-compose(相关脚本)
  • 【必需】域名一枚,并做好解析到服务器上(域名购买、域名解析 视频教程)
  • 【非必需】提前安装好宝塔面板海外版本 aapanel,并安装好 Nginx(安装地址)
  • 【非必需本教程选用】安装好 Nginx Proxy Manager(相关教程)
固然你也可以选择不本身搭服务器用客户端内置服务器(大概有小伙伴担心隐私问题),或者是WebDAV服务器。
可以使用支持WebDAV协议的网盘作为服务器
测试过的服务器:


  • Nextcloud
  • AList
  • InfiniCLOUD
  • aliyundrive-webdav
5. 搭建视频(过俩天补充 = =)

5.1 YouTube

视频地址:https://youtu.be/IR2FLA0skro
5.2 哔哩哔哩

哔哩哔哩:https://www.bilibili.com/video/BV1RPwjewEks/
6. 搭建方式

6.1 安装 Docker 与 Nginx Proxy Manager

可以直接参考这篇内容:
https://blog.laoda.de/archives/nginxproxymanager/
6.2 创建安装目录

创建一下安装的目录:
  1. sudo -i
  2. mkdir -p /root/data/docker_data/syncclipboard
  3. cd /root/data/docker_data/syncclipboard
复制代码
接着我们来编辑下docker-compose.yml
  1. vim docker-compose.yml
复制代码
  1. services:
  2.   syncclipboard-server:
  3.     image: jericx/syncclipboard-server:latest
  4.     container_name: syncclipboard-server
  5.     restart: unless-stopped
  6.     ports:
  7.       - "5133:5033" # 左边的5133可以改成服务器上没有用过的其他端口
  8.     environment:
  9.       - SYNCCLIPBOARD_USERNAME=这里改成你的英文的用户名
  10.       - SYNCCLIPBOARD_PASSWORD=这个改成你的密码
复制代码
其中的5133可以改成服务器上没有效过的端口,记得修改本身的用户名和密码,修改完成之后,可以在英文输入法下,按 i 修改,完成之后,按一下 esc,然后 :wq 保存退出。
6.3 查看端口是否被占用

查看端口是否被占用(以 5133 为例),输入:
  1. lsof -i:5133  #查看 5133 端口是否被占用,如果被占用,重新自定义一个端口
复制代码
假如啥也没出现,表示端口未被占用,我们可以继续下面的操作了~
假如出现:
  1. -bash: lsof: command not found
复制代码
运行:
  1. apt install lsof  #安装 lsof
复制代码
假如端口没有被占用(被占用了就修改一下端口,好比改成 8381,注意 docker 命令行里和防火墙都要改)
6.4 启动 syncclipboard

  1. cd /root/data/docker_data/syncclipboard
  2. docker compose up -d   # 注意,老版本用户用 docker-compose up -d
复制代码
耐心等待拉取好镜像,出现 done的字样之后,
理论上我们就可以输入 http://ip:5133 访问了。
但是这边这个服务必须先搞一下反向署理!http使用明文传输太伤害,我们部署在公网一定要思量使用反向署理工具配置SSL!
做反向署理前,你必要一个域名!
namesilo 上面 xyz 后缀的域名一年就 7 块钱,可以年抛。(冷知识,namesilo上 6位数字的xyz续费永世都是0.99美元 = =)
假如想要恒久使用,还是建议买 com 后缀的域名,更加正规一些,可以输入 laodade 来获得 1 美元的优惠(不知道现在还有没有)
namesilo 自带隐私掩护,咕咕不停在用这家,价格也是这些注册商内里比较低的,关键是他家不像其他家域名注册商,没有七七八八的套路!(就是后台界面有些丑 古老 = =)
【域名购买】Namesilo 优惠码和域名解析教程(附带服务器购买保举和注意事项)
我们接着往下看!
7. 反向署理

7.1 使用 Nginx Proxy Manager

在添加反向署理之前,确保你已经完成了域名解析,不会的可以看这个:域名一枚,并做好解析到服务器上(域名购买、域名解析 视频教程) (名称改成你本身想要的域名前缀即可)
之后,登岸 Nginx Proxy Manager(不会的看这个:安装 Nginx Proxy Manager(相关教程))
   注意:
  Nginx Proxy Manager(以下简称 NPM)会用到 80、443 端口,所以本机不能占用(好比原来就有 Nginx)
  直接丢几张图:
   注意填写对应的 域名、IP 和 端口,按文章来的话,应该是 5133
  IP 填写:
假如 Nginx Proxy Manager 和 SyncClipboard 在同一台服务器上,可以在终端输入:
  1. ip addr show docker0
复制代码
查看对应的 Docker 容器内部 IP。
否则直接填 syncclipboard 所在的服务器 IP 就行。
7.2 使用宝塔面板

发现还是有不少小伙伴习惯用宝塔面板,这边也贴一个宝塔面板的反代配置:
直接新建一个站点,不要数据库,不要 php,纯静态即可。
然后打开下面的配置,修改 Nginx 的配置。
代码如下:
  1. location / {
  2.       proxy_pass http://127.0.0.1:5133/;       # 注意改成你实际使用的端口
  3.       rewrite ^/(.*)$ /$1 break;
  4.       proxy_redirect off;
  5.       proxy_set_header Host $host;
  6.       proxy_set_header X-Forwarded-Proto $scheme;
  7.       proxy_set_header X-Real-IP $remote_addr;
  8.       proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
  9.       proxy_set_header Upgrade-Insecure-Requests 1;
  10.       proxy_set_header X-Forwarded-Proto https;
  11.     }
复制代码
此方法对 90% 的反向署理都能生效,然后就可以用域名来安装访问了。
有同砚大概会问,为什么不直接用宝塔自带的反向署理功能。
也可以,不外咕咕本身之前遇到过当有多个网站必要反代的时候,在这边设置会报错的情况 = =
所以后来就不消了,直接用上面的方法来操作了。
8. 使用教程

8.1 登岸使用(以安卓和IOS为例子)

这边我手头没有window电脑,我演示一下安卓和IOS怎样互通粘贴板。
安卓配置

安卓下载一个APP——HTTP Request Shortcuts

可以直接在谷歌应用市肆搜索下载:https://play.google.com/store/apps/details?id=ch.rmy.android.http_shortcuts
也可以在F-Droid下载:https://f-droid.org/en/packages/ch.rmy.android.http_shortcuts/
或者直接GitHub上下载:https://github.com/Waboodoo/HTTP-Shortcuts/releases
HTTP Request Shortcuts的GitHub堆栈:https://github.com/Waboodoo/HTTP-Shortcuts
手机上下载,导入这个配置文件,
这个是个压缩包,解压之后是个json文件,然后一会儿上传到HTTP Request Shortcuts内里即可。
不方便下载的,咕咕这边留一个网盘的地址,各人可以在这边下载:https://share.gugu.ovh/local/%E5%85%AC%E5%85%B1%E6%96%87%E4%BB%B6%E5%A4%B9/Docker%E9%A1%B9%E7%9B%AE/SyncClipboard
json的内容是这个:
  1. {
  2.   "categories": [
  3.     {
  4.       "id": "accb6a5b-60a3-4ba5-921a-f9cd772067aa",
  5.       "name": "快捷方式",
  6.       "shortcuts": [
  7.         {
  8.           "authentication": "basic",
  9.           "bodyContent": "{"File":"","Clipboard":"{{76b1e948-84b3-497e-8ec5-b911d00f8f0f}}","Type":"Text"}",
  10.           "codeOnSuccess": "showToast(\u0027已上传\u0027);",
  11.           "contentType": "application/json",
  12.           "description": "支持选中文字后分享",
  13.           "iconName": "freepik_upload",
  14.           "id": "d6a958cb-3fa6-4c79-b342-229008bfac8a",
  15.           "method": "PUT",
  16.           "name": "上传剪贴板",
  17.           "password": "{{9421719b-086f-4799-8432-158b84b6e05a}}",
  18.           "proxy": "",
  19.           "quickSettingsTileShortcut": true,
  20.           "responseHandling": {
  21.             "successOutput": "none"
  22.           },
  23.           "url": "{{136751b5-5f38-49fc-81dc-80a825804203}}/SyncClipboard.json",
  24.           "username": "{{719f997c-6bf6-458f-a148-3c2a8ac5e405}}"
  25.         },
  26.         {
  27.           "authentication": "basic",
  28.           "codeOnSuccess": "const profile \u003d JSON.parse(response.body)\r\nconst type \u003d profile.Type\r\n\r\nif (type \u003d\u003d \u0027Text\u0027) {\r\n    const ClibboardText \u003d profile.Clipboard;\r\n    copyToClipboard(ClibboardText);\r\n    showToast(\u0027已拷贝\\n\u0027 + ClibboardText);\r\n\r\n    const httpstr \u003d httpString(ClibboardText);\r\n\r\n    if (httpstr) {\r\n        if (confirm(\u0027包含网址,是否打开\u0027)) {\r\n            openUrl(httpstr[0]);\r\n        }\r\n    }\r\n}\r\nelse if (profile.File \u0026\u0026 profile.File.length \u003e 0) {\r\n    const downloadUrl \u003d getVariable(/*[variable]*/"136751b5-5f38-49fc-81dc-80a825804203"/*[/variable]*/) + \u0027/file/\u0027 + encodeURIComponent(profile.File)\r\n    const inputPara \u003d { \u0027downloadUrl\u0027: downloadUrl }\r\n    showToast(\u0027文件名已拷贝,正在下载\\n\u0027 + profile.File)\r\n    copyToClipboard(profile.File)\r\n    if (type \u003d\u003d \u0027Image\u0027 || isImageFile(profile.File)) {\r\n        enqueueShortcut(/*[shortcut]*/"1e693964-ab59-4e9c-902b-6b94b90ff2f0"/*[/shortcut]*/, inputPara)\r\n    } else {\r\n        enqueueShortcut(/*[shortcut]*/"1e693964-ab59-4e9c-902b-6b94b90ff2f0"/*[/shortcut]*/, inputPara)\r\n    }\r\n}\r\n\r\nfunction isImageFile(file) {\r\n    const filename \u003d file.toLowerCase();\r\n    const list \u003d [\r\n        \u0027.png\u0027,\r\n        \u0027.jpg\u0027,\r\n        \u0027.jpeg\u0027,\r\n        \u0027.gif\u0027,\r\n        \u0027.bmp\u0027,\r\n        \u0027.webp\u0027,\r\n    ]\r\n    let result \u003d false\r\n    list.forEach(element \u003d\u003e {\r\n        if (filename.endsWith(element)) {\r\n            result \u003d true\r\n        }\r\n    })\r\n    return result\r\n}\r\n\r\nfunction httpString(s) {\r\n    var reg \u003d /(https?|http|ftp|file):\\/\\/[-A-Za-z0-9+\u0026@#/%?\u003d~_|!:,.;]+[-A-Za-z0-9+\u0026@#/%\u003d~_|]/g;\r\n    s \u003d s.match(reg);\r\n    return (s)\r\n}",
  29.           "iconName": "freepik_download",
  30.           "id": "91cf41c5-da0c-45b5-988c-9f636e135abd",
  31.           "name": "下载剪贴板",
  32.           "password": "{{9421719b-086f-4799-8432-158b84b6e05a}}",
  33.           "proxy": "",
  34.           "quickSettingsTileShortcut": true,
  35.           "responseHandling": {
  36.             "successOutput": "none"
  37.           },
  38.           "url": "{{136751b5-5f38-49fc-81dc-80a825804203}}/SyncClipboard.json",
  39.           "username": "{{719f997c-6bf6-458f-a148-3c2a8ac5e405}}"
  40.         },
  41.         {
  42.           "authentication": "basic",
  43.           "bodyContent": "{"File":"","Clipboard":"{{76b1e948-84b3-497e-8ec5-b911d00f8f0f}}","Type":"Text"}",
  44.           "codeOnPrepare": "setVariable(/*[variable]*/"d12cab01-6d2b-44aa-a1fb-dfddc6fe7895"/*[/variable]*/, selectedFiles[0].name);",
  45.           "codeOnSuccess": "enqueueShortcut(\u0027上传文件 控制部分\u0027)",
  46.           "contentType": "application/json",
  47.           "description": "从分享菜单使用",
  48.           "iconName": "freepik_upload",
  49.           "id": "2b8e95a4-2ece-41a1-aace-f8f80c0497fb",
  50.           "method": "PUT",
  51.           "name": "上传文件",
  52.           "password": "{{9421719b-086f-4799-8432-158b84b6e05a}}",
  53.           "proxy": "",
  54.           "requestBodyType": "file",
  55.           "responseHandling": {
  56.             "successOutput": "none"
  57.           },
  58.           "url": "{{136751b5-5f38-49fc-81dc-80a825804203}}/file/{{d12cab01-6d2b-44aa-a1fb-dfddc6fe7895}}",
  59.           "username": "{{719f997c-6bf6-458f-a148-3c2a8ac5e405}}"
  60.         }
  61.       ]
  62.     },
  63.     {
  64.       "id": "316553f3-4bb0-4e10-806b-0de26e10fb2a",
  65.       "name": "基础组件",
  66.       "shortcutClickBehavior": "edit",
  67.       "shortcuts": [
  68.         {
  69.           "authentication": "basic",
  70.           "bodyContent": "{"File":"{{d12cab01-6d2b-44aa-a1fb-dfddc6fe7895}}","Clipboard":"","Type":"File"}",
  71.           "codeOnSuccess": "showToast(\u0027已上传\u0027);",
  72.           "contentType": "application/json",
  73.           "iconName": "freepik_upload",
  74.           "id": "2424dcac-6fa0-4ff9-849b-63a56d63c79f",
  75.           "method": "PUT",
  76.           "name": "上传文件 控制部分",
  77.           "password": "{{9421719b-086f-4799-8432-158b84b6e05a}}",
  78.           "proxy": "",
  79.           "responseHandling": {
  80.             "successOutput": "none"
  81.           },
  82.           "url": "{{136751b5-5f38-49fc-81dc-80a825804203}}/SyncClipboard.json",
  83.           "username": "{{719f997c-6bf6-458f-a148-3c2a8ac5e405}}"
  84.         },
  85.         {
  86.           "authentication": "basic",
  87.           "bodyContent": "{"File":"","Clipboard":"{{76b1e948-84b3-497e-8ec5-b911d00f8f0f}}","Type":"Text"}",
  88.           "contentType": "application/json",
  89.           "description": "只支持2m以下文件",
  90.           "iconName": "flat_color_folder",
  91.           "id": "1e693964-ab59-4e9c-902b-6b94b90ff2f0",
  92.           "name": "展示文件",
  93.           "password": "{{9421719b-086f-4799-8432-158b84b6e05a}}",
  94.           "proxy": "",
  95.           "requestBodyType": "file",
  96.           "responseHandling": {
  97.             "actions": [
  98.               "share",
  99.               "copy",
  100.               "save"
  101.             ]
  102.           },
  103.           "url": "{{5989c421-2669-4424-80c3-69ba7995524a}}",
  104.           "username": "{{719f997c-6bf6-458f-a148-3c2a8ac5e405}}"
  105.         }
  106.       ]
  107.     }
  108.   ],
  109.   "compatibilityVersion": 71,
  110.   "variables": [
  111.     {
  112.       "id": "719f997c-6bf6-458f-a148-3c2a8ac5e405",
  113.       "key": "UserName",
  114.       "value": "ChangeIt"
  115.     },
  116.     {
  117.       "id": "9421719b-086f-4799-8432-158b84b6e05a",
  118.       "key": "UserToken",
  119.       "value": "ChangeIt"
  120.     },
  121.     {
  122.       "flags": 1,
  123.       "id": "76b1e948-84b3-497e-8ec5-b911d00f8f0f",
  124.       "jsonEncode": true,
  125.       "key": "Clipboard",
  126.       "type": "clipboard"
  127.     },
  128.     {
  129.       "id": "d12cab01-6d2b-44aa-a1fb-dfddc6fe7895",
  130.       "jsonEncode": true,
  131.       "key": "FileName",
  132.       "value": ""
  133.     },
  134.     {
  135.       "id": "136751b5-5f38-49fc-81dc-80a825804203",
  136.       "key": "url",
  137.       "value": "ChangeIt"
  138.     },
  139.     {
  140.       "id": "5989c421-2669-4424-80c3-69ba7995524a",
  141.       "key": "downloadUrl",
  142.       "value": ""
  143.     }
  144.   ],
  145.   "version": 75
  146. }
复制代码
修改变量中的UserName,UserToken,url, url不要以斜线分隔符/结尾。
HTTP Request Shortcuts支持从下拉菜单、桌面组件、桌面图标、分享菜单中使用。
IOS配置

官方给了很多选择:
使用快捷指令


  • 手动同步,导入这个快捷指令,手动触发上传或下载
  • 主动同步,导入这个快捷指令,运行后设备会主动在后台同步剪贴板内容,此快捷指令将实行无限时长,必要手动关闭,你还可以手动修改同步后是否发送体系通知、查询的间隔秒数
  • 主动上传短信验证码,参考这个帖子中的视频教程 #60
我本身偏向于手动同步,所以导入了这个快捷指令,手动触发上传或下载。
记得修改一下这三个,
然后保持就可以了。
试试效果吧!亲测非常好用!
WIndows, Linux, macOS客户端,Arch Linux还有其他安卓的方式,各人可以参考官方的文档:https://github.com/Jeric-X/SyncClipboard
为了避免有些小伙伴访问不了,我也粘贴一份在博客里:
桌面客户端(Windows/Linux/macOS)运行在后台时将主动同步剪贴板
Windows

下载地址:Release页面中的SyncClipboard.zip,解压缩后运行SyncClipboard.exe
依赖:


  • .NET 6.0桌面运行时,未安装会弹窗提醒并跳转到微软官方下载页面
  • ASP.NET Core 6.0运行时,未安装会弹窗提醒并跳转到微软官方下载页面
  • Windows10 2004及以上
  • 微软Segoe Fluent Icons图标字体,Windows11自带无需安装,Windows10必要手动下载安装(官方地址),否则界面图标会大范围出错
注意:


  • 删除软件时,配置文件目录不会被删除,配置文件储存在%AppData%\SyncClipboard\,必要彻底删除软件时请手动删除整个目录
Linux, macOS

下载地址:SyncClipboard.Desktop,根据体系选择你必要的安装包
注意:


  • 名称中带有no-self-contained:依赖.NET 6.0桌面运行时和ASP.NET Core 6.0运行时
  • 名称中带有self-contained:通常可以直接运行
  • 删除软件时,配置文件目录不会被删除,配置文件储存在~/.config/SyncClipboard/(Linux),~/Library/Application Support/SyncClipboard/(macOS),必要彻底删除软件时请手动删除整个目录
  • 使用deb、rpm安装包时,每次更新版本必要先删除旧版,再安装新版,不支持直接更新
  • Linux: 快捷键在Wayland不可用
  • Linux: 无法主动识别语言,默认为英语
  • macOS: “SyncClipboard”已破坏,无法打开,在终端中实行sudo xattr -d com.apple.quarantine /Applications/SyncClipboard.app
  • macOS: 快捷键依赖辅助功能权限(Accessibility),软件在必要时会弹窗提示(所有快捷键为空时则不必要),每个新版本必要重新授予权限
Arch Linux

Arch Linux 用户可以直接从 AUR 安装:
  1. paru -Sy syncclipboard-desktop
复制代码
安装后从菜单中启动即可,假如要从命令行中启动,请注意必要英文情况,即以 LANG=en_US.UTF-8 syncclipboard-desktop 来启动,启动后可以在软件内设置语言为中文。配置保存路径为:~/.config/SyncClipboard。
Android

使用HTTP Request Shortcuts

导入这个配置文件,修改变量中的UserName,UserToken,url, url不要以斜线分隔符/结尾。HTTP Request Shortcuts支持从下拉菜单、桌面组件、桌面图标、分享菜单中使用
使用Autox.js



  • 主动同步,使用这个js文件。由于安卓体系限定,在安卓10及以上的体系应用无法在后台读取剪贴板,但可以使用基于Root权限的工具(Magisk/Xposed)排除应用后台读取剪贴版的权限,如Riru-ClipboardWhitelist、Clipboard Whitelist。由于在安卓13及以上的体系应用必须由用户手动授权才被允许访问体系日志(剪贴板),也可以使用Xposed主动为应用授权访问体系日志的权限,如DisableLogRequest/禁用日志访问请求
  • 主动上传验证码,使用这个js文件,这个脚本运行在后台时将读取所有通知消息,在识别到验证码类信息时将证码上传到服务器
导入js文件、修改每个文件头部的用户配置后,手动点击运行,或者为每个js文件设置触发方式,例如:开机时触发
使用SmsForwarder



  • 主动上传验证码, #109
使用Tasker



  • https://github.com/forrestgao/taskerforSyncClipboard ,作者:forrestgao
Tasker是一款安卓体系上非常强大的主动化工具软件,你可以根据SyncClipboard的API创建适合本身的配置文件,假如你认为你的配置文件非常通用并希望分享出来,接待联系我置于此处
客户端配置说明

全平台依赖三条必要配置(配置的拼写大概会有所差别,寄义相同)。


  • user
  • password
  • url,格式为http(s)

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

x
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

知者何南

论坛元老
这个人很懒什么都没写!
快速回复 返回顶部 返回列表