├── base ├── alpine │ ├── Dockerfile │ └── meta.json ├── nginx │ ├── Dockerfile │ ├── Dockerfile.vue │ ├── Dockerfile.svelte │ ├── meta.json │ └── conf │ │ ├── default.conf │ │ ├── default.vue.conf │ │ └── default.svelte.conf ├── tg-session │ ├── meta.json │ ├── Dockerfile │ ├── README.md │ └── main.py ├── vscode │ ├── meta.json │ ├── starship.toml │ ├── Dockerfile.stable │ ├── docker-entrypoint.sh │ ├── Dockerfile │ └── README.md └── self │ ├── meta.json │ ├── Dockerfile │ └── Dockerfile.ubuntu ├── .gitignore ├── .markdownlint.json ├── .actrc ├── apps ├── lsky │ ├── assets │ │ └── screenshot.png │ ├── docker-compose.yml │ ├── docker-entrypoint.sh │ ├── default.conf │ ├── meta.json │ ├── Dockerfile │ ├── Dockerfile.dev │ └── README.md ├── readest │ ├── docker-compose.yml │ ├── meta.json │ ├── Dockerfile │ ├── docker-entrypoint.sh │ └── README.md ├── inpaint-web │ ├── Dockerfile │ ├── meta.json │ └── README.md ├── yulegeyu │ ├── meta.json │ ├── Dockerfile │ └── README.md ├── jsonhero-web │ ├── Dockerfile │ ├── docker-entrypoint.sh │ ├── meta.json │ └── README.md ├── weektodo │ ├── Dockerfile │ ├── meta.json │ └── README.md ├── cobalt │ ├── docker-compose.yml │ ├── Dockerfile │ ├── meta.json │ ├── docker-entrypoint.sh │ └── README.md ├── haitang │ ├── meta.json │ ├── Dockerfile │ └── README.md ├── icones │ ├── meta.json │ ├── Dockerfile │ └── README.md ├── telegram-upload │ ├── meta.json │ ├── Dockerfile │ └── README.md ├── n8n-workflows │ ├── meta.json │ ├── Dockerfile │ └── README.md ├── memogram │ ├── meta.json │ ├── Dockerfile │ └── README.md ├── telemirror │ ├── Dockerfile.stable │ ├── Dockerfile │ ├── meta.json │ └── README.md ├── srcbook │ ├── Dockerfile │ ├── Dockerfile.tls │ ├── meta.json │ └── README.md └── weserv │ ├── meta.json │ ├── Dockerfile.alpine │ └── Dockerfile ├── .github ├── instructions │ ├── git-commit-message.md │ ├── action.instructions.md │ └── basic.instructions.md └── workflows │ ├── check-version.yaml │ ├── sync-readme.yaml │ └── build-test.yaml ├── action ├── tsconfig.json ├── src │ ├── types │ │ ├── git.ts │ │ ├── input.ts │ │ ├── index.ts │ │ └── schema.ts │ ├── file.ts │ ├── metadata.ts │ ├── lib │ │ └── validator.ts │ ├── check.ts │ ├── context │ │ └── metaAppsManager.ts │ ├── config.ts │ ├── utils.ts │ └── manifest.ts ├── resolve-meta │ └── action.yml ├── check-version │ └── action.yml └── package.json ├── .editorconfig ├── event.json ├── .devcontainer └── devcontainer.json ├── test ├── weektodo-mul │ ├── Dockerfile │ ├── Dockerfile.dev │ └── meta.json ├── weektodo │ ├── Dockerfile │ └── meta.json ├── icones │ ├── Dockerfile │ └── meta.json └── self │ ├── meta.json │ └── Dockerfile ├── package.json ├── deprecated ├── filecodebox │ ├── Dockerfile │ ├── meta.json │ └── README.md ├── tgcf-multx-01 │ ├── Dockerfile │ └── meta.json └── tgcf │ ├── Dockerfile │ ├── Dockerfile.multx-01 │ ├── meta.json │ └── README.md ├── LICENSE ├── eslint.config.mjs ├── .vscode └── settings.json └── scripts └── new.sh /base/alpine/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM alpine:3.22.1 2 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .history 2 | *.log 3 | test.sh 4 | node_modules 5 | .env 6 | *.bak 7 | 8 | bak 9 | -------------------------------------------------------------------------------- /.markdownlint.json: -------------------------------------------------------------------------------- 1 | { 2 | "no-emphasis-as-heading": false, 3 | "line-length": false 4 | } 5 | -------------------------------------------------------------------------------- /.actrc: -------------------------------------------------------------------------------- 1 | --pull=false 2 | --secret-file .env 3 | --artifact-server-path /tmp/apps-image-artifacts 4 | -------------------------------------------------------------------------------- /apps/lsky/assets/screenshot.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aliuq/apps-image/master/apps/lsky/assets/screenshot.png -------------------------------------------------------------------------------- /base/nginx/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM nginx:alpine 2 | 3 | WORKDIR /app 4 | COPY ./conf/default.conf /etc/nginx/conf.d/default.conf 5 | 6 | CMD ["nginx", "-g", "daemon off;"] 7 | 8 | EXPOSE 80 9 | -------------------------------------------------------------------------------- /base/nginx/Dockerfile.vue: -------------------------------------------------------------------------------- 1 | FROM nginx:alpine 2 | 3 | WORKDIR /app 4 | COPY ./conf/default.vue.conf /etc/nginx/conf.d/default.conf 5 | 6 | CMD ["nginx", "-g", "daemon off;"] 7 | 8 | EXPOSE 80 9 | -------------------------------------------------------------------------------- /base/nginx/Dockerfile.svelte: -------------------------------------------------------------------------------- 1 | FROM nginx:alpine 2 | 3 | WORKDIR /app 4 | COPY ./conf/default.svelte.conf /etc/nginx/conf.d/default.conf 5 | 6 | CMD ["nginx", "-g", "daemon off;"] 7 | 8 | EXPOSE 80 9 | -------------------------------------------------------------------------------- /.github/instructions/git-commit-message.md: -------------------------------------------------------------------------------- 1 | ## Git 提交信息规范 2 | 3 | ### 基本要求 4 | 5 | 1. 始终遵循 Angular 规范的提交信息格式 6 | 2. 始终使用英文进行描述 7 | 3. 提交信息应简洁明了,避免冗长的解释 8 | 4. 在提交信息中使用动词的原形 9 | 10 | ### 项目要求 11 | 12 | 1. 当暂存更改只包含 `apps/{APP}/*`、`base/{APP}/*`、`test/{APP}/*` 目录下的文件时,请遵循以下类似格式 "feat({APP}): "、"fix({APP}): "、"docs({APP}): " 13 | -------------------------------------------------------------------------------- /base/alpine/meta.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "alpine", 3 | "type": "base", 4 | "description": "Alpine Linux 3.20", 5 | "variants": { 6 | "latest": { 7 | "version": "3.22.1", 8 | "sha": "a274bcf3c7710d34df2b38ae6ac4ab5684d8f72d", 9 | "checkver": { 10 | "type": "manual" 11 | } 12 | } 13 | } 14 | } -------------------------------------------------------------------------------- /action/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "es2020", 4 | "module": "NodeNext", 5 | "moduleResolution": "nodenext", 6 | "resolveJsonModule": true, 7 | "strict": true, 8 | "declaration": true, 9 | "outDir": "dist", 10 | "esModuleInterop": true, 11 | "skipLibCheck": true 12 | }, 13 | "include": ["src"] 14 | } 15 | -------------------------------------------------------------------------------- /action/src/types/git.ts: -------------------------------------------------------------------------------- 1 | export interface GitCommitInfo { 2 | /** 提交信息 */ 3 | commitMessage: string 4 | /** 提交作者 */ 5 | commitAuthor: string 6 | /** 提交日期 */ 7 | commitDate: string 8 | /** 修改的文件数量 */ 9 | changedFiles: number 10 | /** 添加的行数 */ 11 | additions: number 12 | /** 删除的行数 */ 13 | deletions: number 14 | /** 最近的提交记录 */ 15 | recentCommits: string[] 16 | } 17 | -------------------------------------------------------------------------------- /apps/readest/docker-compose.yml: -------------------------------------------------------------------------------- 1 | name: readest 2 | 3 | services: 4 | readest: 5 | image: aliuq/readest:latest 6 | container_name: readest 7 | restart: unless-stopped 8 | ports: 9 | - '3000:3000' 10 | environment: 11 | - NEXT_PUBLIC_POSTHOG_KEY=your_posthog_key # 设置为任意不为空的值以禁用数据收集 12 | - NEXT_PUBLIC_SUPABASE_URL=https://your-supabase-url.com # 禁用官方 supabase 实例 13 | -------------------------------------------------------------------------------- /apps/inpaint-web/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM alpine/git AS base 2 | WORKDIR /app 3 | ARG VERSION=f7ff41f 4 | RUN git clone https://github.com/lxfater/inpaint-web . && git checkout ${VERSION} 5 | 6 | FROM node:18.20.2-alpine3.19 AS build 7 | WORKDIR /app 8 | COPY --from=base /app . 9 | RUN npm install && npm run fast-build 10 | 11 | FROM aliuq/nginx:vue 12 | WORKDIR /app 13 | COPY --from=build /app/dist /app 14 | 15 | EXPOSE 80 16 | -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | # EditorConfig is awesome: https://EditorConfig.org 2 | 3 | root = true 4 | 5 | [*] 6 | indent_style = space 7 | indent_size = 2 8 | end_of_line = lf 9 | charset = utf-8 10 | trim_trailing_whitespace = true 11 | insert_final_newline = true 12 | 13 | [*.md] 14 | trim_trailing_whitespace = false 15 | 16 | [*.{yaml,yml}] 17 | indent_size = 2 18 | 19 | [*.sh] 20 | indent_size = 2 21 | 22 | [Dockerfile] 23 | indent_size = 4 24 | -------------------------------------------------------------------------------- /event.json: -------------------------------------------------------------------------------- 1 | { 2 | "inputs": { 3 | "debug": "true", 4 | "create_pr": "false", 5 | "context": "apps/icones", 6 | "variants": "latest" 7 | }, 8 | "pull_request": { 9 | "number": 1, 10 | "title": "update(test/weektodo): update latest version to 2.2.0", 11 | "body": "", 12 | "head": { 13 | "ref": "update/test-weektodo" 14 | }, 15 | "base": { 16 | "ref": "master" 17 | } 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /.devcontainer/devcontainer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "apps-image", 3 | "image": "ghcr.io/aliuq/devcontainer:me", 4 | "customizations": { 5 | "vscode": { 6 | "extensions": [ 7 | "redhat.vscode-yaml", 8 | "tamasfe.even-better-toml", 9 | "dbaeumer.vscode-eslint" 10 | ] 11 | } 12 | }, 13 | "features": { 14 | "ghcr.io/aliuq/devcontainer-features/common:0": { 15 | "misePackages": "act" 16 | } 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /apps/yulegeyu/meta.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "yulegeyu", 3 | "type": "app", 4 | "title": "鱼了个鱼", 5 | "slogan": "羊了个羊纯前端实现版,休闲益智游戏", 6 | "description": "羊了个羊纯前端实现版【鱼了个鱼】,自定义关卡+图案+无限道具", 7 | "variants": { 8 | "latest": { 9 | "version": "4b9de83", 10 | "sha": "4b9de839b62360b05835e5754ec7b7d3e55b2abf", 11 | "checkver": { 12 | "type": "sha", 13 | "repo": "https://github.com/liyupi/yulegeyu" 14 | } 15 | } 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /base/tg-session/meta.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "tg-session", 3 | "type": "base", 4 | "description": "A Telegram session string generator with QR code login support. This tool helps you generate session strings for Telegram applications.", 5 | "license": "MIT", 6 | "variants": { 7 | "latest": { 8 | "version": "0.1.1", 9 | "sha": "d2b131980136ab125a170a534f29cd7a9e1b5b81", 10 | "checkver": { 11 | "type": "manual" 12 | } 13 | } 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /apps/jsonhero-web/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM alpine/git AS source 2 | WORKDIR /app 3 | ARG VERSION=1515705 4 | RUN git clone https://github.com/triggerdotdev/jsonhero-web . && git checkout ${VERSION} 5 | 6 | # Build stage 7 | FROM node:16.17.0-alpine3.16 8 | WORKDIR /app 9 | COPY --from=source /app . 10 | RUN npm install && npm run build 11 | 12 | COPY docker-entrypoint.sh /docker-entrypoint.sh 13 | RUN chmod +x /docker-entrypoint.sh 14 | 15 | ENTRYPOINT ["/docker-entrypoint.sh"] 16 | EXPOSE 8787 17 | -------------------------------------------------------------------------------- /test/weektodo-mul/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM alpine/git AS base 2 | WORKDIR /app 3 | RUN git clone https://github.com/manuelernestog/weektodo.git . && git checkout 0296d29 4 | 5 | FROM node:16.20.2-alpine3.18 AS builder 6 | WORKDIR /app 7 | COPY --from=base /app . 8 | RUN yarn install --frozen-lockfile --network-timeout 600000 9 | RUN yarn run build 10 | 11 | FROM nginx:1.21.3-alpine 12 | 13 | WORKDIR /usr/share/nginx/html 14 | COPY --from=builder /app/dist /usr/share/nginx/html 15 | 16 | EXPOSE 80 17 | -------------------------------------------------------------------------------- /test/weektodo/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM alpine/git AS source 2 | WORKDIR /app 3 | RUN git clone https://github.com/manuelernestog/weektodo . && git checkout 0296d29 4 | 5 | FROM node:16.20.2-alpine3.18 AS builder 6 | WORKDIR /app 7 | COPY --from=source /app . 8 | # 5 min 9 | RUN yarn install --frozen-lockfile --network-timeout 600000 10 | RUN yarn run build 11 | 12 | FROM nginx:1.21.3-alpine 13 | WORKDIR /usr/share/nginx/html 14 | COPY --from=builder /app/dist /usr/share/nginx/html 15 | 16 | EXPOSE 80 17 | -------------------------------------------------------------------------------- /base/tg-session/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM python:3.10.0-alpine3.15 AS build 2 | 3 | ENV PIP_NO_CACHE_DIR=1 4 | WORKDIR /app 5 | RUN pip install --target=/app/dependencies telethon qrcode python-dotenv 6 | 7 | FROM build AS release 8 | 9 | ENV PYTHONUNBUFFERED=1 10 | 11 | WORKDIR /app 12 | COPY --from=build /app /app 13 | COPY ./main.py ./main.py 14 | 15 | ENV PYTHONPATH=/app/dependencies 16 | ENV DEBUG=False 17 | ENV API_ID= 18 | ENV API_HASH= 19 | 20 | CMD ["python", "main.py"] 21 | VOLUME /app/session 22 | -------------------------------------------------------------------------------- /test/weektodo-mul/Dockerfile.dev: -------------------------------------------------------------------------------- 1 | FROM alpine/git AS base 2 | WORKDIR /app 3 | RUN git clone https://github.com/manuelernestog/weektodo.git . && git checkout d384fc7 4 | 5 | FROM node:16.20.2-alpine3.18 AS builder 6 | WORKDIR /app 7 | COPY --from=base /app . 8 | RUN yarn install --frozen-lockfile --network-timeout 600000 9 | RUN yarn run build 10 | 11 | FROM nginx:1.21.3-alpine 12 | 13 | WORKDIR /usr/share/nginx/html 14 | COPY --from=builder /app/dist /usr/share/nginx/html 15 | 16 | EXPOSE 80 17 | -------------------------------------------------------------------------------- /apps/jsonhero-web/docker-entrypoint.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | set -e 4 | 5 | ME=$(basename "$0") 6 | 7 | entrypoint_log() { 8 | if [ -z "${NGINX_ENTRYPOINT_QUIET_LOGS:-}" ]; then 9 | echo "$@" 10 | fi 11 | } 12 | 13 | # 写入环境变量 SESSION_SECRET 到 .env。如果 SESSION_SECRET 为空,则写入默认值 abc123 14 | if [ -z "${SESSION_SECRET}" ]; then 15 | SESSION_SECRET="abc123" 16 | entrypoint_log "$ME: Not found SESSION_SECRET, use default value" 17 | fi 18 | echo "SESSION_SECRET=${SESSION_SECRET}" >> .env 19 | 20 | npm start 21 | -------------------------------------------------------------------------------- /apps/weektodo/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM alpine/git AS base 2 | WORKDIR /app 3 | ARG VERSION=0296d29 4 | RUN git clone https://github.com/manuelernestog/weektodo . && git checkout ${VERSION} 5 | 6 | FROM node:16.20.2-alpine3.18 AS builder 7 | WORKDIR /app 8 | COPY --from=base /app . 9 | RUN yarn install --frozen-lockfile --network-timeout 600000 10 | RUN yarn run build 11 | 12 | FROM nginx:1.21.3-alpine 13 | 14 | WORKDIR /usr/share/nginx/html 15 | COPY --from=builder /app/dist /usr/share/nginx/html 16 | 17 | EXPOSE 80 18 | -------------------------------------------------------------------------------- /apps/cobalt/docker-compose.yml: -------------------------------------------------------------------------------- 1 | services: 2 | cobalt-api: 3 | image: ghcr.io/imputnet/cobalt:11.0.1 4 | restart: always 5 | container_name: cobalt-api 6 | ports: 7 | - 9000:9000 8 | environment: 9 | - API_URL=http://localhost:9000 10 | 11 | cobalt-web: 12 | build: 13 | context: . 14 | dockerfile: Dockerfile 15 | restart: always 16 | container_name: cobalt-web 17 | ports: 18 | - 8080:80 19 | environment: 20 | - BASE_API=http://localhost:9000 21 | -------------------------------------------------------------------------------- /apps/haitang/meta.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "haitang", 3 | "type": "app", 4 | "title": "海棠诗社", 5 | "description": "海棠诗社,古诗词的数字桃源", 6 | "license": "MIT", 7 | "variants": { 8 | "latest": { 9 | "version": "3d5ff9c", 10 | "sha": "3d5ff9c222ee76e6635fad44b9df6bd57f3805fb", 11 | "checkver": { 12 | "type": "sha", 13 | "repo": "javayhu/haitang" 14 | }, 15 | "docker": { 16 | "labels": { 17 | "author": "javayhu" 18 | } 19 | } 20 | } 21 | } 22 | } -------------------------------------------------------------------------------- /apps/icones/meta.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "icones", 3 | "type": "app", 4 | "title": "Icones", 5 | "slogan": "开源图标浏览器,搜索浏览 150,000+ 图标", 6 | "description": "Icon Explorer with Instant searching, powered by Iconify", 7 | "license": "MIT", 8 | "variants": { 9 | "latest": { 10 | "version": "fb6710e", 11 | "sha": "fb6710e341e65727ea6b82f348c8fe49830e2f61", 12 | "checkver": { 13 | "type": "sha", 14 | "repo": "https://github.com/antfu-collective/icones" 15 | } 16 | } 17 | } 18 | } -------------------------------------------------------------------------------- /test/icones/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM alpine/git AS base 2 | WORKDIR /app 3 | RUN git clone https://github.com/antfu-collective/icones . && git checkout d96ef28 4 | 5 | FROM node:22.14.0-alpine3.20 AS build 6 | WORKDIR /app 7 | COPY --from=base /app . 8 | RUN corepack enable && corepack prepare --activate 9 | RUN pnpm install && pnpm run build 10 | 11 | FROM aliuq/nginx:vue 12 | 13 | ENV TZ=Asia/Shanghai 14 | ENV NODE_ENV=production 15 | 16 | WORKDIR /app 17 | 18 | COPY --from=build /app/dist /app 19 | 20 | CMD ["nginx", "-g", "daemon off;"] 21 | EXPOSE 80 22 | -------------------------------------------------------------------------------- /apps/inpaint-web/meta.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "inpaint-web", 3 | "type": "app", 4 | "title": "Inpaint Web", 5 | "slogan": "AI 图像修复工具,智能去除图片对象", 6 | "description": "基于 Webgpu 技术和 wasm 技术的免费开源 inpainting & image-upscaling 工具, 纯浏览器端实现", 7 | "license": "GPL-3.0", 8 | "variants": { 9 | "latest": { 10 | "version": "f7ff41f", 11 | "sha": "f7ff41f0163fa7e4db47889be18cdba656a728dc", 12 | "checkver": { 13 | "type": "sha", 14 | "repo": "https://github.com/lxfater/inpaint-web" 15 | } 16 | } 17 | } 18 | 19 | } 20 | -------------------------------------------------------------------------------- /apps/lsky/docker-compose.yml: -------------------------------------------------------------------------------- 1 | services: 2 | lsky: 3 | build: 4 | context: . 5 | dockerfile: Dockerfile 6 | restart: always 7 | ports: 8 | - 8089:80 9 | environment: 10 | - UPLOAD_MAX_FILESIZE=20M 11 | - POST_MAX_SIZE=15M 12 | depends_on: 13 | - lsky-db 14 | lsky-db: 15 | image: postgres:15-alpine 16 | container_name: lsky-db 17 | restart: always 18 | environment: 19 | POSTGRES_USER: lsky 20 | POSTGRES_PASSWORD: lsky 21 | POSTGRES_DB: lsky 22 | PGDATA: /pg-data 23 | -------------------------------------------------------------------------------- /apps/telegram-upload/meta.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "telegram-upload", 3 | "type": "app", 4 | "title": "Telegram Upload", 5 | "slogan": "Telegram 文件上传工具,支持大文件分片", 6 | "description": "Upload and download files from Telegram up to 4 GiB using your account", 7 | "license": "MIT", 8 | "variants": { 9 | "latest": { 10 | "version": "c700f86", 11 | "sha": "c700f86dd72ec97d0ca782b8d504e7eb502f04dc", 12 | "checkver": { 13 | "type": "sha", 14 | "repo": "https://github.com/Nekmo/telegram-upload" 15 | } 16 | } 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /apps/n8n-workflows/meta.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "n8n-workflows", 3 | "type": "app", 4 | "slogan": "n8n 工作流模板", 5 | "description": "all of the workflows of n8n i could find (also from the site itself)", 6 | "variants": { 7 | "latest": { 8 | "version": "61bc7a4", 9 | "sha": "61bc7a4455c49d47b0e288848e72ccd5778a7470", 10 | "checkver": { 11 | "type": "sha", 12 | "repo": "Zie619/n8n-workflows" 13 | }, 14 | "docker": { 15 | "labels": { 16 | "author": "Zie619" 17 | } 18 | } 19 | } 20 | } 21 | } -------------------------------------------------------------------------------- /apps/yulegeyu/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM alpine/git AS source 2 | WORKDIR /app 3 | ARG VERSION=4b9de83 4 | RUN git clone https://github.com/liyupi/yulegeyu . && git checkout ${VERSION} 5 | 6 | FROM node:20.10.0-alpine AS build 7 | WORKDIR /app 8 | 9 | COPY --from=source /app . 10 | RUN yarn install --frozen-lockfile --network-timeout 600000 11 | RUN yarn run build 12 | 13 | FROM aliuq/nginx:vue 14 | 15 | ENV TZ=Asia/Shanghai 16 | ENV NODE_ENV=production 17 | 18 | WORKDIR /app 19 | 20 | COPY --from=build /app/dist /app 21 | 22 | CMD ["nginx", "-g", "daemon off;"] 23 | EXPOSE 80 24 | -------------------------------------------------------------------------------- /apps/icones/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM alpine/git AS source 2 | WORKDIR /app 3 | ARG VERSION=fb6710e 4 | RUN git clone https://github.com/antfu-collective/icones . && git checkout ${VERSION} 5 | 6 | FROM node:22.14.0-alpine3.20 AS build 7 | WORKDIR /app 8 | COPY --from=source /app . 9 | RUN corepack enable && corepack prepare --activate 10 | RUN pnpm install && pnpm run build 11 | 12 | FROM aliuq/nginx:vue 13 | 14 | ENV TZ=Asia/Shanghai 15 | ENV NODE_ENV=production 16 | 17 | WORKDIR /app 18 | 19 | COPY --from=build /app/dist /app 20 | 21 | CMD ["nginx", "-g", "daemon off;"] 22 | EXPOSE 80 23 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "apps-image", 3 | "version": "1.0.0", 4 | "private": true, 5 | "description": "A collection of Docker images for various applications", 6 | "main": "index.js", 7 | "workspaces": [ 8 | "action" 9 | ], 10 | "scripts": { 11 | "lint": "eslint .", 12 | "eslint:inspect": "bunx @eslint/config-inspector --config eslint.config.mjs", 13 | "manifest": "bun run --cwd=action src/manifest.ts" 14 | }, 15 | "devDependencies": { 16 | "@antfu/eslint-config": "^5.2.1", 17 | "eslint": "^9.33.0", 18 | "fast-glob": "^3.3.3" 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /action/resolve-meta/action.yml: -------------------------------------------------------------------------------- 1 | name: Action 2 | author: AliuQ 3 | description: Action for aliuq/apps-image repository 4 | inputs: 5 | context: 6 | description: 'Context directory, only works on resolve-meta, e.g. apps/tgcf' 7 | required: false 8 | variants: 9 | description: 'Variants to build, e.g. latest,dev' 10 | required: false 11 | default: '' 12 | debug: 13 | description: Debug mode 14 | required: false 15 | default: 'false' 16 | 17 | runs: 18 | using: node20 19 | main: ../dist/metadata.js 20 | 21 | branding: 22 | icon: message-square 23 | color: blue 24 | -------------------------------------------------------------------------------- /apps/memogram/meta.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "memogram", 3 | "type": "app", 4 | "title": "Memogram", 5 | "slogan": "Memos 的 Telegram 机器人集成", 6 | "description": "Memogram is an easy to use integration service for syncing messages and images from a Telegram bot into your Memos.", 7 | "license": "Custom properties", 8 | "variants": { 9 | "latest": { 10 | "version": "0.3.0", 11 | "sha": "316ea40c31bd83e7acdaafd80507e8e4e086f686", 12 | "checkver": { 13 | "type": "tag", 14 | "repo": "https://github.com/usememos/telegram-integration" 15 | } 16 | } 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /deprecated/filecodebox/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM alpine/git AS source 2 | WORKDIR /app 3 | RUN git clone https://github.com/vastsa/FileCodeBox.git . 4 | 5 | FROM python:3.9.5-slim-buster AS builder 6 | WORKDIR /app 7 | 8 | COPY --from=source /app/requirements.txt ./requirements.txt 9 | RUN python -m venv /venv && \ 10 | /venv/bin/pip install --no-cache-dir -r requirements.txt 11 | 12 | FROM python:3.9.5-slim-buster 13 | WORKDIR /app 14 | 15 | ENV PATH="/venv/bin:$PATH" 16 | ENV TZ=Asia/Shanghai 17 | 18 | COPY --from=source /app . 19 | COPY --from=builder /venv /venv 20 | 21 | CMD ["python", "main.py"] 22 | 23 | VOLUME /app/data 24 | EXPOSE 12345 25 | -------------------------------------------------------------------------------- /apps/cobalt/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM alpine/git AS source 2 | WORKDIR /app 3 | ARG VERSION=e4b5388 4 | RUN git clone https://github.com/imputnet/cobalt . && git checkout ${VERSION} 5 | 6 | FROM node:23-alpine AS builder 7 | WORKDIR /app 8 | COPY --from=source /app . 9 | RUN corepack enable && corepack prepare --activate 10 | RUN pnpm install --frozen-lockfile 11 | RUN WEB_DEFAULT_API=\$BASE_API pnpm -C web build 12 | 13 | FROM aliuq/nginx:svelte 14 | 15 | ENV BASE_API="https://api.cobalt.tools" 16 | 17 | COPY --from=builder /app/web/build /app 18 | COPY ./docker-entrypoint.sh /docker-entrypoint.d/00-replace-envs.sh 19 | RUN chmod +x /docker-entrypoint.d/00-replace-envs.sh 20 | -------------------------------------------------------------------------------- /apps/jsonhero-web/meta.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "jsonhero-web", 3 | "type": "app", 4 | "title": "Jsonhero Web", 5 | "slogan": "Web JSON 浏览器,快速浏览和搜索 JSON", 6 | "description": "JSON Hero is an open-source, beautiful JSON explorer for the web that lets you browse, search and navigate your JSON files at speed. 🚀. Built with 💜 by the Trigger.dev team.", 7 | "license": "Apache-2.0", 8 | "variants": { 9 | "latest": { 10 | "version": "1515705", 11 | "sha": "15157053174ba7a0a79c77b2925fbde7e05a6334", 12 | "checkver": { 13 | "type": "sha", 14 | "repo": "https://github.com/triggerdotdev/jsonhero-web" 15 | } 16 | } 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /apps/memogram/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM alpine/git AS source 2 | WORKDIR /app 3 | ARG VERSION=v0.3.0 4 | RUN git clone --branch ${VERSION} https://github.com/usememos/telegram-integration . 5 | 6 | # Build stage 7 | FROM cgr.dev/chainguard/go:latest AS builder 8 | WORKDIR /app 9 | COPY --from=source /app/go.mod ./ 10 | COPY --from=source /app/go.sum ./ 11 | RUN go mod download 12 | COPY --from=source /app . 13 | RUN CGO_ENABLED=0 go build -o memogram ./bin/memogram 14 | RUN chmod +x memogram 15 | 16 | # Run stage 17 | FROM cgr.dev/chainguard/static:latest-glibc 18 | WORKDIR /app 19 | COPY --from=source /app/.env.example .env 20 | COPY --from=builder /app/memogram . 21 | CMD ["./memogram"] 22 | -------------------------------------------------------------------------------- /test/weektodo/meta.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "weektodo", 3 | "type": "app", 4 | "title": "WeekToDo | FOSS Minimalist Weekly Planner", 5 | "description": "WeekToDo is a Free and Open Source Minimalist Weekly Planner and To Do list App focused on privacy. Available for Windows, Mac, Linux or online.", 6 | "license": "GPL-3.0 license", 7 | "context": "apps/weektodo", 8 | "variants": { 9 | "latest": { 10 | "version": "2.2.0", 11 | "sha": "0296d299bd819e5cf31cf993bad9482fd7787981", 12 | "checkver": { 13 | "repo": "manuelernestog/weektodo", 14 | "type": "version", 15 | "file": "package.json" 16 | } 17 | } 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /apps/weektodo/meta.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "weektodo", 3 | "type": "app", 4 | "title": "WeekToDo | FOSS Minimalist Weekly Planner", 5 | "slogan": "每周任务管理工具,高效规划待办事项", 6 | "description": "WeekToDo is a Free and Open Source Minimalist Weekly Planner and To Do list App focused on privacy. Available for Windows, Mac, Linux or online.", 7 | "license": "GPL-3.0 license", 8 | "variants": { 9 | "latest": { 10 | "version": "2.2.0", 11 | "sha": "0296d299bd819e5cf31cf993bad9482fd7787981", 12 | "checkver": { 13 | "type": "version", 14 | "repo": "https://github.com/manuelernestog/weektodo", 15 | "file": "package.json" 16 | } 17 | } 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /apps/telemirror/Dockerfile.stable: -------------------------------------------------------------------------------- 1 | FROM alpine/git AS base 2 | WORKDIR /app 3 | RUN git clone https://github.com/khoben/telemirror . && git checkout {{sha}} 4 | 5 | FROM python:3.11-slim-bullseye AS build 6 | 7 | ENV PIP_NO_CACHE_DIR=1 8 | 9 | WORKDIR /app 10 | COPY --from=base /app/requirements.txt /app/requirements.txt 11 | RUN pip install --target=/app/dependencies -r requirements.txt 12 | 13 | FROM build AS release 14 | 15 | RUN useradd -m apprunner 16 | USER apprunner 17 | 18 | ENV PYTHONUNBUFFERED=1 19 | 20 | WORKDIR /app 21 | COPY --from=base --chown=apprunner: /app /app 22 | 23 | ENV PYTHONPATH="${PYTHONPATH}:/app/dependencies" 24 | 25 | ARG PORT=8000 26 | EXPOSE ${PORT} 27 | 28 | CMD ["python", "main.py"] 29 | -------------------------------------------------------------------------------- /apps/cobalt/meta.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "cobalt", 3 | "type": "app", 4 | "title": "Cobalt", 5 | "slogan": "媒体下载器,支持多平台视频/音频下载", 6 | "description": "best way to save what you love", 7 | "license": "AGPL-3.0", 8 | "variants": { 9 | "latest": { 10 | "version": "11.3", 11 | "sha": "e4b53880af4026b8be6a870ae7d8133f744a6181", 12 | "checkver": { 13 | "type": "version", 14 | "repo": "https://github.com/imputnet/cobalt", 15 | "file": "web/package.json" 16 | }, 17 | "docker": { 18 | "tags": [ 19 | "type=raw,value=latest", 20 | "type=raw,value={{version}}", 21 | "type=raw,value={{major}}" 22 | ] 23 | } 24 | } 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /.github/instructions/action.instructions.md: -------------------------------------------------------------------------------- 1 | --- 2 | applyTo: '**' 3 | --- 4 | 5 | 这是一个 GitHub Action,用于自动化处理应用镜像的版本更新和 PR 创建。它支持多种应用和变体,并提供灵活的模板系统来生成 PR 标题和内容 6 | 7 | ## Code Standards 8 | 9 | 工作目录: `action/` 10 | 11 | ### Required Before Each Commit 12 | 13 | - 确保代码符合 TypeScript 和 ESLint 规范 14 | - 运行 `bun run lint` 检查代码风格 15 | - 使用 [`@actions/toolkit`](https://github.com/actions/toolkit) 提供的工具来处理相关的 GitHub Action 功能 16 | - 类型约束在 `.vscode/meta.schema.json` 中定义,确保代码符合预期的结构和类型 17 | 18 | ## Development Flow 19 | 20 | - 安装依赖: `bun install` 21 | - 开发服务器: `bun run --filter action dev` 22 | - 构建: `bun run --filter build` 23 | - Lint: `bun run lint` 24 | 25 | ## Key Guidelines 26 | 27 | - 代码应具有良好的可读性和一致的风格 28 | - 使用 TypeScript 的类型系统来增强代码的可维护性 29 | -------------------------------------------------------------------------------- /action/check-version/action.yml: -------------------------------------------------------------------------------- 1 | name: Action 2 | author: AliuQ 3 | description: 检查版本更新的 GitHub Action 4 | inputs: 5 | token: 6 | description: Personal Access Token (PAT) for the repository 7 | required: false 8 | context: 9 | description: 'Context directory, only works on resolve-meta, e.g. apps/tgcf' 10 | required: false 11 | create_pr: 12 | description: Create a PR if the version is outdated, supports `true`, `false`, and `development` 13 | required: false 14 | default: 'false' 15 | debug: 16 | description: Debug mode 17 | required: false 18 | default: 'false' 19 | 20 | runs: 21 | using: node20 22 | main: ../dist/check.js 23 | 24 | branding: 25 | icon: message-square 26 | color: blue 27 | -------------------------------------------------------------------------------- /apps/telemirror/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM alpine/git AS base 2 | WORKDIR /app 3 | ARG VERSION=21930b5 4 | RUN git clone https://github.com/khoben/telemirror . && git checkout ${VERSION} 5 | 6 | FROM python:3.11-slim-bullseye AS build 7 | 8 | ENV PIP_NO_CACHE_DIR=1 9 | 10 | WORKDIR /app 11 | COPY --from=base /app/requirements.txt /app/requirements.txt 12 | RUN pip install --target=/app/dependencies -r requirements.txt 13 | 14 | FROM build AS release 15 | 16 | RUN useradd -m apprunner 17 | USER apprunner 18 | 19 | ENV PYTHONUNBUFFERED=1 20 | 21 | WORKDIR /app 22 | COPY --from=base --chown=apprunner: /app /app 23 | 24 | ENV PYTHONPATH="${PYTHONPATH}:/app/dependencies" 25 | 26 | ARG PORT=8000 27 | EXPOSE ${PORT} 28 | 29 | CMD ["python", "main.py"] 30 | -------------------------------------------------------------------------------- /deprecated/filecodebox/meta.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "filecodebox", 3 | "type": "app", 4 | "version": "bdab5bb", 5 | "repo": "https://github.com/vastsa/FileCodeBox", 6 | "sha": "bdab5bb375f39de720e27b7282e7b2c1442afd5b", 7 | "checkVer": { 8 | "type": "sha" 9 | }, 10 | "dockerMeta": { 11 | "images": [ 12 | "aliuq/filecodebox", 13 | "ghcr.io/aliuq/filecodebox" 14 | ], 15 | "tags": [ 16 | "type=raw,value=latest", 17 | "type=raw,value=bdab5bb" 18 | ], 19 | "context": "apps/filecodebox", 20 | "dockerfile": "Dockerfile", 21 | "platforms": [], 22 | "push": true, 23 | "labels": { 24 | "title": "FileCodeBox", 25 | "description": "文件快递柜-匿名口令分享文本,文件,像拿快递一样取文件", 26 | "licenses": "LGPL-3.0" 27 | } 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /deprecated/filecodebox/README.md: -------------------------------------------------------------------------------- 1 | # filecodebox 2 | 3 | **弃用**: 不再更新,请使用官方镜像 [`lanol/filecodebox:beta`](https://hub.docker.com/r/lanol/filecodebox/tags) 4 | 5 | + [Dockerfile](https://github.com/aliuq/apps-image/tree/master/apps/filecodebox) 6 | + 上游仓库: 7 | 8 | > 官方 beta 镜像已经包含有最新主题,请使用官方镜像 9 | 10 | + 镜像地址: 11 | + 最新版本: `lanol/filecodebox:beta` 12 | + 默认密码: `FileCodeBox2023` 13 | 14 | ## 构建镜像 15 | 16 | ```bash 17 | docker buildx build -f ./Dockerfile -t filecodebox:0.0.1 --no-cache --load . 18 | docker buildx build --progress=plain -f ./Dockerfile -t filecodebox:0.0.1 --no-cache --load . 19 | ``` 20 | 21 | ## 运行 22 | 23 | ```bash 24 | docker run -it --rm --name filecodebox -p 12345:12345 filecodebox:0.0.1 25 | ``` 26 | -------------------------------------------------------------------------------- /test/icones/meta.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "icones", 3 | "type": "app", 4 | "title": "Icones", 5 | "description": "Icon Explorer with Instant searching, powered by Iconify", 6 | "license": "MIT", 7 | "context": "apps/icones", 8 | "variants": { 9 | "latest": { 10 | "version": "d96ef28", 11 | "sha": "d96ef283218ee96ea92e55f981a14504bd90a331", 12 | "checkver": { 13 | "repo": "https://github.com/antfu-collective/icones", 14 | "type": "sha" 15 | }, 16 | "docker": { 17 | "images": [ 18 | "aliuq/icones", 19 | "ghcr.io/aliuq/icones" 20 | ], 21 | "tags": [ 22 | "type=raw,value=latest", 23 | "type=raw,value={{version}}", 24 | "type=raw,value={{sha}}" 25 | ] 26 | } 27 | } 28 | } 29 | } -------------------------------------------------------------------------------- /deprecated/tgcf-multx-01/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM alpine/git AS source 2 | WORKDIR /app 3 | RUN git clone -b multx-01 https://github.com/aahnik/tgcf.git . 4 | 5 | FROM python:3.10-slim-bullseye AS builder 6 | WORKDIR /app 7 | COPY --from=source /app . 8 | RUN pip install --no-cache-dir poetry && \ 9 | python -m venv /venv && \ 10 | poetry build && \ 11 | /venv/bin/pip install --no-cache-dir dist/*.whl 12 | 13 | FROM python:3.10-slim-bullseye 14 | WORKDIR /app 15 | ENV VENV_PATH="/venv" 16 | ENV PATH="$VENV_PATH/bin:$PATH" 17 | 18 | RUN apt-get update && \ 19 | apt-get install -y --no-install-recommends \ 20 | ffmpeg \ 21 | tesseract-ocr && \ 22 | apt-get clean && \ 23 | rm -rf /var/lib/apt/lists/* 24 | 25 | COPY --from=builder /venv /venv 26 | 27 | CMD ["tgcf-web"] 28 | 29 | EXPOSE 8501 30 | -------------------------------------------------------------------------------- /deprecated/tgcf/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM alpine/git AS source 2 | WORKDIR /app 3 | RUN git clone https://github.com/aahnik/tgcf.git . && git checkout f0d5859 4 | 5 | FROM python:3.10-slim-bullseye AS builder 6 | WORKDIR /app 7 | COPY --from=source /app . 8 | RUN pip install --no-cache-dir poetry && \ 9 | python -m venv /venv && \ 10 | poetry build && \ 11 | /venv/bin/pip install --no-cache-dir dist/*.whl 12 | 13 | FROM python:3.10-slim-bullseye 14 | WORKDIR /app 15 | ENV VENV_PATH="/venv" 16 | ENV PATH="$VENV_PATH/bin:$PATH" 17 | 18 | RUN apt-get update && \ 19 | apt-get install -y --no-install-recommends \ 20 | ffmpeg \ 21 | tesseract-ocr && \ 22 | apt-get clean && \ 23 | rm -rf /var/lib/apt/lists/* 24 | 25 | COPY --from=builder /venv /venv 26 | 27 | CMD ["tgcf-web"] 28 | 29 | EXPOSE 8501 30 | -------------------------------------------------------------------------------- /apps/srcbook/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM node:22.7.0-alpine3.20 AS builder 2 | WORKDIR /app 3 | 4 | RUN yarn add srcbook@0.0.19 && \ 5 | rm -rf package* yarn* && \ 6 | cp -R ./node_modules/srcbook/dist . && \ 7 | cp -R ./node_modules/srcbook/public . && \ 8 | cp -R ./node_modules/srcbook/package.json . && \ 9 | rm -rf ./node_modules && \ 10 | yarn install --prod 11 | 12 | RUN echo "#!/usr/bin/env node" > /srcbook && \ 13 | echo "import program from '/app/dist/src/cli.mjs';" >> /srcbook && \ 14 | echo "program();" >> /srcbook 15 | 16 | FROM node:22.7.0-alpine3.20 17 | 18 | WORKDIR /app 19 | COPY --from=builder /app . 20 | COPY --from=builder /srcbook /usr/local/bin/srcbook 21 | 22 | RUN chmod +x /usr/local/bin/srcbook 23 | 24 | CMD ["srcbook", "start"] 25 | 26 | EXPOSE 2150 27 | VOLUME /root/.srcbook 28 | VOLUME /root/.npm 29 | -------------------------------------------------------------------------------- /apps/telegram-upload/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM alpine/git AS source 2 | WORKDIR /app 3 | ARG VERSION=c700f86 4 | RUN git clone https://github.com/Nekmo/telegram-upload . && git checkout ${VERSION} 5 | 6 | FROM python:3.9.7-slim-bullseye AS build 7 | WORKDIR /app 8 | RUN python -m venv /venv 9 | ENV PATH="/venv/bin:$PATH" 10 | 11 | COPY --from=source /app/requirements.txt ./requirements.txt 12 | RUN pip install --no-cache-dir -r requirements.txt 13 | 14 | FROM python:3.9.7-slim-bullseye 15 | WORKDIR /app 16 | RUN python -m venv /venv 17 | ENV PATH="/venv/bin:$PATH" 18 | ENV TELEGRAM_UPLOAD_CONFIG_DIRECTORY=/config 19 | ENV PYTHONPATH=/app/ 20 | 21 | COPY --from=source /app/telegram_upload /app/telegram_upload 22 | COPY --from=build /venv /venv 23 | 24 | ENTRYPOINT ["python", "/app/telegram_upload/management.py"] 25 | 26 | VOLUME /config 27 | VOLUME /files 28 | -------------------------------------------------------------------------------- /apps/cobalt/docker-entrypoint.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | set -e 4 | 5 | ME=$(basename "$0") 6 | 7 | entrypoint_log() { 8 | if [ -z "${NGINX_ENTRYPOINT_QUIET_LOGS:-}" ]; then 9 | echo "$@" 10 | fi 11 | } 12 | 13 | auto_envsubst() { 14 | local filter="${NGINX_ENVSUBST_FILTER:-}" 15 | 16 | defined_envs=$(printf '${%s} ' $(awk "END { for (name in ENVIRON) { print ( name ~ /${filter}/ ) ? name : \"\" } }" "$template.1" 25 | mv "$template.1" "$template" 26 | done 27 | } 28 | 29 | auto_envsubst 30 | 31 | exit 0 32 | -------------------------------------------------------------------------------- /deprecated/tgcf/Dockerfile.multx-01: -------------------------------------------------------------------------------- 1 | FROM alpine/git as base 2 | WORKDIR /app 3 | RUN git clone -b multx-01 https://github.com/aahnik/tgcf.git . 4 | 5 | FROM python:3.10-slim-bullseye 6 | 7 | LABEL version="0.0.5" 8 | LABEL repository="https://github.com/aahnik/tgcf" 9 | 10 | ENV VENV_PATH="/venv" 11 | ENV PATH="$VENV_PATH/bin:$PATH" 12 | 13 | WORKDIR /app 14 | RUN apt-get update && \ 15 | apt-get install -y --no-install-recommends apt-utils && \ 16 | apt-get upgrade -y && \ 17 | apt-get install ffmpeg tesseract-ocr -y && \ 18 | apt-get autoclean && \ 19 | rm -rf /var/lib/apt/lists/* 20 | 21 | RUN pip install --upgrade poetry 22 | RUN python -m venv /venv 23 | COPY --from=base /app . 24 | RUN poetry build && \ 25 | /venv/bin/pip install --upgrade pip wheel setuptools && \ 26 | /venv/bin/pip install dist/*.whl 27 | 28 | EXPOSE 8501 29 | 30 | CMD tgcf-web 31 | -------------------------------------------------------------------------------- /apps/n8n-workflows/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM alpine/git AS source 2 | WORKDIR /app 3 | ARG VERSION=61bc7a4 4 | RUN git clone https://github.com/Zie619/n8n-workflows . && git checkout ${VERSION} 5 | 6 | FROM python:3.11-slim-bookworm AS base 7 | WORKDIR /app 8 | ENV PATH="/opt/venv/bin:$PATH" 9 | 10 | FROM base AS builder 11 | WORKDIR /app 12 | RUN python -m venv /opt/venv 13 | COPY --from=source /app/requirements.txt . 14 | RUN apt-get update && \ 15 | apt-get install -y gcc python3-dev ca-certificates && \ 16 | apt-get clean && rm -rf /var/lib/apt/lists/* 17 | 18 | RUN pip install --no-cache-dir --upgrade pip && \ 19 | pip install --no-cache-dir -r requirements.txt 20 | 21 | FROM base 22 | WORKDIR /app 23 | COPY --from=builder /opt/venv /opt/venv 24 | COPY --from=source /app . 25 | ENTRYPOINT ["python", "run.py", "--host", "0.0.0.0", "--port", "8000"] 26 | 27 | EXPOSE 8000 28 | -------------------------------------------------------------------------------- /deprecated/tgcf/meta.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "tgcf", 3 | "type": "app", 4 | "version": "f0d5859", 5 | "repo": "https://github.com/aahnik/tgcf", 6 | "sha": "f0d5859acfda4aa234d3c5316f14eb3b38e5f7ce", 7 | "checkVer": { 8 | "type": "sha" 9 | }, 10 | "dockerMeta": { 11 | "images": [ 12 | "aliuq/tgcf", 13 | "ghcr.io/aliuq/tgcf" 14 | ], 15 | "tags": [ 16 | "type=raw,value=latest", 17 | "type=raw,value=f0d5859" 18 | ], 19 | "context": "apps/tgcf", 20 | "dockerfile": "Dockerfile", 21 | "platforms": [], 22 | "push": true, 23 | "labels": { 24 | "title": "tgcf", 25 | "description": "The ultimate tool to automate custom telegram message forwarding. Live-syncer, Auto-poster, backup-bot, cloner, chat-forwarder, duplicator, ... Call it whatever you like! tgcf can fulfill your custom needs.", 26 | "licenses": "MIT" 27 | } 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /test/weektodo-mul/meta.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "weektodo-mul", 3 | "type": "app", 4 | "title": "WeekToDo | FOSS Minimalist Weekly Planner", 5 | "description": "WeekToDo is a Free and Open Source Minimalist Weekly Planner and To Do list App focused on privacy. Available for Windows, Mac, Linux or online.", 6 | "license": "GPL-3.0 license", 7 | "context": "test/weektodo-mul", 8 | "variants": { 9 | "latest": { 10 | "version": "2.2.0", 11 | "sha": "0296d299bd819e5cf31cf993bad9482fd7787981", 12 | "checkver": { 13 | "repo": "manuelernestog/weektodo", 14 | "type": "version", 15 | "file": "package.json" 16 | } 17 | }, 18 | "dev": { 19 | "version": "d384fc7", 20 | "sha": "d384fc72d04e9c8a8431d456a3218c08d0c77e29", 21 | "checkver": { 22 | "repo": "manuelernestog/weektodo", 23 | "type": "sha" 24 | } 25 | } 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /apps/lsky/docker-entrypoint.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | set -e 4 | 5 | ME=$(basename "$0") 6 | 7 | if [ ! -z "$UPLOAD_MAX_FILESIZE" ]; then 8 | sed -i "s/upload_max_filesize = .*/upload_max_filesize = $UPLOAD_MAX_FILESIZE/g" $PHP_INI_DIR/php.ini 9 | echo "$ME: Set upload_max_filesize to $UPLOAD_MAX_FILESIZE" 10 | fi 11 | 12 | if [ ! -z "$POST_MAX_SIZE" ]; then 13 | sed -i "s/post_max_size = .*/post_max_size = $POST_MAX_SIZE/g" $PHP_INI_DIR/php.ini 14 | echo "$ME: Set post_max_size to $POST_MAX_SIZE" 15 | fi 16 | 17 | if [ ! -d "/app" ] || [ -z "$(ls -A /app)" ]; then 18 | tar -xzf /tmp/app.tar.gz -C /app 19 | chmod -R 777 /app 20 | echo "$ME: Extracted /tmp/app.tar.gz to /app" 21 | fi 22 | 23 | if [ ! -d "/etc/nginx" ] || [ -z "$(ls -A /etc/nginx)" ]; then 24 | tar -xzf /tmp/nginx.tar.gz -C / 25 | chmod -R 777 /etc/nginx 26 | echo "$ME: Extracted /tmp/nginx.tar.gz to /etc/nginx" 27 | fi 28 | 29 | php-fpm -D 30 | -------------------------------------------------------------------------------- /apps/srcbook/Dockerfile.tls: -------------------------------------------------------------------------------- 1 | FROM node:22.7.0-alpine3.20 AS builder 2 | WORKDIR /app 3 | 4 | RUN yarn add srcbook@0.0.19 && \ 5 | rm -rf package* yarn* && \ 6 | cp -R ./node_modules/srcbook/dist . && \ 7 | cp -R ./node_modules/srcbook/public . && \ 8 | cp -R ./node_modules/srcbook/package.json . && \ 9 | rm -rf ./node_modules && \ 10 | yarn install --prod 11 | 12 | # Fix ws:// to wss:// in the frontend 13 | RUN find ./public -type f -name "*.js" -exec sed -i 's/ws:\/\//wss:\/\//g' {} + 14 | 15 | RUN echo "#!/usr/bin/env node" > /srcbook && \ 16 | echo "import program from '/app/dist/src/cli.mjs';" >> /srcbook && \ 17 | echo "program();" >> /srcbook 18 | 19 | FROM node:22.7.0-alpine3.20 20 | 21 | WORKDIR /app 22 | COPY --from=builder /app . 23 | COPY --from=builder /srcbook /usr/local/bin/srcbook 24 | 25 | RUN chmod +x /usr/local/bin/srcbook 26 | 27 | CMD ["srcbook", "start"] 28 | 29 | EXPOSE 2150 30 | VOLUME /root/.srcbook 31 | VOLUME /root/.npm 32 | -------------------------------------------------------------------------------- /deprecated/tgcf-multx-01/meta.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "tgcf-multx-01", 3 | "type": "app", 4 | "version": "08b811f", 5 | "repo": "https://github.com/aahnik/tgcf", 6 | "sha": "08b811f2126f1dbc42a09e11879cb23ee12cb77e", 7 | "branch": "multx-01", 8 | "checkVer": { 9 | "type": "sha" 10 | }, 11 | "dockerMeta": { 12 | "images": [ 13 | "aliuq/tgcf", 14 | "ghcr.io/aliuq/tgcf" 15 | ], 16 | "tags": [ 17 | "type=raw,value=multx-01", 18 | "type=raw,value=08b811f-multx-01" 19 | ], 20 | "context": "apps/tgcf-multx-01", 21 | "dockerfile": "Dockerfile", 22 | "platforms": [], 23 | "push": true, 24 | "labels": { 25 | "title": "tgcf", 26 | "description": "The ultimate tool to automate custom telegram message forwarding. Live-syncer, Auto-poster, backup-bot, cloner, chat-forwarder, duplicator, ... Call it whatever you like! tgcf can fulfill your custom needs.", 27 | "licenses": "MIT" 28 | } 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /apps/lsky/default.conf: -------------------------------------------------------------------------------- 1 | server { 2 | listen 80; 3 | server_name localhost; 4 | root /app/public; 5 | 6 | add_header X-Frame-Options "SAMEORIGIN"; 7 | add_header X-XSS-Protection "1; mode=block"; 8 | add_header X-Content-Type-Options "nosniff"; 9 | 10 | index index.php; 11 | 12 | charset utf-8; 13 | 14 | location / { 15 | try_files $uri $uri/ /index.php?$query_string; 16 | } 17 | 18 | location = /favicon.ico { access_log off; log_not_found off; } 19 | location = /robots.txt { access_log off; log_not_found off; } 20 | 21 | error_page 404 /index.php; 22 | 23 | location ~ \.php$ { 24 | fastcgi_split_path_info ^(.+\.php)(/.+)$; 25 | fastcgi_pass 127.0.0.1:9000; 26 | fastcgi_index index.php; 27 | fastcgi_param SCRIPT_FILENAME $realpath_root$fastcgi_script_name; 28 | include fastcgi_params; 29 | } 30 | 31 | location ~ /\.(?!well-known) { 32 | deny all; 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /apps/telemirror/meta.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "telemirror", 3 | "type": "app", 4 | "title": "Telemirror", 5 | "slogan": "Telegram 消息镜像转发工具", 6 | "description": "Telegram message forwarder (client API)", 7 | "license": "GPL-3.0", 8 | "variants": { 9 | "latest": { 10 | "version": "21930b5", 11 | "sha": "21930b5a7f13c563051391d4a327155961885ddd", 12 | "checkver": { 13 | "type": "sha", 14 | "repo": "khoben/telemirror" 15 | }, 16 | "docker": { 17 | "tags": [ 18 | "type=raw,value=latest", 19 | "type=raw,value={{version}}" 20 | ] 21 | } 22 | }, 23 | "stable": { 24 | "enabled": false, 25 | "checkver": { 26 | "type": "tag", 27 | "repo": "khoben/telemirror" 28 | }, 29 | "docker": { 30 | "tags": [ 31 | "type=raw,value=stable", 32 | "type=raw,value={{version}}", 33 | "type=raw,value=stable-{{sha}}" 34 | ] 35 | } 36 | } 37 | } 38 | } -------------------------------------------------------------------------------- /base/vscode/meta.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "vscode", 3 | "type": "base", 4 | "description": "Visual Studio Code is a free source-code editor made by Microsoft for Windows, Linux and macOS.", 5 | "license": "MIT", 6 | "variants": { 7 | "latest": { 8 | "version": "1.107.0", 9 | "sha": "302ff6a2e235c95b88e587d4a4b6eeb1b6613297", 10 | "checkver": { 11 | "type": "tag", 12 | "repo": "microsoft/vscode" 13 | }, 14 | "docker": { 15 | "tags": [ 16 | "type=raw,value=latest", 17 | "type=raw,value={{version}}" 18 | ] 19 | } 20 | }, 21 | "stable": { 22 | "version": "1.107.0", 23 | "sha": "302ff6a2e235c95b88e587d4a4b6eeb1b6613297", 24 | "checkver": { 25 | "type": "tag", 26 | "repo": "microsoft/vscode" 27 | }, 28 | "docker": { 29 | "tags": [ 30 | "type=raw,value=stable", 31 | "type=raw,value={{version}}-stable" 32 | ] 33 | } 34 | } 35 | } 36 | } -------------------------------------------------------------------------------- /base/self/meta.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "self", 3 | "type": "base", 4 | "title": "Personal Development Environment", 5 | "description": "个人开发环境基础镜像,集成 Node.js、Python、Zsh、Oh-my-zsh、Starship 等开发工具", 6 | "license": "MIT", 7 | "variants": { 8 | "latest": { 9 | "version": "0.1.0", 10 | "sha": "162984856e9b0390bfda8b5e20edeea665582b1b", 11 | "checkver": { 12 | "type": "manual" 13 | }, 14 | "docker": { 15 | "tags": [ 16 | "type=raw,value=latest", 17 | "type=raw,value=alpine", 18 | "type=raw,value={{version}}" 19 | ] 20 | } 21 | }, 22 | "ubuntu": { 23 | "version": "0.1.0", 24 | "sha": "162984856e9b0390bfda8b5e20edeea665582b1b", 25 | "enabled": false, 26 | "checkver": { 27 | "type": "manual" 28 | }, 29 | "docker": { 30 | "tags": [ 31 | "type=raw,value=ubuntu", 32 | "type=raw,value={{version}}-ubuntu" 33 | ] 34 | } 35 | } 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /apps/readest/meta.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "readest", 3 | "type": "app", 4 | "title": "Readest", 5 | "slogan": "现代化的电子书阅读器,优雅的阅读体验", 6 | "description": "Readest 是一款现代化、功能丰富的电子书阅读器", 7 | "license": "AGPL-3.0", 8 | "variants": { 9 | "latest": { 10 | "version": "0.9.93", 11 | "sha": "721e70d0271fc9997bd0d60fe6d844b38f86fc5b", 12 | "checkver": { 13 | "type": "tag", 14 | "repo": "https://github.com/readest/readest" 15 | } 16 | }, 17 | "test": { 18 | "version": "0.9.88", 19 | "sha": "05e9549410bb3ba8e26b5dee3a1472b3a8fcd1b0", 20 | "enabled": false, 21 | "checkver": { 22 | "type": "tag", 23 | "repo": "readest/readest" 24 | }, 25 | "docker": { 26 | "file": "Dockerfile", 27 | "images": [ 28 | "aliuq/{name}" 29 | ], 30 | "tags": [ 31 | "type=raw,value=test" 32 | ], 33 | "platforms": [ 34 | "linux/amd64" 35 | ] 36 | } 37 | } 38 | } 39 | } -------------------------------------------------------------------------------- /apps/lsky/meta.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "lsky", 3 | "type": "app", 4 | "title": "兰空图床", 5 | "slogan": "兰空图床,轻量级图片云存储系统", 6 | "description": "兰空图床(Lsky Pro) - Your photo album on the cloud.", 7 | "license": "GPL-3.0", 8 | "variants": { 9 | "latest": { 10 | "version": "2.1", 11 | "sha": "923f567e0a93c7291c4c9fc5279da9847ed39f7e", 12 | "checkver": { 13 | "type": "tag", 14 | "repo": "https://github.com/lsky-org/lsky-pro" 15 | }, 16 | "docker": { 17 | "tags": [ 18 | "type=raw,value=latest", 19 | "type=raw,value={{version}}" 20 | ] 21 | } 22 | }, 23 | "dev": { 24 | "version": "38d52c4", 25 | "sha": "38d52c4609eb85236b45ac75acac2ced55174953", 26 | "checkver": { 27 | "type": "sha", 28 | "repo": "https://github.com/lsky-org/lsky-pro" 29 | }, 30 | "docker": { 31 | "tags": [ 32 | "type=raw,value=dev", 33 | "type=raw,value=dev-{{sha}}" 34 | ] 35 | } 36 | } 37 | } 38 | } -------------------------------------------------------------------------------- /apps/srcbook/meta.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "srcbook", 3 | "type": "app", 4 | "title": "SrcBook", 5 | "slogan": "TypeScript 笔记本,浏览器中运行 TS", 6 | "description": "TypeScript-centric app development platform: notebook and AI app builder", 7 | "license": "Apache-2.0", 8 | "variants": { 9 | "latest": { 10 | "version": "0.0.19", 11 | "sha": "0ba24b1ea83b0dd20137236ce9aebc3ff86bff37", 12 | "checkver": { 13 | "type": "version", 14 | "repo": "https://github.com/srcbookdev/srcbook", 15 | "file": "srcbook/package.json" 16 | } 17 | }, 18 | "tls": { 19 | "version": "0.0.19", 20 | "sha": "0ba24b1ea83b0dd20137236ce9aebc3ff86bff37", 21 | "checkver": { 22 | "type": "version", 23 | "repo": "https://github.com/srcbookdev/srcbook", 24 | "file": "srcbook/package.json" 25 | }, 26 | "docker": { 27 | "tags": [ 28 | "type=raw,value=tls", 29 | "type=raw,value={{version}}-tls" 30 | ] 31 | } 32 | } 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /apps/weserv/meta.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "weserv", 3 | "type": "app", 4 | "slogan": "wsrv.nl", 5 | "description": "weserv 是一个用于快速生成图像的 API", 6 | "variants": { 7 | "latest": { 8 | "version": "a4dd91e", 9 | "sha": "a4dd91e157258c0e01065348e1718aed1c5a8a36", 10 | "checkver": { 11 | "type": "sha", 12 | "repo": "weserv/images", 13 | "branch": "5.x" 14 | }, 15 | "docker": { 16 | "tags": [ 17 | "type=raw,value=latest", 18 | "type=raw,value=5.x", 19 | "type=raw,value={{version}}" 20 | ] 21 | } 22 | }, 23 | "alpine": { 24 | "version": "a4dd91e", 25 | "sha": "a4dd91e157258c0e01065348e1718aed1c5a8a36", 26 | "checkver": { 27 | "type": "sha", 28 | "repo": "weserv/images", 29 | "branch": "5.x" 30 | }, 31 | "docker": { 32 | "tags": [ 33 | "type=raw,value=alpine", 34 | "type=raw,value=5.x-alpine", 35 | "type=raw,value={{version}}-alpine" 36 | ] 37 | } 38 | } 39 | } 40 | } -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2024 AliuQ 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /test/self/meta.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "self", 3 | "type": "base", 4 | "title": "Personal Development Environment", 5 | "description": "个人开发环境基础镜像,集成 Node.js、Python、Zsh、Oh-my-zsh、Starship 等开发工具", 6 | "license": "MIT", 7 | "variants": { 8 | "latest": { 9 | "version": "0.0.5", 10 | "sha": "192b3fc26a9a6bd6a79df63570acefa7a4e6d4dd", 11 | "checkver": { 12 | "type": "manual" 13 | }, 14 | "docker": { 15 | "images": [ 16 | "aliuq/{{name}}", 17 | "ghcr.io/aliuq/{{name}}" 18 | ], 19 | "tags": [ 20 | "type=raw,value=latest", 21 | "type=raw,value=alpine", 22 | "type=raw,value={{version}}", 23 | "type=raw,value={{sha}}" 24 | ] 25 | } 26 | }, 27 | "ubuntu": { 28 | "enabled": false, 29 | "checkver": { 30 | "type": "manual" 31 | }, 32 | "docker": { 33 | "images": [ 34 | "aliuq/{{name}}", 35 | "ghcr.io/aliuq/{{name}}" 36 | ], 37 | "tags": [ 38 | "type=raw,value=ubuntu", 39 | "type=raw,value={{version}}", 40 | "type=raw,value={{sha}}" 41 | ] 42 | } 43 | } 44 | } 45 | } -------------------------------------------------------------------------------- /base/nginx/meta.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "nginx", 3 | "type": "base", 4 | "description": "Nginx with custom configuration, based on alpine. The root path is /app.", 5 | "variants": { 6 | "latest": { 7 | "version": "0.1.0", 8 | "sha": "363f047cd6f9f160cb6bb142afb8d14191aac07e", 9 | "checkver": { 10 | "type": "manual" 11 | }, 12 | "docker": { 13 | "tags": [ 14 | "type=raw,value=latest", 15 | "type=raw,value={{version}}" 16 | ] 17 | } 18 | }, 19 | "vue": { 20 | "version": "0.1.0", 21 | "sha": "363f047cd6f9f160cb6bb142afb8d14191aac07e", 22 | "checkver": { 23 | "type": "manual" 24 | }, 25 | "docker": { 26 | "tags": [ 27 | "type=raw,value=vue", 28 | "type=raw,value={{version}}-vue" 29 | ] 30 | } 31 | }, 32 | "svelte": { 33 | "version": "0.1.0", 34 | "sha": "363f047cd6f9f160cb6bb142afb8d14191aac07e", 35 | "checkver": { 36 | "type": "manual" 37 | }, 38 | "docker": { 39 | "tags": [ 40 | "type=raw,value=svelte", 41 | "type=raw,value={{version}}-svelte" 42 | ] 43 | } 44 | } 45 | } 46 | } -------------------------------------------------------------------------------- /base/nginx/conf/default.conf: -------------------------------------------------------------------------------- 1 | server { 2 | listen 80; 3 | server_name localhost; 4 | 5 | #access_log /var/log/nginx/host.access.log main; 6 | 7 | location / { 8 | root /app; 9 | index index.html index.htm; 10 | } 11 | 12 | #error_page 404 /404.html; 13 | 14 | # redirect server error pages to the static page /50x.html 15 | # 16 | error_page 500 502 503 504 /50x.html; 17 | location = /50x.html { 18 | root /app; 19 | } 20 | 21 | # proxy the PHP scripts to Apache listening on 127.0.0.1:80 22 | # 23 | #location ~ \.php$ { 24 | # proxy_pass http://127.0.0.1; 25 | #} 26 | 27 | # pass the PHP scripts to FastCGI server listening on 127.0.0.1:9000 28 | # 29 | #location ~ \.php$ { 30 | # root html; 31 | # fastcgi_pass 127.0.0.1:9000; 32 | # fastcgi_index index.php; 33 | # fastcgi_param SCRIPT_FILENAME /scripts$fastcgi_script_name; 34 | # include fastcgi_params; 35 | #} 36 | 37 | # deny access to .htaccess files, if Apache's document root 38 | # concurs with nginx's one 39 | # 40 | #location ~ /\.ht { 41 | # deny all; 42 | #} 43 | } 44 | 45 | -------------------------------------------------------------------------------- /base/nginx/conf/default.vue.conf: -------------------------------------------------------------------------------- 1 | server { 2 | listen 80; 3 | server_name localhost; 4 | 5 | #access_log /var/log/nginx/host.access.log main; 6 | 7 | location / { 8 | root /app; 9 | try_files $uri $uri/ /index.html; 10 | } 11 | 12 | #error_page 404 /404.html; 13 | 14 | # redirect server error pages to the static page /50x.html 15 | # 16 | error_page 500 502 503 504 /50x.html; 17 | location = /50x.html { 18 | root /app; 19 | } 20 | 21 | # proxy the PHP scripts to Apache listening on 127.0.0.1:80 22 | # 23 | #location ~ \.php$ { 24 | # proxy_pass http://127.0.0.1; 25 | #} 26 | 27 | # pass the PHP scripts to FastCGI server listening on 127.0.0.1:9000 28 | # 29 | #location ~ \.php$ { 30 | # root html; 31 | # fastcgi_pass 127.0.0.1:9000; 32 | # fastcgi_index index.php; 33 | # fastcgi_param SCRIPT_FILENAME /scripts$fastcgi_script_name; 34 | # include fastcgi_params; 35 | #} 36 | 37 | # deny access to .htaccess files, if Apache's document root 38 | # concurs with nginx's one 39 | # 40 | #location ~ /\.ht { 41 | # deny all; 42 | #} 43 | } 44 | 45 | -------------------------------------------------------------------------------- /base/nginx/conf/default.svelte.conf: -------------------------------------------------------------------------------- 1 | server { 2 | listen 80; 3 | server_name localhost; 4 | 5 | #access_log /var/log/nginx/host.access.log main; 6 | 7 | location / { 8 | root /app; 9 | try_files $uri $uri/ $uri/index.html $uri.html /index.html; 10 | } 11 | 12 | #error_page 404 /404.html; 13 | 14 | # redirect server error pages to the static page /50x.html 15 | # 16 | error_page 500 502 503 504 /50x.html; 17 | location = /50x.html { 18 | root /app; 19 | } 20 | 21 | # proxy the PHP scripts to Apache listening on 127.0.0.1:80 22 | # 23 | #location ~ \.php$ { 24 | # proxy_pass http://127.0.0.1; 25 | #} 26 | 27 | # pass the PHP scripts to FastCGI server listening on 127.0.0.1:9000 28 | # 29 | #location ~ \.php$ { 30 | # root html; 31 | # fastcgi_pass 127.0.0.1:9000; 32 | # fastcgi_index index.php; 33 | # fastcgi_param SCRIPT_FILENAME /scripts$fastcgi_script_name; 34 | # include fastcgi_params; 35 | #} 36 | 37 | # deny access to .htaccess files, if Apache's document root 38 | # concurs with nginx's one 39 | # 40 | #location ~ /\.ht { 41 | # deny all; 42 | #} 43 | } 44 | 45 | -------------------------------------------------------------------------------- /action/src/types/input.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * 检查版本更新接收的输入类型 3 | */ 4 | export interface CheckVersionInputs { 5 | /** 6 | * GitHub Token,用于创建 PR 7 | */ 8 | token?: string 9 | /** 10 | * 上下文路径,唯一标识应用,当提供时,将用于查找应用的元数据 11 | * 12 | * - `all` 是一个特殊的值,表示检查所有应用 13 | * @default all 14 | */ 15 | context?: string 16 | /** 17 | * 并发数,控制同时处理的应用数量,默认为 `3` 18 | * @default 3 19 | */ 20 | concurrency: number 21 | /** 22 | * 是否创建 PR 23 | * - `true` - 创建 PR,使用 `update/xxx` 分支 24 | * - `false` - 不创建 PR 25 | * - `development` - 创建 PR,使用 `dev/xxx` 分支,该分支格式不会触发镜像构建 26 | * @default true 27 | */ 28 | createPr?: boolean | 'development' 29 | /** 30 | * 是否启用调试模式,调试模式下,将打印更多日志信息 31 | * @default false 32 | */ 33 | debug?: boolean 34 | /** 35 | * 日志打印格式 36 | */ 37 | logFormat?: 'simple' | 'detailed' | 'json' 38 | } 39 | 40 | /** 41 | * 解析数据接收的输入类型 42 | */ 43 | export interface ResolveMetadataInputs { 44 | /** 45 | * 上下文路径,唯一标识应用,当提供时,将用于查找应用的元数据 46 | * 47 | * - `all` 是一个特殊的值,表示检查所有应用 48 | * @default all 49 | */ 50 | context?: string 51 | /** 52 | * 需要处理的变体名称 53 | * 54 | * @default latest 55 | */ 56 | variants?: string 57 | /** 58 | * 是否启用调试模式,调试模式下,将打印更多日志信息 59 | * @default false 60 | */ 61 | debug?: boolean 62 | } 63 | -------------------------------------------------------------------------------- /action/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "action", 3 | "type": "module", 4 | "version": "0.0.0", 5 | "private": true, 6 | "description": "A tool to check application updates", 7 | "sideEffects": false, 8 | "engines": { 9 | "node": "20.x" 10 | }, 11 | "scripts": { 12 | "dev": "concurrently -c cyan,magenta --pad-prefix --timings 'bun:dev:check' 'bun:dev:metadata'", 13 | "dev:check": "bun build ./src/check.ts --outdir dist --target node --watch", 14 | "dev:metadata": "bun build ./src/metadata.ts --outdir dist --target node --watch", 15 | "build": "bun build ./src/check.ts ./src/metadata.ts --outdir dist --target node --minify", 16 | "build:check": "bun build ./src/check.ts --outdir dist --target node --minify", 17 | "build:metadata": "bun build ./src/metadata.ts --outdir dist --target node --minify" 18 | }, 19 | "devDependencies": { 20 | "@actions/cache": "^4.0.5", 21 | "@actions/core": "^1.11.1", 22 | "@actions/exec": "^1.1.1", 23 | "@actions/github": "^6.0.1", 24 | "@actions/glob": "^0.5.0", 25 | "@octokit/core": "^7.0.3", 26 | "@octokit/webhooks-definitions": "^3.67.3", 27 | "@types/semver": "^7.7.0", 28 | "ajv": "^8.17.1", 29 | "ajv-formats": "^3.0.1", 30 | "concurrently": "^9.2.0", 31 | "dayjs": "^1.11.13", 32 | "defu": "^6.1.4", 33 | "kolorist": "^1.8.0", 34 | "octokit-plugin-create-pull-request": "^6.0.1", 35 | "semver": "^7.7.2", 36 | "superjson": "^2.2.2", 37 | "typescript": "^5.9.2" 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /apps/haitang/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM alpine/git AS source 2 | WORKDIR /app 3 | ARG VERSION=3d5ff9c 4 | RUN git clone https://github.com/javayhu/haitang . && git checkout ${VERSION} 5 | # Analytics: Umami + Google Analytics 6 | RUN echo "" > src/layouts/Analytics.astro && \ 7 | # Comment: Giscus 8 | echo "" > src/components/Giscus.astro 9 | 10 | FROM node:20.19.4-alpine3.22 AS base 11 | WORKDIR /app 12 | 13 | FROM base AS build 14 | COPY --from=source /app . 15 | RUN corepack enable && corepack prepare --activate 16 | RUN yarn && yarn astro add node -y && yarn add @astrojs/node@8 17 | RUN yarn build 18 | 19 | FROM base AS deps 20 | COPY --from=build /app/package.json /app/yarn.lock* ./ 21 | RUN corepack enable && corepack prepare --activate 22 | RUN yarn install --production --frozen-lockfile 23 | 24 | FROM base 25 | ENV TZ=Asia/Shanghai 26 | ENV HOST=0.0.0.0 27 | 28 | COPY --from=build /app/dist ./dist/ 29 | COPY --from=deps /app/node_modules ./node_modules/ 30 | COPY --from=deps /app/package.json ./ 31 | 32 | # 清理 node_modules 中不必要的文件 33 | RUN find ./node_modules -name "*.md" -type f -delete && \ 34 | find ./node_modules -name "*.ts" -type f -delete && \ 35 | find ./node_modules -name "*.map" -type f -delete && \ 36 | find ./node_modules -name "test" -type d -exec rm -rf {} + 2>/dev/null || true && \ 37 | find ./node_modules -name "examples" -type d -exec rm -rf {} + 2>/dev/null || true && \ 38 | find ./node_modules -name "docs" -type d -exec rm -rf {} + 2>/dev/null || true 39 | 40 | EXPOSE 4321 41 | CMD ["node", "dist/server/entry.mjs"] 42 | -------------------------------------------------------------------------------- /action/src/file.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * 文件相关操作 3 | */ 4 | import fs from 'node:fs/promises' 5 | import path from 'node:path' 6 | 7 | /** 8 | * 检查路径是否存在 9 | */ 10 | export async function pathExists(path: string) { 11 | try { 12 | await fs.access(path, fs.constants.F_OK) 13 | return true 14 | } 15 | catch { 16 | return false 17 | } 18 | } 19 | 20 | /** 21 | * 安全地创建目录 22 | */ 23 | export async function ensureDir(dirPath: string): Promise { 24 | try { 25 | await fs.mkdir(dirPath, { recursive: true }) 26 | } 27 | catch (error) { 28 | if (error instanceof Error && 'code' in error && error.code !== 'EEXIST') { 29 | throw error 30 | } 31 | } 32 | } 33 | 34 | /** 35 | * 读取文件 36 | */ 37 | export async function readFile(filePath: string) { 38 | try { 39 | return await fs.readFile(filePath, 'utf-8') 40 | } 41 | catch { 42 | return null 43 | } 44 | } 45 | 46 | /** 47 | * 读取 JSON 48 | */ 49 | export async function readJson(filePath: string): Promise { 50 | try { 51 | const content = await readFile(filePath) 52 | return content ? JSON.parse(content) as T : null 53 | } 54 | catch { 55 | return null 56 | } 57 | } 58 | 59 | /** 60 | * 安全地写入文件 61 | */ 62 | export async function writeFile(filePath: string, content: string) { 63 | try { 64 | await ensureDir(path.dirname(filePath)) 65 | await fs.writeFile(filePath, content, 'utf-8') 66 | return true 67 | } 68 | catch (error) { 69 | console.error(`Failed to write file ${filePath}:`, error) 70 | return false 71 | } 72 | } 73 | -------------------------------------------------------------------------------- /base/vscode/starship.toml: -------------------------------------------------------------------------------- 1 | # 设置配置范例,开启编辑器的自动补全 2 | "$schema" = 'https://starship.rs/config-schema.json' 3 | 4 | # Use the color palette 5 | palette = "dracula" 6 | 7 | [character] 8 | error_symbol = "[❯](bold red)" 9 | success_symbol = "[❯](bold green)" 10 | 11 | [cmd_duration] 12 | style = "bold yellow" 13 | show_milliseconds = true 14 | show_notifications = true 15 | 16 | [directory] 17 | style = "bold green" 18 | 19 | [git_branch] 20 | style = "bold pink" 21 | 22 | [git_status] 23 | style = "bold red" 24 | 25 | [localip] 26 | ssh_only = false 27 | disabled = false 28 | 29 | [memory_usage] 30 | disabled = false 31 | threshold = -1 32 | format = "[${ram}( | ${swap})]($style) " 33 | style = "bold dimmed white" 34 | 35 | [time] 36 | disabled = false 37 | format = '[\[ $time \]]($style) ' 38 | time_format = "%T" 39 | utc_time_offset = "+8" 40 | style = "bold dimmed blue" 41 | 42 | [hostname] 43 | ssh_only = false 44 | style = "bold purple" 45 | format = '[$ssh_symbol$hostname]($style) ' 46 | disabled = false 47 | 48 | [username] 49 | style_user = "bold cyan" 50 | show_always = true 51 | disabled = false 52 | 53 | [shell] 54 | style = 'bold cyan' 55 | format = '[$indicator]($style) ' 56 | fish_indicator = '󰈺 ' 57 | disabled = false 58 | 59 | [container] 60 | disabled = true 61 | 62 | # Define Dracula color palette 63 | [palettes.dracula] 64 | background = "#282a36" 65 | current_line = "#44475a" 66 | foreground = "#f8f8f2" 67 | comment = "#6272a4" 68 | cyan = "#8be9fd" 69 | green = "#50fa7b" 70 | orange = "#ffb86c" 71 | pink = "#ff79c6" 72 | purple = "#bd93f9" 73 | red = "#ff5555" 74 | yellow = "#f1fa8c" 75 | -------------------------------------------------------------------------------- /apps/lsky/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM php:8.0.2-alpine3.13 AS builder 2 | 3 | WORKDIR /app 4 | ADD --chmod=0755 https://github.com/mlocati/docker-php-extension-installer/releases/latest/download/install-php-extensions /usr/local/bin/ 5 | 6 | ARG LSKY_VERSION=2.1 7 | ARG REPO_URL=https://github.com/lsky-org/lsky-pro/releases/download/${LSKY_VERSION}/lsky-pro-${LSKY_VERSION}.zip 8 | RUN curl -fsSL ${REPO_URL} -o lsky-pro.zip && \ 9 | unzip lsky-pro.zip && \ 10 | rm lsky-pro.zip && \ 11 | tar -czf /tmp/app.tar.gz . 12 | 13 | FROM nginx:alpine AS nginx 14 | 15 | FROM php:8.0.2-fpm-alpine3.12 16 | 17 | WORKDIR /app 18 | 19 | COPY --from=nginx /etc/nginx /etc/nginx 20 | COPY --from=nginx /docker-entrypoint.sh /docker-entrypoint.sh 21 | COPY --from=nginx /docker-entrypoint.d /docker-entrypoint.d 22 | 23 | COPY --from=builder /tmp/app.tar.gz /tmp/app.tar.gz 24 | COPY --from=builder /usr/local/bin/install-php-extensions /usr/local/bin/install-php-extensions 25 | 26 | COPY ./docker-entrypoint.sh /docker-entrypoint.d/00-entrypoint.sh 27 | COPY ./default.conf /etc/nginx/conf.d/default.conf 28 | 29 | RUN install-php-extensions @composer pdo_mysql pdo_pgsql pdo_sqlsrv bcmath imagick redis && \ 30 | mv "$PHP_INI_DIR/php.ini-production" "$PHP_INI_DIR/php.ini" && \ 31 | apk update && apk add --no-cache nginx && \ 32 | chmod +x /docker-entrypoint.sh && \ 33 | chmod +x -R /docker-entrypoint.d && \ 34 | rm -rf /var/cache/apk/* && \ 35 | tar -czf /tmp/nginx.tar.gz /etc/nginx 36 | 37 | ENTRYPOINT [ "/docker-entrypoint.sh" ] 38 | CMD [ "nginx", "-g", "daemon off;"] 39 | 40 | EXPOSE 80 41 | VOLUME /etc/nginx 42 | VOLUME /app 43 | -------------------------------------------------------------------------------- /action/src/types/index.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * 类型定义入口 3 | */ 4 | 5 | import type { createPullRequest } from 'octokit-plugin-create-pull-request' 6 | import type { GitCommitInfo } from './git.js' 7 | import type { ImageVariant } from './schema.js' 8 | 9 | export * from './git.js' 10 | export * from './input.js' 11 | export * from './schema.js' 12 | 13 | export type CreatePullRequestOptions = Parameters['createPullRequest']>[0] 14 | 15 | /** 16 | * 检查变体更新的结果 (version) 17 | */ 18 | export interface CheckVariantResult { 19 | /** 20 | * 版本信息,检查后的版本 21 | */ 22 | version: string 23 | /** 24 | * SHA 信息,检查后的提交 SHA 25 | */ 26 | sha: string 27 | /** 28 | * 提交记录 29 | */ 30 | commitInfo?: GitCommitInfo 31 | /** 32 | * 变体名称 33 | */ 34 | variantName: string 35 | /** 36 | * 是否需要更新 37 | */ 38 | needsUpdate: boolean 39 | /** 40 | * 变体配置,源配置,这里不做修改 41 | */ 42 | variant: ImageVariant 43 | /** 44 | * 上下文信息 45 | */ 46 | context: string 47 | } 48 | 49 | /** 50 | * 文件处理结果 51 | */ 52 | export interface ProcessedFile { 53 | /** 54 | * 文件路径,相对于项目根路径,而不是上下文路径 55 | * 例如:`apps/icones/Dockerfile` 56 | */ 57 | path: string 58 | /** 59 | * 文件内容 60 | */ 61 | content: string 62 | /** 63 | * 是否有变更 64 | */ 65 | changed: boolean 66 | /** 67 | * 原始内容 68 | */ 69 | originalContent: string 70 | } 71 | 72 | /** 73 | * 占位符数据接口 74 | * 75 | * - 用于替换文件内容中的占位符 76 | * - 键为占位符名称,值为包含新旧值的数组 77 | */ 78 | export type PlaceholderData = Record< 79 | string, 80 | [replacedValue?: string] | [replacedValue: string, originalValue?: string] 81 | > 82 | -------------------------------------------------------------------------------- /base/tg-session/README.md: -------------------------------------------------------------------------------- 1 | # tg-session 2 | 3 | A Telegram session string generator with QR code login support. This tool helps you generate session strings for Telegram applications. 4 | 5 | ## Usage 6 | 7 | 1. Get API Credentials 8 | - Visit 9 | - Login with your Telegram account 10 | - Click on "API Development tools" 11 | - Create a new application 12 | - Note down your `API_ID` and `API_HASH` 13 | 14 | 2. Run Container 15 | 16 | ```bash 17 | # Basic usage 18 | docker run -it --rm --name tg-session -v $(pwd):/app/session aliuq/tg-session 19 | 20 | # Debug mode (displays session string in console) 21 | docker run -it --rm --name tg-session -e DEBUG=true aliuq/tg-session 22 | 23 | # With API credentials 24 | docker run -it --rm \ 25 | --name tg-session \ 26 | -v $(pwd):/app/session \ 27 | -e API_ID=your_api_id \ 28 | -e API_HASH=your_api_hash \ 29 | aliuq/tg-session 30 | ``` 31 | 32 | The generated session string will be saved in `./.session` file. 33 | 34 | ## Environment Variables 35 | 36 | - `API_ID` - Telegram API ID from my.telegram.org 37 | - `API_HASH` - Telegram API Hash from my.telegram.org 38 | - `DEBUG` - Set to "true" to display session string in console (default: false) 39 | 40 | ## Build Instructions 41 | 42 | ```bash 43 | # Standard build 44 | docker build -t tg-session . 45 | 46 | # Build with buildx 47 | docker buildx build -t tg-session --load . 48 | 49 | # Build with detailed progress 50 | docker buildx build --progress=plain -t tg-session --load . 51 | ``` 52 | 53 | ## Security Note 54 | 55 | - Keep your API credentials and session string secure 56 | - Never share your session string with others 57 | - When DEBUG mode is enabled, session string will be visible in console 58 | -------------------------------------------------------------------------------- /test/self/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM alpine:3.19.1 2 | 3 | # For nghttp2-dev, we need this respository. 4 | # RUN echo https://dl-cdn.alpinelinux.org/alpine/edge/testing >>/etc/apk/repositories 5 | # RUN echo https://dl-cdn.alpinelinux.org/alpine/v3.19/main >>/etc/apk/repositories 6 | # 7 | 8 | RUN apk update && apk --no-cache add \ 9 | bash git curl zsh starship shadow \ 10 | ca-certificates openssl python3 make gcc g++ libgcc linux-headers grep \ 11 | ncurses coreutils util-linux binutils findutils 12 | 13 | SHELL ["bash", "-c"] 14 | 15 | ENV NVM_VERSION=0.39.7 16 | 17 | # install nvm 18 | RUN touch ~/.bashrc && \ 19 | curl -fsSL https://raw.githubusercontent.com/nvm-sh/nvm/v${NVM_VERSION}/install.sh | bash && \ 20 | chmod +x $HOME/.nvm/nvm.sh 21 | 22 | # install oh-my-zsh 23 | RUN chsh -s /bin/zsh && \ 24 | curl -fsSL https://raw.githubusercontent.com/ohmyzsh/ohmyzsh/master/tools/install.sh | bash && \ 25 | git clone https://github.com/zsh-users/zsh-autosuggestions ~/.oh-my-zsh/custom/plugins/zsh-autosuggestions && \ 26 | git clone https://github.com/zsh-users/zsh-syntax-highlighting ~/.oh-my-zsh/custom/plugins/zsh-syntax-highlighting && \ 27 | sed -i 's/plugins=(git)/plugins=(git zsh-autosuggestions zsh-syntax-highlighting)/g' ~/.zshrc && \ 28 | echo "export USER=\$(whoami)" >> ~/.zshrc 29 | 30 | # other 31 | RUN curl -fsSL https://raw.githubusercontent.com/nvm-sh/nvm/v${NVM_VERSION}/install.sh | bash && \ 32 | echo "eval \"\$(starship init zsh)\"" >> ~/.zshrc && \ 33 | curl -fs -S --create-dirs -o ~/.config/starship.toml https://raw.githubusercontent.com/aliuq/config/master/starship.toml 34 | 35 | RUN apk cache clean && \ 36 | rm -rf /var/cache/apk/* && \ 37 | rm -rf /tmp/* && \ 38 | rm -rf /var/log/* 39 | 40 | ENTRYPOINT [ "/bin/zsh" ] 41 | -------------------------------------------------------------------------------- /apps/inpaint-web/README.md: -------------------------------------------------------------------------------- 1 | # Inpaint Web 2 | 3 | > 基于 Web 的免费开源图像修复工具,使用 AI 技术智能去除图片中的不需要对象 4 | 5 | [![Docker Pulls](https://img.shields.io/docker/pulls/aliuq/inpaint-web)](https://hub.docker.com/r/aliuq/inpaint-web) 6 | [![Docker Image Size](https://img.shields.io/docker/image-size/aliuq/inpaint-web)](https://hub.docker.com/r/aliuq/inpaint-web) 7 | 8 | ## 项目信息 9 | 10 | - **上游仓库**: [lxfater/inpaint-web](https://github.com/lxfater/inpaint-web) 11 | - **Docker 镜像**: [aliuq/inpaint-web](https://hub.docker.com/r/aliuq/inpaint-web) 12 | - **Dockerfile**: [查看构建文件](https://github.com/aliuq/apps-image/tree/master/apps/inpaint-web) 13 | 14 | ## 快速开始 15 | 16 | ### 使用 Docker 运行 17 | 18 | ```bash 19 | docker run -d --name inpaint-web -p 8080:80 aliuq/inpaint-web:latest 20 | # 测试 21 | docker run --rm --name inpaint-web -p 8080:80 aliuq/inpaint-web:latest 22 | ``` 23 | 24 | 访问 `http://localhost:8080` 即可使用 25 | 26 | ### 使用 Docker Compose 27 | 28 | 创建 `docker-compose.yml` 文件: 29 | 30 | ```yaml 31 | name: inpaint-web 32 | services: 33 | inpaint-web: 34 | image: aliuq/inpaint-web:latest 35 | container_name: inpaint-web 36 | restart: unless-stopped 37 | ports: 38 | - '8080:80' 39 | ``` 40 | 41 | 运行服务: 42 | 43 | ```bash 44 | docker-compose up -d 45 | ``` 46 | 47 | ## 开发 48 | 49 | ### 本地构建 50 | 51 | ```bash 52 | # 克隆仓库 53 | git clone https://github.com/aliuq/apps-image.git 54 | cd apps-image/apps/inpaint-web 55 | 56 | # 构建镜像 57 | docker buildx build -f ./Dockerfile -t inpaint-web:local --load . 58 | 59 | # 运行测试 60 | docker run --rm --name inpaint-web-local -p 8080:80 inpaint-web:local 61 | ``` 62 | 63 | ### 调试模式 64 | 65 | ```bash 66 | # 显示详细构建日志 67 | docker buildx build --progress=plain -f ./Dockerfile -t inpaint-web:debug --load . 68 | ``` 69 | 70 | --- 71 | 72 | > 📝 该文档由 AI 辅助生成并整理,如有问题请随时反馈 73 | -------------------------------------------------------------------------------- /apps/lsky/Dockerfile.dev: -------------------------------------------------------------------------------- 1 | FROM alpine/git AS source 2 | WORKDIR /app 3 | ARG VERSION=38d52c4 4 | RUN git clone https://github.com/lsky-org/lsky-pro.git . && git checkout ${VERSION} 5 | 6 | FROM node:20-alpine3.20 AS web 7 | WORKDIR /app 8 | COPY --from=source /app . 9 | RUN npm install && npm run prod && rm -rf node_modules 10 | 11 | FROM php:8.0.2-alpine3.13 AS builder 12 | WORKDIR /app 13 | ADD --chmod=0755 https://github.com/mlocati/docker-php-extension-installer/releases/latest/download/install-php-extensions /usr/local/bin/ 14 | COPY --from=web /app . 15 | RUN install-php-extensions @composer && \ 16 | composer install --no-dev --optimize-autoloader --no-interaction --no-progress --no-suggest && \ 17 | tar -czf /tmp/app.tar.gz . 18 | 19 | FROM nginx:alpine AS nginx 20 | 21 | FROM php:8.0.2-fpm-alpine3.12 22 | WORKDIR /app 23 | 24 | COPY --from=nginx /etc/nginx /etc/nginx 25 | COPY --from=nginx /docker-entrypoint.sh /docker-entrypoint.sh 26 | COPY --from=nginx /docker-entrypoint.d /docker-entrypoint.d 27 | 28 | COPY --from=builder /tmp/app.tar.gz /tmp/app.tar.gz 29 | COPY --from=builder /usr/local/bin/install-php-extensions /usr/local/bin/install-php-extensions 30 | 31 | COPY ./docker-entrypoint.sh /docker-entrypoint.d/00-entrypoint.sh 32 | COPY ./default.conf /etc/nginx/conf.d/default.conf 33 | 34 | RUN install-php-extensions @composer pdo_mysql pdo_pgsql pdo_sqlsrv bcmath imagick redis && \ 35 | mv "$PHP_INI_DIR/php.ini-production" "$PHP_INI_DIR/php.ini" && \ 36 | apk update && apk add --no-cache nginx && \ 37 | chmod +x /docker-entrypoint.sh && \ 38 | chmod +x -R /docker-entrypoint.d && \ 39 | rm -rf /var/cache/apk/* && \ 40 | tar -czf /tmp/nginx.tar.gz /etc/nginx 41 | 42 | ENTRYPOINT [ "/docker-entrypoint.sh" ] 43 | CMD [ "nginx", "-g", "daemon off;"] 44 | 45 | EXPOSE 80 46 | VOLUME /etc/nginx 47 | VOLUME /app 48 | -------------------------------------------------------------------------------- /base/self/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM alpine:3.19.1 2 | 3 | # For nghttp2-dev, we need this respository. 4 | # RUN echo https://dl-cdn.alpinelinux.org/alpine/edge/testing >>/etc/apk/repositories 5 | # RUN echo https://dl-cdn.alpinelinux.org/alpine/v3.19/main >>/etc/apk/repositories 6 | # 7 | 8 | LABEL version="0.0.2" 9 | LABEL maintainer="AliuQ " 10 | 11 | RUN apk update && apk --no-cache add \ 12 | bash git curl zsh starship shadow \ 13 | ca-certificates openssl python3 make gcc g++ libgcc linux-headers grep \ 14 | ncurses coreutils util-linux binutils findutils 15 | 16 | SHELL ["bash", "-c"] 17 | 18 | ENV NVM_VERSION=0.39.7 19 | 20 | # install nvm 21 | RUN touch ~/.bashrc && \ 22 | curl -fsSL https://raw.githubusercontent.com/nvm-sh/nvm/v$NVM_VERSION/install.sh | bash && \ 23 | chmod +x $HOME/.nvm/nvm.sh 24 | 25 | # install oh-my-zsh 26 | RUN chsh -s /bin/zsh && \ 27 | curl -fsSL https://raw.githubusercontent.com/ohmyzsh/ohmyzsh/master/tools/install.sh | bash && \ 28 | git clone https://github.com/zsh-users/zsh-autosuggestions ~/.oh-my-zsh/custom/plugins/zsh-autosuggestions && \ 29 | git clone https://github.com/zsh-users/zsh-syntax-highlighting ~/.oh-my-zsh/custom/plugins/zsh-syntax-highlighting && \ 30 | sed -i 's/plugins=(git)/plugins=(git zsh-autosuggestions zsh-syntax-highlighting)/g' ~/.zshrc && \ 31 | echo "export USER=\$(whoami)" >> ~/.zshrc 32 | 33 | # other 34 | RUN curl -fsSL https://raw.githubusercontent.com/nvm-sh/nvm/v$NVM_VERSION/install.sh | bash && \ 35 | echo "eval \"\$(starship init zsh)\"" >> ~/.zshrc && \ 36 | curl -fs -S --create-dirs -o ~/.config/starship.toml https://raw.githubusercontent.com/aliuq/config/master/starship.toml 37 | 38 | RUN apk cache clean && \ 39 | rm -rf /var/cache/apk/* && \ 40 | rm -rf /tmp/* && \ 41 | rm -rf /var/log/* 42 | 43 | ENTRYPOINT [ "/bin/zsh" ] 44 | -------------------------------------------------------------------------------- /apps/weektodo/README.md: -------------------------------------------------------------------------------- 1 | # WeekTodo 2 | 3 | > 一个简洁美观的每周任务管理工具,帮助您高效规划和管理一周的待办事项 4 | 5 | [![Docker Pulls](https://img.shields.io/docker/pulls/aliuq/weektodo)](https://hub.docker.com/r/aliuq/weektodo) 6 | [![Docker Image Size](https://img.shields.io/docker/image-size/aliuq/weektodo)](https://hub.docker.com/r/aliuq/weektodo) 7 | 8 | ## 项目信息 9 | 10 | - **上游仓库**: [manuelernestog/weektodo](https://github.com/manuelernestog/weektodo) 11 | - **Docker 镜像**: [aliuq/weektodo](https://hub.docker.com/r/aliuq/weektodo) 12 | - **Dockerfile**: [查看构建文件](https://github.com/aliuq/apps-image/tree/master/apps/weektodo) 13 | 14 | ## 快速开始 15 | 16 | ### 使用 Docker 运行 17 | 18 | ```bash 19 | docker run -d --name weektodo -p 8000:80 aliuq/weektodo:latest 20 | ``` 21 | 22 | 访问 `http://localhost:8000` 即可使用 23 | 24 | ### 使用 Docker Compose 25 | 26 | 创建 `docker-compose.yml` 文件: 27 | 28 | ```yaml 29 | name: weektodo 30 | services: 31 | weektodo: 32 | image: aliuq/weektodo:latest 33 | container_name: weektodo 34 | restart: unless-stopped 35 | ports: 36 | - '8000:80' 37 | ``` 38 | 39 | 运行服务: 40 | 41 | ```bash 42 | docker-compose up -d 43 | ``` 44 | 45 | ## 功能特性 46 | 47 | - 📅 **每周视图**: 以周为单位展示和管理待办事项 48 | - ✅ **任务管理**: 支持添加、编辑、删除和标记完成任务 49 | - 🎨 **简洁界面**: 现代化的用户界面设计,操作简单直观 50 | - 📱 **响应式设计**: 完美适配桌面和移动设备 51 | - 💾 **本地存储**: 数据保存在浏览器本地,无需注册账户 52 | - 🔄 **实时更新**: 任务状态实时更新和保存 53 | 54 | ## 开发 55 | 56 | ### 本地构建 57 | 58 | ```bash 59 | # 克隆仓库 60 | git clone https://github.com/aliuq/apps-image.git 61 | cd apps-image/apps/weektodo 62 | 63 | # 构建镜像 64 | docker buildx build -f ./Dockerfile -t weektodo:local --load . 65 | 66 | # 运行测试 67 | docker run --rm --name weektodo-local -p 8000:80 weektodo:local 68 | ``` 69 | 70 | ### 调试模式 71 | 72 | ```bash 73 | # 显示详细构建日志 74 | docker buildx build --progress=plain -f ./Dockerfile -t weektodo:debug --no-cache --load . 75 | ``` 76 | 77 | ## 注意事项 78 | 79 | - 数据存储在浏览器本地,清除浏览器数据会丢失任务 80 | - 建议定期导出重要任务数据作为备份 81 | - 使用现代浏览器以获得最佳体验 82 | 83 | ## 相关链接 84 | 85 | - [项目演示](https://weektodo.me/) 86 | 87 | --- 88 | 89 | > 📝 该文档由 AI 辅助生成并整理,如有问题请随时反馈 90 | -------------------------------------------------------------------------------- /apps/icones/README.md: -------------------------------------------------------------------------------- 1 | # Icones 2 | 3 | > 一个开源、美观的图标浏览器,让您能够搜索和浏览超过 150,000 个开源矢量图标 4 | 5 | [![Docker Pulls](https://img.shields.io/docker/pulls/aliuq/icones)](https://hub.docker.com/r/aliuq/icones) 6 | [![Docker Image Size](https://img.shields.io/docker/image-size/aliuq/icones)](https://hub.docker.com/r/aliuq/icones) 7 | 8 | ## 项目信息 9 | 10 | - **官方仓库**: [antfu-collective/icones](https://github.com/antfu-collective/icones) 11 | - **Docker 镜像**: [aliuq/icones](https://hub.docker.com/r/aliuq/icones) 12 | - **Dockerfile**: [查看构建文件](https://github.com/aliuq/apps-image/blob/master/apps/icones/Dockerfile) 13 | 14 | ## 快速开始 15 | 16 | ### 使用 Docker 运行 17 | 18 | ```bash 19 | docker run -d --name icones -p 8080:80 aliuq/icones:latest 20 | # 测试 21 | docker run --rm --name icones -p 8080:80 aliuq/icones:latest 22 | ``` 23 | 24 | 访问 `http://localhost:8080` 即可使用 25 | 26 | ### 使用 Docker Compose 27 | 28 | 创建 `docker-compose.yml` 文件: 29 | 30 | ```yaml 31 | name: icones 32 | services: 33 | icones: 34 | image: aliuq/icones:latest 35 | container_name: icones 36 | restart: unless-stopped 37 | ports: 38 | - '8080:80' 39 | ``` 40 | 41 | 运行服务: 42 | 43 | ```bash 44 | docker-compose up -d 45 | ``` 46 | 47 | ## 功能特性 48 | 49 | - 🔍 **搜索图标**: 从超过 150,000 个开源图标中快速搜索 50 | - 📦 **多图标库支持**: 支持 Material Design、FontAwesome、Heroicons 等 51 | - 🎨 **自定义样式**: 支持修改颜色、大小等属性 52 | - 📱 **响应式设计**: 完美适配桌面和移动设备 53 | - ⬇️ **多格式导出**: 支持 SVG、PNG、Vue 组件等格式 54 | 55 | ## 开发 56 | 57 | ### 本地构建 58 | 59 | ```bash 60 | # 克隆仓库 61 | git clone https://github.com/aliuq/apps-image.git 62 | cd apps-image/apps/icones 63 | 64 | # 构建镜像 65 | docker buildx build -f ./Dockerfile -t icones:local --load . 66 | 67 | # 运行测试 68 | docker run --rm --name icones-local -p 8080:80 icones:local 69 | ``` 70 | 71 | ### 调试模式 72 | 73 | ```bash 74 | # 以开发模式运行(显示构建日志) 75 | docker buildx build --progress=plain -f ./Dockerfile -t icones:debug --load . 76 | ``` 77 | 78 | ## 相关链接 79 | 80 | - [https://icones.js.org](https://icones.js.org) 81 | - [https://icones.netlify.app](https://icones.netlify.app) 82 | 83 | --- 84 | 85 | > 📝 该文档由 AI 辅助生成并整理,如有问题请随时反馈 86 | -------------------------------------------------------------------------------- /base/self/Dockerfile.ubuntu: -------------------------------------------------------------------------------- 1 | FROM ubuntu:22.04 2 | 3 | # 修改 archive.ubuntu.com 为阿里云镜像 4 | RUN sed -i s@/archive.ubuntu.com/@/mirrors.aliyun.com/@g /etc/apt/sources.list && \ 5 | sed -i s@/security.ubuntu.com/@/mirrors.aliyun.com/@g /etc/apt/sources.list && \ 6 | apt clean && \ 7 | apt update 8 | 9 | RUN apt install --no-install-recommends -y curl wget zip unzip vim make gcc libncurses5-dev libncursesw5-dev 10 | RUN apt install -y software-properties-common 11 | 12 | # Git 13 | RUN add-apt-repository -y ppa:git-core/ppa && \ 14 | apt update && \ 15 | apt install --no-install-recommends -y git 16 | 17 | # Zsh 18 | RUN curl -fsSL https://raw.githubusercontent.com/aliuq/shs/main/zsh/ubuntu.sh | bash -s 5.9 19 | 20 | # NVM 21 | ENV NVM_VERSION=0.39.7 22 | RUN curl -fsSL https://raw.githubusercontent.com/nvm-sh/nvm/v$NVM_VERSION/install.sh | bash 23 | 24 | # Oh-my-zsh 25 | RUN chsh -s /bin/zsh && \ 26 | curl -fsSL https://raw.githubusercontent.com/ohmyzsh/ohmyzsh/master/tools/install.sh | bash && \ 27 | git clone https://github.com/zsh-users/zsh-autosuggestions ~/.oh-my-zsh/custom/plugins/zsh-autosuggestions && \ 28 | git clone https://github.com/zsh-users/zsh-syntax-highlighting ~/.oh-my-zsh/custom/plugins/zsh-syntax-highlighting && \ 29 | sed -i 's/plugins=(git)/plugins=(git zsh-autosuggestions zsh-syntax-highlighting)/g' ~/.zshrc && \ 30 | echo "export USER=\$(whoami)" >> ~/.zshrc && \ 31 | curl -fsSL https://raw.githubusercontent.com/nvm-sh/nvm/v$NVM_VERSION/install.sh | bash 32 | 33 | # Starship 34 | RUN curl -sS https://starship.rs/install.sh | sh -s -- -y && \ 35 | echo "eval \"\$(starship init zsh)\"" >> ~/.zshrc && \ 36 | curl -fs -S --create-dirs -o ~/.config/starship.toml https://raw.githubusercontent.com/aliuq/config/master/starship.toml 37 | 38 | # Remove 39 | RUN apt remove -y ca-certificates gcc-11-base gcc-11 gcc make openssl libncurses5-dev libncursesw5-dev 40 | 41 | # Clean 42 | RUN apt clean -y && apt autoclean -y && apt autoremove -y && \ 43 | rm -rf /var/lib/apt/lists && \ 44 | rm -rf /tmp && \ 45 | rm -rf /var/log 46 | 47 | ENTRYPOINT [ "/bin/zsh" ] 48 | -------------------------------------------------------------------------------- /apps/yulegeyu/README.md: -------------------------------------------------------------------------------- 1 | # 鱼了个鱼 2 | 3 | > 羊了个羊纯前端实现版,支持自定义关卡、图案和无限道具的休闲益智游戏 4 | 5 | [![Docker Pulls](https://img.shields.io/docker/pulls/aliuq/yulegeyu)](https://hub.docker.com/r/aliuq/yulegeyu) 6 | [![Docker Image Size](https://img.shields.io/docker/image-size/aliuq/yulegeyu)](https://hub.docker.com/r/aliuq/yulegeyu) 7 | 8 | ## 项目信息 9 | 10 | - **上游仓库**: [liyupi/yulegeyu](https://github.com/liyupi/yulegeyu) 11 | - **Docker 镜像**: [aliuq/yulegeyu](https://hub.docker.com/r/aliuq/yulegeyu) 12 | - **Dockerfile**: [查看构建文件](https://github.com/aliuq/apps-image/tree/master/apps/yulegeyu/Dockerfile) 13 | 14 | ## 快速开始 15 | 16 | ### 使用 Docker 运行 17 | 18 | ```bash 19 | docker run -d --name yulegeyu -p 8000:80 aliuq/yulegeyu:latest 20 | ``` 21 | 22 | 访问 `http://localhost:8000` 即可开始游戏 23 | 24 | ### 使用 Docker Compose 25 | 26 | 创建 `docker-compose.yml` 文件: 27 | 28 | ```yaml 29 | name: yulegeyu 30 | services: 31 | yulegeyu: 32 | image: aliuq/yulegeyu:latest 33 | container_name: yulegeyu 34 | restart: unless-stopped 35 | ports: 36 | - '8000:80' 37 | ``` 38 | 39 | 运行服务: 40 | 41 | ```bash 42 | docker-compose up -d 43 | ``` 44 | 45 | ## 功能特性 46 | 47 | - 🎮 **经典玩法**: 完整还原羊了个羊的核心游戏机制 48 | - 🛠️ **自定义关卡**: 支持创建和编辑自定义游戏关卡 49 | - 🎨 **自定义图案**: 可以替换游戏中的图案和主题 50 | - ⚡ **无限道具**: 提供无限的游戏道具,降低游戏难度 51 | - 💻 **纯前端实现**: 基于 Web 技术开发,无需后端服务 52 | - 📱 **响应式设计**: 支持在各种设备上流畅游戏 53 | 54 | ## 游戏玩法 55 | 56 | 1. **游戏目标**: 将相同的三个图案消除,直到清空所有方块 57 | 2. **操作方式**: 点击方块将其移动到底部卡槽 58 | 3. **消除规则**: 当三个相同图案聚集在卡槽时自动消除 59 | 4. **胜利条件**: 成功清空所有方块即可过关 60 | 61 | ## 开发 62 | 63 | ### 本地构建 64 | 65 | ```bash 66 | # 克隆仓库 67 | git clone https://github.com/aliuq/apps-image.git 68 | cd apps-image/apps/yulegeyu 69 | 70 | # 构建镜像 71 | docker buildx build -f ./Dockerfile -t yulegeyu:local --load . 72 | 73 | # 运行测试 74 | docker run --rm --name yulegeyu-local -p 8000:80 yulegeyu:local 75 | ``` 76 | 77 | ### 调试模式 78 | 79 | ```bash 80 | # 显示详细构建日志 81 | docker buildx build --progress=plain -f ./Dockerfile -t yulegeyu:debug --no-cache --load . 82 | ``` 83 | 84 | ## 相关链接 85 | 86 | - [在线体验](https://yulegeyu.yupi.icu/) 87 | 88 | --- 89 | 90 | > 📝 该文档由 AI 辅助生成并整理,如有问题请随时反馈 91 | -------------------------------------------------------------------------------- /apps/cobalt/README.md: -------------------------------------------------------------------------------- 1 | # Cobalt 2 | 3 | > 媒体下载器,支持多平台视频/音频下载 4 | 5 | [![Docker Pulls](https://img.shields.io/docker/pulls/aliuq/cobalt)](https://hub.docker.com/r/aliuq/cobalt) 6 | [![Docker Image Size](https://img.shields.io/docker/image-size/aliuq/cobalt)](https://hub.docker.com/r/aliuq/cobalt) 7 | 8 | ## 项目信息 9 | 10 | - **官方仓库**: [imputnet/cobalt](https://github.com/imputnet/cobalt) 11 | - **Docker 镜像**: [`aliuq/cobalt`](https://hub.docker.com/r/aliuq/cobalt) 12 | - **Dockerfile**: [查看构建文件](https://github.com/aliuq/apps-image/blob/master/apps/cobalt/Dockerfile) 13 | 14 | ## 快速开始 15 | 16 | ### 使用 Docker Compose 17 | 18 | 创建 `docker-compose.yml` 文件 19 | 20 | ```yaml 21 | name: cobalt 22 | services: 23 | cobalt-api: 24 | image: ghcr.io/imputnet/cobalt:11.0.1 25 | restart: always 26 | container_name: cobalt-api 27 | ports: 28 | - 9000:9000 29 | environment: 30 | - API_URL=http://localhost:9000 31 | 32 | cobalt-web: 33 | image: aliuq/cobalt:latest 34 | restart: always 35 | container_name: cobalt-web 36 | ports: 37 | - 8080:80 38 | environment: 39 | - BASE_API=http://localhost:9000 40 | ``` 41 | 42 | 运行服务: 43 | 44 | ```bash 45 | docker-compose up -d 46 | ``` 47 | 48 | ## 功能特性 49 | 50 | - 🎵 支持多平台媒体下载(YouTube, Twitter, TikTok, Instagram 等) 51 | - 🎥 视频和音频格式选择 52 | - 🔗 简单的 URL 粘贴下载 53 | - 📱 响应式设计,支持移动端 54 | - 🚀 快速下载,无需注册 55 | - 🎯 支持高质量格式(最高 8K) 56 | 57 | ## 环境变量 58 | 59 | | 变量名 | 默认值 | 说明 | 60 | |--------|--------|------| 61 | | `BASE_API` | `https://api.cobalt.tools` | Cobalt API 服务地址 | 62 | 63 | ## 开发 64 | 65 | ### 本地构建 66 | 67 | ```bash 68 | # 克隆仓库 69 | git clone https://github.com/aliuq/apps-image.git 70 | cd apps-image/apps/cobalt 71 | 72 | # 构建镜像 73 | docker buildx build -f ./Dockerfile -t cobalt:local --load . 74 | ``` 75 | 76 | ### 调试模式 77 | 78 | ```bash 79 | # 以开发模式运行(显示构建日志) 80 | docker buildx build --progress=plain -f ./Dockerfile -t cobalt:debug --load . 81 | ``` 82 | 83 | ## 相关链接 84 | 85 | - [官方网站](https://cobalt.tools/) 86 | - [文档](https://github.com/imputnet/cobalt/blob/main/docs/api-env-variables.md) 87 | 88 | --- 89 | 90 | > 📝 该文档由 AI 辅助生成并整理,如有问题请随时反馈 91 | -------------------------------------------------------------------------------- /apps/n8n-workflows/README.md: -------------------------------------------------------------------------------- 1 | # N8n Workflows 2 | 3 | > n8n 工作流模板集合,提供 4,343+ 个生产就绪的自动化工作流和在线浏览界面 4 | 5 | [![Docker Pulls](https://img.shields.io/docker/pulls/aliuq/n8n-workflows)](https://hub.docker.com/r/aliuq/n8n-workflows) 6 | [![Docker Image Size](https://img.shields.io/docker/image-size/aliuq/n8n-workflows)](https://hub.docker.com/r/aliuq/n8n-workflows) 7 | 8 | ## 项目信息 9 | 10 | - **上游仓库**: [Zie619/n8n-workflows](https://github.com/Zie619/n8n-workflows) 11 | - **Docker 镜像**: [aliuq/n8n-workflows](https://hub.docker.com/r/aliuq/n8n-workflows) 12 | - **Dockerfile**: [查看构建文件](https://github.com/aliuq/apps-image/tree/master/apps/n8n-workflows) 13 | - **在线体验**: [zie619.github.io/n8n-workflows](https://zie619.github.io/n8n-workflows) 14 | 15 | ## 快速开始 16 | 17 | ### 使用 Docker 运行 18 | 19 | ```bash 20 | docker run -d --name n8n-workflows -p 8000:8000 aliuq/n8n-workflows:latest 21 | ``` 22 | 23 | 访问 `http://localhost:8000` 即可使用 24 | 25 | ### 使用 Docker Compose 26 | 27 | 创建 `docker-compose.yml` 文件: 28 | 29 | ```yaml 30 | name: n8n-workflows 31 | services: 32 | n8n-workflows: 33 | image: aliuq/n8n-workflows:latest 34 | container_name: n8n-workflows 35 | restart: unless-stopped 36 | ports: 37 | - '8000:8000' 38 | ``` 39 | 40 | 运行服务: 41 | 42 | ```bash 43 | docker-compose up -d 44 | ``` 45 | 46 | ## 功能特性 47 | 48 | - 📊 **4,343+ 工作流**: 涵盖 365+ 种集成服务的生产就绪工作流 49 | - 🔍 **智能搜索**: 基于 SQLite FTS5 的全文搜索,< 100ms 响应时间 50 | - 📂 **15+ 分类**: 按使用场景组织(营销、销售、DevOps 等) 51 | - 📱 **响应式设计**: 完美适配桌面和移动设备 52 | - ⬇️ **直接下载**: 一键获取工作流 JSON 文件 53 | - 🎨 **现代界面**: 支持明暗主题切换 54 | - 🚀 **高性能**: 700 倍性能提升,10 倍更快加载速度 55 | 56 | ## 开发 57 | 58 | ### 本地构建 59 | 60 | ```bash 61 | # 克隆仓库 62 | git clone https://github.com/aliuq/apps-image.git 63 | cd apps-image/apps/n8n-workflows 64 | 65 | # 构建镜像 66 | docker buildx build -f ./Dockerfile -t n8n-workflows:local --load . 67 | ``` 68 | 69 | ### 调试模式 70 | 71 | ```bash 72 | # 以开发模式运行(显示构建日志) 73 | docker buildx build --progress=plain -f ./Dockerfile -t n8n-workflows:local --load . 74 | 75 | # 运行容器并进入交互模式 76 | docker run -it --rm -p 8000:8000 n8n-workflows:local 77 | ``` 78 | 79 | --- 80 | 81 | > 📝 该文档由 AI 辅助生成并整理,如有问题请随时反馈 82 | -------------------------------------------------------------------------------- /action/src/metadata.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * 解析数据的入口 3 | */ 4 | import process from 'node:process' 5 | import core from '@actions/core' 6 | import { yellow } from 'kolorist' 7 | import { resolveMetadataConfig as config, isAct } from './config.js' 8 | import { MetaAppsManager } from './context/metaAppsManager.js' 9 | import { createLogger } from './logger.js' 10 | 11 | async function main() { 12 | const logger = createLogger() 13 | try { 14 | isAct && await logger.json(config, 'Inputs') 15 | 16 | // 1. 初始化应用管理生命周期 17 | const appsManager = new MetaAppsManager() 18 | 19 | // 2. 获取改变的上下文 20 | const result = await appsManager.scanChangedContext() 21 | await logger.json(result, 'Changed Contexts') 22 | if (!result?.context) 23 | return 24 | 25 | // 2. 加载应用上下文 26 | const app = await appsManager.loadAppContext(result.context) 27 | if (!app) 28 | return 29 | 30 | // 3. 获取 variants 31 | const variants = app.getChangedVariants(result.variants) 32 | if (!variants || !Object.keys(variants)?.length) { 33 | core.notice('No changed variants found.') 34 | process.exit(0) 35 | } 36 | await logger.json(variants, 'Changed variants') 37 | 38 | core.summary.addHeading('Resolve Docker Metadata summary', 2) 39 | 40 | // 4. 解析应用元数据 41 | const matrixArray = await app?.buildMatrixData(variants) 42 | if (!matrixArray) { 43 | logger.warn(yellow('No valid matrix data found, skipping metadata resolution.')) 44 | core.summary.addRaw('⚠️ No valid matrix data found, skipping metadata resolution.') 45 | } 46 | else { 47 | await logger.json({ include: matrixArray }, 'Matrix') 48 | core.setOutput('matrix', { include: matrixArray }) 49 | appsManager.generateSummary(matrixArray) 50 | 51 | // 将 latest 变体导出去 52 | const latestVariant = matrixArray.find((item: any) => item.variant === 'latest') 53 | core.setOutput('latest', latestVariant) 54 | } 55 | core.summary.write() 56 | } 57 | catch (error) { 58 | if (error instanceof Error) { 59 | logger.error(`❌ An error occurred during the resolve metadata operation: ${error.message}`) 60 | } 61 | else { 62 | logger.error(`❌ An unexpected error occurred: ${String(error)}`) 63 | } 64 | } 65 | } 66 | 67 | main() 68 | -------------------------------------------------------------------------------- /apps/haitang/README.md: -------------------------------------------------------------------------------- 1 | # Haitang 海棠诗社 2 | 3 | > 古诗词的数字桃源,提供丰富的中国古典诗词浏览、搜索和学习功能 4 | 5 | [![Docker Pulls](https://img.shields.io/docker/pulls/aliuq/haitang)](https://hub.docker.com/r/aliuq/haitang) 6 | [![Docker Image Size](https://img.shields.io/docker/image-size/aliuq/haitang)](https://hub.docker.com/r/aliuq/haitang) 7 | 8 | ## 项目信息 9 | 10 | - **上游仓库**: [javayhu/haitang](https://github.com/javayhu/haitang) 11 | - **Docker 镜像**: [aliuq/haitang](https://hub.docker.com/r/aliuq/haitang) 12 | - **Dockerfile**: [查看构建文件](https://github.com/aliuq/apps-image/tree/master/apps/haitang) 13 | - **官方网站**: [haitang.app](https://haitang.app/) 14 | - **在线体验**: [haitang.vercel.app](https://haitang.vercel.app/) 15 | 16 | ## 快速开始 17 | 18 | ### 使用 Docker 运行 19 | 20 | ```bash 21 | docker run -d --name haitang -p 4321:4321 aliuq/haitang:latest 22 | # 测试 23 | docker run --rm --name haitang -p 4321:4321 aliuq/haitang:latest 24 | ``` 25 | 26 | 访问 `http://localhost:4321` 即可使用 27 | 28 | ### 使用 Docker Compose 29 | 30 | 创建 `docker-compose.yml` 文件: 31 | 32 | ```yaml 33 | name: haitang 34 | services: 35 | haitang: 36 | image: aliuq/haitang:latest 37 | container_name: haitang 38 | restart: unless-stopped 39 | ports: 40 | - '4321:4321' 41 | ``` 42 | 43 | 运行服务: 44 | 45 | ```bash 46 | docker-compose up -d 47 | ``` 48 | 49 | ## 功能特性 50 | 51 | - 🎯 **多维度检索**: 按诗集、朝代、诗人、诗词等方式检索,内容丰富,信息齐全 52 | - 📝 **精选分类**: 按选集、主题、节日、节气、词牌、时令、地理等方式精选分类 53 | - 🔍 **全站响应式**: 兼容移动端,支持暗黑模式,响应速度快 54 | - 🏮 **海量诗词**: 收录大量中国古典诗词作品 55 | - 📱 **完美适配**: 桌面和移动设备都有优秀的使用体验 56 | - 🎨 **优雅界面**: 中式设计风格,简洁美观 57 | 58 | ## 开发 59 | 60 | ### 本地构建 61 | 62 | ```bash 63 | # 克隆仓库 64 | git clone https://github.com/aliuq/apps-image.git 65 | cd apps-image/apps/haitang 66 | 67 | # 构建镜像 68 | docker buildx build -f ./Dockerfile -t haitang:local --load . 69 | 70 | # 运行测试 71 | docker run --rm --name haitang-local -p 4321:4321 haitang:local 72 | ``` 73 | 74 | ### 调试模式 75 | 76 | ```bash 77 | # 显示详细构建日志 78 | docker buildx build --progress=plain -f ./Dockerfile -t haitang:debug --no-cache --load . 79 | ``` 80 | 81 | ## 注意事项 82 | 83 | - 容器已经移除 `Analytics: Umami + Google Analytics` 相关代码 84 | - 容器已经移除 `Comment: Giscus` 相关代码 85 | 86 | ## 相关链接 87 | 88 | - [海棠诗社官网](https://haitang.app/) 89 | - [开源版本体验](https://haitang.vercel.app/) 90 | - [上游项目主页](https://github.com/javayhu/haitang) 91 | 92 | --- 93 | 94 | > 📝 该文档由 AI 辅助生成并整理,如有问题请随时反馈 95 | -------------------------------------------------------------------------------- /apps/srcbook/README.md: -------------------------------------------------------------------------------- 1 | # Srcbook 2 | 3 | > 一个开源的 TypeScript 笔记本,在浏览器中运行 TypeScript,提供交互式开发体验 4 | 5 | [![Docker Pulls](https://img.shields.io/docker/pulls/aliuq/srcbook)](https://hub.docker.com/r/aliuq/srcbook) 6 | [![Docker Image Size](https://img.shields.io/docker/image-size/aliuq/srcbook)](https://hub.docker.com/r/aliuq/srcbook) 7 | 8 | ## 项目信息 9 | 10 | - **上游仓库**: [srcbookdev/srcbook](https://github.com/srcbookdev/srcbook) 11 | - **Docker 镜像**: [aliuq/srcbook](https://hub.docker.com/r/aliuq/srcbook) 12 | - **Dockerfile**: [查看构建文件](https://github.com/aliuq/apps-image/tree/master/apps/srcbook) 13 | 14 | > [!WARNING] 15 | > 截止 2025-07-20,暂时无法直接在 https 协议下使用,由于项目 websocket 连接使用的是 `ws://`,会出现错误,请使用 http 协议访问 16 | > 暂时可以使用 tls 标签,`srcbook:tls` 版本中,已经将 `ws://` 替换为 `wss://` 17 | 18 | *官方内部使用了 Posthog,会发送一些匿名数据,如果不希望发送数据,需要手动在源码中去掉,并重新构建镜像* 19 | 20 | ## 快速开始 21 | 22 | ### 使用 Docker 运行 23 | 24 | ```bash 25 | docker run -d --name srcbook -p 2150:2150 aliuq/srcbook:latest 26 | # 挂载目录 27 | docker run -d --name srcbook -v ./srcbook-data:/srcbook -p 2150:2150 aliuq/srcbook:latest 28 | # 测试 29 | docker run --rm --name srcbook -p 2150:2150 aliuq/srcbook:latest 30 | ``` 31 | 32 | 访问 `http://localhost:2150` 即可使用 33 | 34 | ### 使用 Docker Compose 35 | 36 | 创建 `docker-compose.yml` 文件 37 | 38 | ```yaml 39 | name: srcbook 40 | services: 41 | srcbook: 42 | image: aliuq/srcbook:latest 43 | container_name: srcbook 44 | restart: unless-stopped 45 | ports: 46 | - '2150:2150' 47 | volumes: 48 | - ./srcbook-data:/srcbook 49 | ``` 50 | 51 | 运行服务 52 | 53 | ```bash 54 | docker-compose up -d 55 | ``` 56 | 57 | ## 功能特性 58 | 59 | - 📝 **TypeScript 笔记本**: 在浏览器中运行 TypeScript 代码 60 | - ⚡ **实时执行**: 即时运行代码块并查看结果 61 | - 📊 **数据可视化**: 支持图表和数据展示 62 | - 🔄 **热重载**: 代码修改即时生效 63 | - 💾 **数据持久化**: 自动保存笔记本和执行结果 64 | - 🎨 **现代界面**: 清晰直观的用户界面 65 | - 🔗 **模块支持**: 支持 npm 包和模块导入 66 | 67 | ## 开发 68 | 69 | ### 本地构建 70 | 71 | ```bash 72 | # 克隆仓库 73 | git clone https://github.com/aliuq/apps-image.git 74 | cd apps-image/apps/srcbook 75 | 76 | # 构建镜像 77 | docker buildx build -f ./Dockerfile -t srcbook:local --load . 78 | 79 | # 运行测试 80 | docker run --rm --name srcbook-local -p 2150:2150 srcbook:local 81 | ``` 82 | 83 | ### 调试模式 84 | 85 | ```bash 86 | # 显示详细构建日志 87 | docker buildx build --progress=plain -f ./Dockerfile -t srcbook:debug --no-cache --load . 88 | ``` 89 | 90 | ## 相关链接 91 | 92 | - [Srcbook 官网](https://srcbook.com/) 93 | 94 | --- 95 | 96 | > 📝 该文档由 AI 辅助生成并整理,如有问题请随时反馈。 97 | -------------------------------------------------------------------------------- /action/src/lib/validator.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * 验证器 - 使用外部 schema 文件 3 | */ 4 | 5 | import type { Schema, ValidateFunction } from 'ajv' 6 | import path from 'node:path' 7 | import process from 'node:process' 8 | import { Ajv } from 'ajv' 9 | import addFormats from 'ajv-formats' 10 | import { yellow } from 'kolorist' 11 | import { readJson } from '../file.js' 12 | import { createLogger } from '../logger.js' 13 | 14 | export class Validator { 15 | private readonly ajv: Ajv 16 | private validateAppMetaFn?: ValidateFunction 17 | private readonly logger = createLogger('ajv') 18 | 19 | constructor() { 20 | this.ajv = new Ajv({ allErrors: true, verbose: true }) 21 | addFormats.default(this.ajv) 22 | } 23 | 24 | /** 25 | * 加载外部 schema 文件 26 | */ 27 | private async loadSchema() { 28 | try { 29 | if (this.validateAppMetaFn) { 30 | return 31 | } 32 | // 从项目根目录的 .vscode/meta.schema.json 加载 schema 33 | const schemaPath = path.join(process.cwd(), '.vscode', 'meta.schema.json') 34 | const schema = await readJson(schemaPath) 35 | if (!schema) { 36 | this.logger.warn(`Failed to load meta schema at ${schemaPath}`) 37 | return 38 | } 39 | this.validateAppMetaFn = this.ajv.compile(schema) 40 | } 41 | catch (error) { 42 | throw new Error(`Failed to load meta schema: ${error}`) 43 | } 44 | } 45 | 46 | /** 47 | * 验证应用元数据 48 | */ 49 | async validateAppMeta(data: T) { 50 | await this.loadSchema() 51 | if (!this.validateAppMetaFn) { 52 | this.logger.warn(yellow('No validation function available, schema might not be loaded')) 53 | return false 54 | } 55 | 56 | const valid = this.validateAppMetaFn(data) 57 | 58 | if (!valid) { 59 | const errorMessage = this.ajv.errorsText(this.validateAppMetaFn.errors) 60 | this.logger.debug(`Validation failed: ${errorMessage}`) 61 | return false 62 | } 63 | 64 | return data 65 | } 66 | } 67 | 68 | /** 69 | * 缓存的验证器实例 70 | */ 71 | let cachedValidator: Validator | null = null 72 | 73 | /** 74 | * 获取缓存的验证器实例 75 | */ 76 | function getValidator(): Validator { 77 | if (!cachedValidator) { 78 | cachedValidator = new Validator() 79 | } 80 | return cachedValidator 81 | } 82 | 83 | /** 84 | * 验证应用元数据 85 | */ 86 | export async function validateAppMeta(data: T) { 87 | const validator = getValidator() 88 | return await validator.validateAppMeta(data) 89 | } 90 | -------------------------------------------------------------------------------- /apps/telegram-upload/README.md: -------------------------------------------------------------------------------- 1 | # Telegram Upload 2 | 3 | > 一个命令行工具,用于将文件上传到 Telegram,支持大文件分片上传和断点续传 4 | 5 | [![Docker Pulls](https://img.shields.io/docker/pulls/aliuq/telegram-upload)](https://hub.docker.com/r/aliuq/telegram-upload) 6 | [![Docker Image Size](https://img.shields.io/docker/image-size/aliuq/telegram-upload)](https://hub.docker.com/r/aliuq/telegram-upload) 7 | 8 | ## 项目信息 9 | 10 | - **上游仓库**: [Nekmo/telegram-upload](https://github.com/Nekmo/telegram-upload) 11 | - **Docker 镜像**: [aliuq/telegram-upload](https://hub.docker.com/r/aliuq/telegram-upload) 12 | - **Dockerfile**: [查看构建文件](https://github.com/aliuq/apps-image/tree/master/apps/telegram-upload) 13 | - **Documentation**: [查看文档](https://docs.nekmo.org/telegram-upload/usage.html) 14 | 15 | ## 快速开始 16 | 17 | ### 基本用法 18 | 19 | ```bash 20 | # 查看帮助信息 21 | docker run -it --rm --name telegram-upload aliuq/telegram-upload:latest upload --help 22 | ``` 23 | 24 | ## 功能特性 25 | 26 | - 📤 **大文件上传**: 支持大文件分片上传,突破 Telegram 文件大小限制 27 | - 🔄 **断点续传**: 支持上传中断后自动续传 28 | - 📁 **批量上传**: 支持多文件和文件夹批量上传 29 | - 🎯 **精准控制**: 支持指定频道、群组或私聊上传 30 | - 📊 **进度显示**: 实时显示上传进度和速度 31 | - 🔐 **安全认证**: 使用官方 Telegram API,安全可靠 32 | - 💾 **配置持久化**: 支持配置文件保存,避免重复认证 33 | 34 | ## 使用示例 35 | 36 | ### Docker Compose 配置 37 | 38 | 创建 `docker-compose.yml` 文件 39 | 40 | ```yaml 41 | name: telegram-upload 42 | services: 43 | telegram-upload: 44 | image: aliuq/telegram-upload:latest 45 | container_name: telegram-upload 46 | restart: always 47 | command: upload -i 48 | volumes: 49 | - ./config:/config 50 | - ./files:/files 51 | ``` 52 | 53 | ## 开发 54 | 55 | ### 本地构建 56 | 57 | ```bash 58 | # 克隆仓库 59 | git clone https://github.com/aliuq/apps-image.git 60 | cd apps-image/apps/telegram-upload 61 | 62 | # 构建镜像 63 | docker buildx build -f ./Dockerfile -t telegram-upload:local --load . 64 | 65 | # 运行测试 66 | docker run -it --rm --name telegram-upload-local telegram-upload:local upload --help 67 | ``` 68 | 69 | ### 调试模式 70 | 71 | ```bash 72 | # 显示详细构建日志 73 | docker buildx build --progress=plain -f ./Dockerfile -t telegram-upload:debug --no-cache --load . 74 | ``` 75 | 76 | ## 注意事项 77 | 78 | - 首次使用需要提供 Telegram API 凭据(API ID 和 Hash) 79 | - 建议挂载配置目录以避免重复认证 80 | - 大文件上传可能需要较长时间,请耐心等待 81 | - 确保有足够的网络带宽和存储空间 82 | 83 | ## 相关链接 84 | 85 | - [上游项目主页](https://github.com/Nekmo/telegram-upload) 86 | - [Telegram API 文档](https://core.telegram.org/api) 87 | - [获取 API 凭据](https://my.telegram.org/apps) 88 | 89 | --- 90 | 91 | > 📝 该文档由 AI 辅助生成并整理,如有问题请随时反馈 92 | -------------------------------------------------------------------------------- /action/src/check.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * 检查版本更新 3 | * 4 | * 触发方式: 5 | * 6 | * 1 手动触发: 通过 GitHub Actions 手动触发检查 7 | * 2 计划任务: 通过 GitHub Actions 定时任务自动触发检查,默认为每小时检查一次 8 | * 3 Push 推送: 包含有 meta.json 或者 Dockerfile 提交记录的推送会触发检查 9 | */ 10 | import core from '@actions/core' 11 | import { green, yellow } from 'kolorist' 12 | import { checkVersionConfig as config, isAct } from './config.js' 13 | import { CheckAppsManager } from './context/checkAppsManager.js' 14 | import { createLogger } from './logger.js' 15 | 16 | async function main() { 17 | const logger = createLogger() 18 | try { 19 | await logger.json(config, 'Inputs') 20 | core.summary.addHeading('Check Version Results', 2) 21 | 22 | // 1. 初始化应用管理生命周期 23 | const appsManager = new CheckAppsManager() 24 | 25 | // 2. 扫描应用 26 | const appPaths = await appsManager.scanApps() 27 | if (!appPaths?.length) { 28 | logger.warn(yellow('No applications found to process. Skipping version check.')) 29 | return 30 | } 31 | 32 | // 3. 加载应用上下文 33 | await appsManager.loadApps(appPaths) 34 | 35 | // 5. 执行版本检查 36 | const { allApps, outdatedApps } = await appsManager.checkAllVersions() 37 | 38 | if (!outdatedApps?.size) { 39 | logger.info('🎉 All apps are up to date, no updates needed') 40 | core.summary.addRaw(`\n🎉 Total ${allApps.size} apps are up to date, no updates needed\n`) 41 | core.summary.addDetails('Apps', `
${JSON.stringify(appPaths, null, 2)}
`) 42 | } 43 | else { 44 | logger.info(`Total ${green(allApps.size)} apps checked, ${green(outdatedApps.size)} apps needs update`) 45 | } 46 | 47 | // 6. 构建 PR 数据 48 | if (config.createPr || isAct) { 49 | const prResults = await appsManager.buildPrDatas(outdatedApps) 50 | await logger.json(prResults, 'PR Datas') 51 | 52 | if (config.createPr) { 53 | const createPrResults = await appsManager.createPr(prResults) 54 | await logger.json(createPrResults, 'Create PR Results') 55 | appsManager.generateSummary(outdatedApps, allApps, createPrResults) 56 | } 57 | else { 58 | appsManager.generateSummary(outdatedApps, allApps) 59 | } 60 | } 61 | else { 62 | appsManager.generateSummary(outdatedApps, allApps) 63 | } 64 | 65 | core.summary.write() 66 | } 67 | catch (error) { 68 | if (error instanceof Error) { 69 | logger.error(`❌ An error occurred during the version check operation: ${error.message}`) 70 | } 71 | else { 72 | logger.error(`❌ An unexpected error occurred: ${String(error)}`) 73 | } 74 | } 75 | } 76 | 77 | main() 78 | -------------------------------------------------------------------------------- /apps/readest/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM alpine/git AS source 2 | WORKDIR /app 3 | ARG READEST_VERSION=v0.9.93 4 | RUN git clone -b ${READEST_VERSION} --recurse-submodules https://github.com/readest/readest . 5 | 6 | FROM node:22-slim AS base 7 | ENV PNPM_HOME="/pnpm" 8 | ENV PATH="$PNPM_HOME:$PATH" 9 | RUN corepack enable && corepack prepare pnpm@latest-10 --activate 10 | 11 | FROM base AS build 12 | WORKDIR /app 13 | # Uncomment the following line to increase the Node.js memory limit (if needed) 14 | ENV NODE_OPTIONS="--max-old-space-size=6144" 15 | 16 | COPY --from=source /app . 17 | # Copy the variables starting with `NEXT_PUBLIC_` from 18 | # `/app/apps/readest-app/.env.local.example` to /app/apps/readest-app/.env.local, 19 | # and set their values as environment variable placeholders in the format `KEY=\$KEY`. 20 | RUN env_source=/app/apps/readest-app/.env.local.example; \ 21 | env_target=/app/apps/readest-app/.env.local; \ 22 | awk -F= '/^NEXT_PUBLIC_/ && $1 != "" { printf "%s=\$%s\n", $1, $1 }' $env_source >> $env_target && \ 23 | \ 24 | # Replace `NEXT_PUBLIC_SUPABASE_URL` to `https://your-supabase-url.com` placeholder for avoid `Invalid URL` error during build 25 | sed -i 's|^NEXT_PUBLIC_SUPABASE_URL=.*$|NEXT_PUBLIC_SUPABASE_URL=https://your-supabase-url.com|' $env_target 26 | 27 | RUN pnpm install --frozen-lockfile 28 | RUN pnpm --filter=@readest/readest-app setup-pdfjs && \ 29 | pnpm --filter=@readest/readest-app build-web 30 | 31 | # Replace `https://your-supabase-url.com` in `.next` js files with environment variable 32 | RUN find /app/apps/readest-app/.next -name "*.js" -exec sed -i "s|https://your-supabase-url.com|\$NEXT_PUBLIC_SUPABASE_URL|g" {} + 33 | 34 | RUN rm -rf /app/apps/readest-app/.next/cache && \ 35 | pnpm --filter=@readest/readest-app install dotenv-cli @next/bundle-analyzer -P 36 | 37 | FROM base 38 | ENV NODE_ENV=production 39 | WORKDIR /app 40 | 41 | COPY --from=source /app . 42 | COPY --from=build /app/apps/readest-app/package.json /app/apps/readest-app/package.json 43 | COPY --from=build /app/pnpm-lock.yaml /app/pnpm-workspace.yaml ./ 44 | COPY --from=build /app/apps/readest-app/.next /app/apps/readest-app/.next 45 | COPY --from=build /app/apps/readest-app/public /app/apps/readest-app/public 46 | 47 | RUN pnpm fetch --prod && pnpm install -r --offline --prod && \ 48 | \ 49 | # Install gettext for envsubst 50 | apt-get update && apt-get install -y gettext-base && \ 51 | rm -rf /var/lib/apt/lists/* 52 | 53 | # Add at the end to leverage cache 54 | COPY ./docker-entrypoint.sh /docker-entrypoint.sh 55 | 56 | RUN chmod +x /docker-entrypoint.sh && \ 57 | rm -rf packages/tauri* apps/readest-app/src-tauri 58 | 59 | WORKDIR /app/apps/readest-app 60 | ENTRYPOINT ["/docker-entrypoint.sh"] 61 | EXPOSE 3000 62 | -------------------------------------------------------------------------------- /deprecated/tgcf/README.md: -------------------------------------------------------------------------------- 1 | # tgcf 2 | 3 | > Telegram 消息转发工具,支持频道、群组和私聊之间的消息转发和过滤 4 | 5 | [![Docker Pulls](https://img.shields.io/docker/pulls/aliuq/tgcf)](https://hub.docker.com/r/aliuq/tgcf) 6 | [![Docker Image Size](https://img.shields.io/docker/image-size/aliuq/tgcf)](https://hub.docker.com/r/aliuq/tgcf) 7 | 8 | ## 项目信息 9 | 10 | - **上游仓库**: [aahnik/tgcf](https://github.com/aahnik/tgcf) 11 | - **Docker 镜像**: [aliuq/tgcf](https://hub.docker.com/r/aliuq/tgcf) 12 | - **Dockerfile**: [查看构建文件](https://github.com/aliuq/apps-image/tree/master/apps/tgcf) 13 | 14 | ## 快速开始 15 | 16 | ### 使用 Docker 运行 17 | 18 | ```bash 19 | docker run -d --name tgcf -p 8501:8501 aliuq/tgcf:latest 20 | ``` 21 | 22 | 访问 `http://localhost:8501` 即可使用 23 | 24 | ### 使用 Docker Compose 25 | 26 | 创建 `docker-compose.yml` 文件: 27 | 28 | ```yaml 29 | version: '3.8' 30 | services: 31 | tgcf: 32 | image: aliuq/tgcf:latest 33 | container_name: tgcf 34 | restart: unless-stopped 35 | ports: 36 | - '8501:8501' 37 | ``` 38 | 39 | 运行服务: 40 | 41 | ```bash 42 | docker-compose up -d 43 | ``` 44 | 45 | ## 功能特性 46 | 47 | - 📤 **消息转发**: 支持频道、群组、私聊之间的消息转发 48 | - 🔍 **内容过滤**: 支持基于关键词、用户、媒体类型的消息过滤 49 | - 🎛️ **Web 界面**: 提供直观的 Streamlit Web 界面进行配置 50 | - 📝 **格式化**: 支持消息格式化和自定义模板 51 | - 🔗 **批量转发**: 支持多个源到多个目标的批量转发 52 | - ⚙️ **灵活配置**: 支持 YAML 配置文件和环境变量配置 53 | - 📊 **实时监控**: 实时显示转发状态和统计信息 54 | 55 | ## 使用方法 56 | 57 | ### 初始配置 58 | 59 | 1. **启动服务**: 使用上述 Docker 命令启动服务 60 | 2. **访问界面**: 打开浏览器访问 `http://localhost:8501` 61 | 3. **配置 API**: 输入 Telegram API ID 和 Hash 62 | 4. **设置转发规则**: 配置源和目标聊天 63 | 5. **启动转发**: 开始自动转发消息 64 | 65 | ### 获取 Telegram API 凭据 66 | 67 | 1. 访问 [my.telegram.org](https://my.telegram.org/) 68 | 2. 登录您的 Telegram 账户 69 | 3. 创建应用程序获取 API ID 和 Hash 70 | 71 | ## 开发 72 | 73 | ### 本地构建 74 | 75 | ```bash 76 | # 克隆仓库 77 | git clone https://github.com/aliuq/apps-image.git 78 | cd apps-image/apps/tgcf 79 | 80 | # 构建镜像 81 | docker buildx build -f ./Dockerfile -t tgcf:local --load . 82 | 83 | # 运行测试 84 | docker run --rm --name tgcf-local -p 8501:8501 tgcf:local 85 | ``` 86 | 87 | ### 调试模式 88 | 89 | ```bash 90 | # 显示详细构建日志 91 | docker buildx build --progress=plain -f ./Dockerfile -t tgcf:debug --no-cache --load . 92 | 93 | # 交互式运行容器 94 | docker run -it --rm --name tgcf-debug -p 8501:8501 tgcf:debug 95 | ``` 96 | 97 | ## 注意事项 98 | 99 | - 需要有效的 Telegram API 凭据才能使用 100 | - 建议挂载配置目录以持久化设置 101 | - 转发大量消息可能触发 Telegram API 限制 102 | - 请遵守相关法律法规和平台规则 103 | 104 | ## 相关链接 105 | 106 | - [上游项目主页](https://github.com/aahnik/tgcf) 107 | - [Telegram API 文档](https://core.telegram.org/api) 108 | - [获取 API 凭据](https://my.telegram.org/) 109 | 110 | --- 111 | 112 | > 📝 该文档由 AI 辅助生成并整理,如有问题请随时反馈 113 | -------------------------------------------------------------------------------- /eslint.config.mjs: -------------------------------------------------------------------------------- 1 | import antfu from '@antfu/eslint-config' 2 | 3 | export default antfu( 4 | { 5 | type: 'lib', 6 | typescript: true, 7 | jsonc: true, 8 | yaml: true, 9 | javascript: true, 10 | ignores: ['dist', 'node_modules', '.history'], 11 | }, 12 | { 13 | files: ['action/**/*.ts'], 14 | rules: { 15 | 'ts/explicit-function-return-type': 'off', 16 | }, 17 | }, 18 | { 19 | files: ['spec/**/*.spec.js'], 20 | rules: { 21 | 'no-console': 'off', 22 | }, 23 | }, 24 | { 25 | files: ['**/*/meta.json'], 26 | rules: { 27 | 'jsonc/array-element-newline': ['error', 'consistent'], 28 | 'jsonc/array-bracket-newline': ['error', { multiline: true, minItems: 1 }], 29 | 'jsonc/sort-keys': [ 30 | 'error', 31 | { 32 | pathPattern: '^$', 33 | order: [ 34 | 'name', 35 | 'type', 36 | 'title', 37 | 'slogan', 38 | 'description', 39 | 'license', 40 | 'context', 41 | 'readme', 42 | 'variants', 43 | 'skip', 44 | ], 45 | }, 46 | { 47 | // variants.*.checkver 字段排序 48 | pathPattern: '^variants\\..+\\.checkver$', 49 | order: [ 50 | 'type', 51 | 'repo', 52 | 'branch', 53 | 'file', 54 | 'regex', 55 | 'tagPattern', 56 | 'targetVersion', 57 | 'processFiles', 58 | 'checkFrequency', 59 | 'lastCheck', 60 | ], 61 | }, 62 | { 63 | // variants.*.docker.cache 字段排序 64 | pathPattern: '^variants\\..+\\.docker\\.cache$', 65 | order: [ 66 | 'from', 67 | 'to', 68 | ], 69 | }, 70 | { 71 | // variants.*.docker 字段排序 72 | pathPattern: '^variants\\..+\\.docker$', 73 | order: [ 74 | 'file', 75 | 'images', 76 | 'tags', 77 | 'platforms', 78 | 'labels', 79 | 'buildArgs', 80 | 'secrets', 81 | 'outputs', 82 | 'cache', 83 | 'push', 84 | 'load', 85 | ], 86 | }, 87 | { 88 | // variants.* 字段排序 89 | pathPattern: '^variants\\..+$', 90 | order: [ 91 | 'version', 92 | 'sha', 93 | 'enabled', 94 | 'checkver', 95 | 'docker', 96 | ], 97 | }, 98 | ], 99 | }, 100 | }, 101 | { 102 | ignores: ['**/dist', '**/build', '.github/instructions'], 103 | }, 104 | ) 105 | -------------------------------------------------------------------------------- /apps/jsonhero-web/README.md: -------------------------------------------------------------------------------- 1 | # JSON Hero Web 2 | 3 | > 一个开源、美观的 Web JSON 浏览器,让您能够快速浏览、搜索和导航 JSON 文件 4 | 5 | [![Docker Pulls](https://img.shields.io/docker/pulls/aliuq/jsonhero-web)](https://hub.docker.com/r/aliuq/jsonhero-web) 6 | [![Docker Image Size](https://img.shields.io/docker/image-size/aliuq/jsonhero-web)](https://hub.docker.com/r/aliuq/jsonhero-web) 7 | 8 | ## 项目信息 9 | 10 | - **上游仓库**: [triggerdotdev/jsonhero-web](https://github.com/triggerdotdev/jsonhero-web) 11 | - **Docker 镜像**: [aliuq/jsonhero-web](https://hub.docker.com/r/aliuq/jsonhero-web) 12 | - **Dockerfile**: [查看构建文件](https://github.com/aliuq/apps-image/tree/master/apps/jsonhero-web) 13 | 14 | ## 快速开始 15 | 16 | ### 使用 Docker 运行 17 | 18 | ```bash 19 | docker run -d --name jsonhero-web -p 8787:8787 -e SESSION_SECRET= aliuq/jsonhero-web:latest 20 | # 测试 21 | docker run --rm --name jsonhero-web -p 8787:8787 -e SESSION_SECRET=test-secret aliuq/jsonhero-web:latest 22 | ``` 23 | 24 | 访问 `http://localhost:8787` 即可使用 25 | 26 | ### 使用 Docker Compose 27 | 28 | 创建 `docker-compose.yml` 文件: 29 | 30 | ```yaml 31 | name: jsonhero-web 32 | services: 33 | jsonhero-web: 34 | image: aliuq/jsonhero-web:latest 35 | container_name: jsonhero-web 36 | restart: unless-stopped 37 | ports: 38 | - '8787:8787' 39 | environment: 40 | - SESSION_SECRET= 41 | ``` 42 | 43 | 运行服务: 44 | 45 | ```bash 46 | docker-compose up -d 47 | ``` 48 | 49 | ## 功能特性 50 | 51 | - 🔍 **快速搜索**: 在大型 JSON 文件中快速搜索特定字段或值 52 | - 🌳 **树状浏览**: 直观的树形结构展示 JSON 数据 53 | - 📱 **响应式设计**: 完美适配桌面和移动设备 54 | - 🎨 **美观界面**: 现代化的 UI 设计,支持语法高亮 55 | - 📊 **数据类型识别**: 自动识别并高亮不同的数据类型 56 | - 🔗 **URL 分享**: 生成可分享的链接,方便团队协作 57 | - 💾 **本地存储**: 支持本地文件上传和在线 JSON 数据 58 | 59 | ## 配置选项 60 | 61 | ### 环境变量 62 | 63 | | 变量名 | 必需 | 默认值 | 描述 | 64 | |--------|------|--------|------| 65 | | `SESSION_SECRET` | 是 | - | 会话加密密钥,用于安全认证 | 66 | 67 | ## 使用方法 68 | 69 | 1. **上传 JSON**: 将 JSON 文件拖拽到页面或粘贴 JSON 内容 70 | 2. **浏览数据**: 使用树状结构浏览 JSON 数据 71 | 3. **搜索内容**: 使用搜索功能快速定位特定字段 72 | 4. **分享链接**: 生成可分享的链接供他人查看 73 | 74 | ## 开发 75 | 76 | ### 本地构建 77 | 78 | ```bash 79 | # 克隆仓库 80 | git clone https://github.com/aliuq/apps-image.git 81 | cd apps-image/apps/jsonhero-web 82 | 83 | # 构建镜像 84 | docker buildx build -f ./Dockerfile -t jsonhero-web:local --load . 85 | 86 | # 运行测试 87 | docker run --rm --name jsonhero-web-local -p 8787:8787 -e SESSION_SECRET=test-secret jsonhero-web:local 88 | ``` 89 | 90 | ### 调试模式 91 | 92 | ```bash 93 | # 显示详细构建日志 94 | docker buildx build --progress=plain -f ./Dockerfile -t jsonhero-web:debug --no-cache --load . 95 | ``` 96 | 97 | ## 相关链接 98 | 99 | - [JSON Hero 官网](https://jsonhero.io/) 100 | 101 | --- 102 | 103 | > 📝 该文档由 AI 辅助生成并整理,如有问题请随时反馈 104 | -------------------------------------------------------------------------------- /.github/workflows/check-version.yaml: -------------------------------------------------------------------------------- 1 | name: Check Version 2 | 3 | on: 4 | schedule: 5 | - cron: '0 */2 * * *' # 每 2 小时检查一次 6 | workflow_dispatch: 7 | inputs: 8 | context: 9 | description: 上下文目录,例如 apps/icones 10 | type: choice 11 | default: all 12 | options: 13 | - all 14 | # ContextStart 15 | - apps/cobalt 16 | - apps/haitang 17 | - apps/icones 18 | - apps/inpaint-web 19 | - apps/jsonhero-web 20 | - apps/lsky 21 | - apps/memogram 22 | - apps/n8n-workflows 23 | - apps/readest 24 | - apps/srcbook 25 | - apps/telegram-upload 26 | - apps/telemirror 27 | - apps/weektodo 28 | - apps/weserv 29 | - apps/yulegeyu 30 | - base/alpine 31 | - base/nginx 32 | - base/self 33 | - base/tg-session 34 | - base/vscode 35 | - test/icones 36 | - test/self 37 | - test/weektodo 38 | - test/weektodo-mul 39 | # ContextEnd 40 | create_pr: 41 | description: 是否创建 PR 42 | type: choice 43 | default: 'false' 44 | options: 45 | - 'true' 46 | - 'false' 47 | - development 48 | debug: 49 | description: Debug 模式 50 | type: boolean 51 | default: false 52 | push: 53 | branches: 54 | - master 55 | paths: 56 | - apps/*/meta.json 57 | - apps/*/Dockerfile 58 | - apps/*/Dockerfile.* 59 | - base/*/meta.json 60 | - base/*/Dockerfile 61 | - base/*/Dockerfile.* 62 | - test/*/meta.json 63 | - test/*/Dockerfile 64 | - test/*/Dockerfile.* 65 | 66 | jobs: 67 | check-version: 68 | name: Check Version 69 | runs-on: ubuntu-latest 70 | if: github.event_name == 'workflow_dispatch' || github.event_name == 'schedule' || (github.event_name == 'push' && github.event.head_commit && !contains(github.event.head_commit.message, '[skip check]')) 71 | permissions: 72 | contents: read 73 | steps: 74 | - name: Checkout 75 | uses: actions/checkout@v4 76 | with: 77 | fetch-depth: 0 # 0 = 完整历史 78 | 79 | - name: Cache Git repositories 80 | uses: actions/cache@v4 81 | with: 82 | path: .git-cache 83 | key: git-repos-${{ hashFiles('**/meta.json') }} 84 | restore-keys: | 85 | git-repos- 86 | 87 | - name: Check Version 88 | uses: ./action/check-version 89 | env: 90 | TZ: Asia/Shanghai 91 | with: 92 | token: ${{ secrets.PAT }} 93 | context: ${{ inputs.context }} 94 | create_pr: ${{ inputs.create_pr }} 95 | debug: ${{ inputs.debug }} 96 | -------------------------------------------------------------------------------- /apps/readest/docker-entrypoint.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | set -e 4 | 5 | ME=$(basename "$0") 6 | 7 | entrypoint_log() { 8 | if [ -z "${ENTRYPOINT_QUIET_LOGS:-}" ]; then 9 | echo "$@" 10 | fi 11 | } 12 | 13 | # Get environment variable from .env file and decode from base64 14 | # Returns decoded value or empty string if not found/invalid 15 | get_env_decoded() { 16 | local key="$1" 17 | local value 18 | local env_path="/app/apps/readest-app/.env" 19 | 20 | # Extract value from .env file 21 | value=$(grep -E "^[[:space:]]*$key=" "$env_path" 2>/dev/null | grep -v '^#' | tail -n1 | cut -d'=' -f2- | tr -d '"' | tr -d "'") 22 | 23 | # Check if value exists 24 | if [ -z "$value" ]; then 25 | entrypoint_log "$ME: Warning - Variable $key not found in $env_path file" 26 | return 1 27 | fi 28 | 29 | # Try to decode base64, handle errors gracefully 30 | local decoded 31 | decoded=$(echo "$value" | base64 --decode 2>/dev/null) 32 | 33 | if [ $? -ne 0 ] || [ -z "$decoded" ]; then 34 | entrypoint_log "$ME: Warning - Failed to decode base64 value for $key" 35 | return 1 36 | fi 37 | 38 | echo "$decoded" 39 | return 0 40 | } 41 | 42 | auto_envsubst() { 43 | local default_posthog_host=$(get_env_decoded "NEXT_PUBLIC_DEFAULT_POSTHOG_URL_BASE64") || default_posthog_host="" 44 | local default_posthog_key=$(get_env_decoded "NEXT_PUBLIC_DEFAULT_POSTHOG_KEY_BASE64") || default_posthog_key="" 45 | local default_supabase_url=$(get_env_decoded "NEXT_PUBLIC_DEFAULT_SUPABASE_URL_BASE64") || default_supabase_url="" 46 | local default_supabase_anon_key=$(get_env_decoded "NEXT_PUBLIC_DEFAULT_SUPABASE_KEY_BASE64") || default_supabase_anon_key="" 47 | 48 | export NEXT_PUBLIC_POSTHOG_HOST=${NEXT_PUBLIC_POSTHOG_HOST:-$default_posthog_host} 49 | export NEXT_PUBLIC_POSTHOG_KEY=${NEXT_PUBLIC_POSTHOG_KEY:-$default_posthog_key} 50 | export NEXT_PUBLIC_SUPABASE_URL=${NEXT_PUBLIC_SUPABASE_URL:-$default_supabase_url} 51 | export NEXT_PUBLIC_SUPABASE_ANON_KEY=${NEXT_PUBLIC_SUPABASE_ANON_KEY:-$default_supabase_anon_key} 52 | export NEXT_PUBLIC_STORAGE_FIXED_QUOTA=${NEXT_PUBLIC_STORAGE_FIXED_QUOTA:-0} 53 | export NEXT_PUBLIC_API_BASE_URL=${NEXT_PUBLIC_API_BASE_URL:-} 54 | export NEXT_PUBLIC_OBJECT_STORAGE_TYPE=${NEXT_PUBLIC_OBJECT_STORAGE_TYPE:-} 55 | 56 | local filter="${ENVSUBST_FILTER:-}" 57 | 58 | defined_envs=$(printf '${%s} ' $(awk "END { for (name in ENVIRON) { print ( name ~ /${filter}/ ) ? name : \"\" } }" "$template.1" 64 | mv "$template.1" "$template" 65 | done 66 | 67 | entrypoint_log "$ME: Environment variables replaced successfully" 68 | } 69 | 70 | auto_envsubst 71 | 72 | pnpm start-web 73 | -------------------------------------------------------------------------------- /apps/telemirror/README.md: -------------------------------------------------------------------------------- 1 | # Telemirror 2 | 3 | > 一个 Telegram 消息镜像工具,可以将 Telegram 频道/群组的消息转发到其他频道或群组 4 | 5 | [![Docker Pulls](https://img.shields.io/docker/pulls/aliuq/telemirror)](https://hub.docker.com/r/aliuq/telemirror) 6 | [![Docker Image Size](https://img.shields.io/docker/image-size/aliuq/telemirror)](https://hub.docker.com/r/aliuq/telemirror) 7 | 8 | ## 项目信息 9 | 10 | - **上游仓库**: [khoben/telemirror](https://github.com/khoben/telemirror) 11 | - **Docker 镜像**: [aliuq/telemirror](https://hub.docker.com/r/aliuq/telemirror) 12 | - **Dockerfile**: [查看构建文件](https://github.com/aliuq/apps-image/tree/master/apps/telemirror) 13 | 14 | ## 快速开始 15 | 16 | ### 使用 Docker Compose 17 | 18 | 创建 `docker-compose.yml` 文件 19 | 20 | ```yaml 21 | name: telemirror 22 | services: 23 | telemirror: 24 | image: aliuq/telemirror:latest 25 | restart: unless-stopped 26 | environment: 27 | - API_ID= 28 | - API_HASH= 29 | - SESSION_STRING= 30 | - USE_MEMORY_DB=false 31 | - DATABASE_URL=postgres://postgres:postgres@postgres:5432/telemirror 32 | - LOG_LEVEL=info 33 | volumes: 34 | - ./.configs:/app/.configs:ro 35 | ports: 36 | - '8000:8000' 37 | depends_on: 38 | - postgres 39 | 40 | postgres: 41 | image: postgres:15 42 | restart: unless-stopped 43 | environment: 44 | POSTGRES_DB: telemirror 45 | POSTGRES_USER: postgres 46 | POSTGRES_PASSWORD: postgres 47 | volumes: 48 | - ./pg_data:/var/lib/postgresql/data 49 | ``` 50 | 51 | 运行服务: 52 | 53 | ```bash 54 | docker-compose up -d 55 | ``` 56 | 57 | ## 功能特性 58 | 59 | - 🔄 **消息转发**: 自动转发 Telegram 频道或群组消息 60 | - 📱 **多平台支持**: 支持频道到频道、群组到群组的转发 61 | - 🎯 **精确控制**: 支持过滤规则和转发条件设置 62 | - 📊 **实时监控**: 提供 Web 界面查看转发状态和统计 63 | - 🔧 **灵活配置**: 支持多种配置选项和自定义规则 64 | - 💾 **数据持久化**: 保存转发记录和配置信息 65 | - 📝 **日志记录**: 详细的操作日志和错误记录 66 | 67 | ## 使用方法 68 | 69 | ### 获取 Telegram API 凭据 70 | 71 | 1. 访问 [my.telegram.org](https://my.telegram.org/) 72 | 2. 登录您的 Telegram 账户 73 | 3. 创建应用程序获取 API ID 和 Hash 74 | 75 | ## 开发 76 | 77 | ### 本地构建 78 | 79 | ```bash 80 | # 克隆仓库 81 | git clone https://github.com/aliuq/apps-image.git 82 | cd apps-image/apps/telemirror 83 | 84 | # 构建镜像 85 | docker buildx build -f ./Dockerfile -t telemirror:local --load . 86 | 87 | # 运行测试 88 | docker run --rm --name telemirror-local -p 8000:8000 telemirror:local 89 | ``` 90 | 91 | ### 调试模式 92 | 93 | ```bash 94 | # 显示详细构建日志 95 | docker buildx build --progress=plain -f ./Dockerfile -t telemirror:debug --no-cache --load . 96 | ``` 97 | 98 | ## 注意事项 99 | 100 | - 需要有效的 Telegram API 凭据才能使用 101 | - 建议挂载配置目录以持久化设置 102 | - 转发大量消息可能触发 Telegram API 限制 103 | - 请遵守相关法律法规和平台规则 104 | 105 | ## 相关链接 106 | 107 | - [Telegram API 文档](https://core.telegram.org/api) 108 | - [获取 API 凭据](https://my.telegram.org/) 109 | 110 | --- 111 | 112 | > 📝 该文档由 AI 辅助生成并整理,如有问题请随时反馈 113 | -------------------------------------------------------------------------------- /.github/workflows/sync-readme.yaml: -------------------------------------------------------------------------------- 1 | name: Update README 2 | 3 | on: 4 | push: 5 | branches: 6 | - master 7 | paths: 8 | - apps/*/README.md 9 | - base/*/README.md 10 | 11 | jobs: 12 | sync-readme: 13 | runs-on: ubuntu-latest 14 | permissions: 15 | contents: write 16 | steps: 17 | - name: Checkout 18 | uses: actions/checkout@v4 19 | with: 20 | fetch-depth: 0 # 获取完整历史记录 21 | 22 | - name: Prepare 23 | id: prepare 24 | uses: aliuq/script-action@v1 25 | with: 26 | auto_install: true 27 | script: | 28 | import fs from 'node:fs' 29 | import path from 'node:path' 30 | 31 | const gcwd = process.env.GITHUB_WORKSPACE 32 | 33 | // 获取最近一次提交的文件 34 | const changedFiles = await execCommand(`git -C ${gcwd} diff-tree --no-commit-id --name-only -r HEAD`) 35 | await core.group('Changed files', async () => core.info(changedFiles)) 36 | 37 | // 过滤出 README.md 文件 38 | const files = changedFiles.split('\n').filter(file => file.match(/^apps\/.*\/README\.md$/)) 39 | await core.group('README.md files', async () => core.info(files.join('\n'))) 40 | 41 | if (!files.length) { 42 | core.info('No README.md files changed') 43 | core.setOutput('status', 'success') 44 | process.exit(0) 45 | } 46 | 47 | const readmePath = files[files.length - 1] 48 | const appDir = path.dirname(readmePath) 49 | const metaFile = path.join(gcwd, appDir, 'meta.json') 50 | const meta = JSON.parse(fs.readFileSync(metaFile, 'utf-8')) 51 | 52 | const docker = meta.dockerMeta 53 | const skip = meta.skip || false 54 | 55 | const images = docker.images 56 | const matchDockerhub = images.find(i => i.match(/^aliuq\//)) 57 | const matchGhcr = images.find(i => i.match(/^ghcr.io\//)) 58 | 59 | const repo = matchDockerhub ? matchDockerhub : matchGhcr ? matchGhcr?.replace(/^ghcr.io\//, '') : '' 60 | const data = { repo } 61 | if (docker.readme_path !== false) { 62 | data.readme_path = path.join(appDir, docker.readme_path || 'README.md') 63 | } 64 | 65 | if (skip) { 66 | core.info('Skip sync README') 67 | core.setOutput('status', 'success') 68 | process.exit(0) 69 | } else { 70 | await core.group('JSON Output', async () => core.info(JSON.stringify(data, null, 2))) 71 | outputJson(data) 72 | } 73 | 74 | - name: Sync README 75 | uses: peter-evans/dockerhub-description@v4 76 | if: steps.prepare.outputs.repo != '' && steps.prepare.outputs.readme_path != '' 77 | with: 78 | username: ${{ secrets.DOCKERHUB_USERNAME }} 79 | password: ${{ secrets.DOCKERHUB_TOKEN }} 80 | repository: ${{ steps.prepare.outputs.repo }} 81 | readme-filepath: ${{ steps.prepare.outputs.readme_path }} 82 | -------------------------------------------------------------------------------- /apps/weserv/Dockerfile.alpine: -------------------------------------------------------------------------------- 1 | FROM alpine/git AS source 2 | WORKDIR /app 3 | ARG BRANCH=5.x 4 | ARG VERSION=a4dd91e 5 | RUN git clone -b ${BRANCH} --recurse-submodules https://github.com/weserv/images . && git checkout ${VERSION} 6 | 7 | # Based on: 8 | # https://github.com/nginx/pkg-oss/blob/master/alpine/Makefile 9 | # https://github.com/nginxinc/docker-nginx/blob/master/mainline/alpine/Dockerfile 10 | FROM alpine:3.22 11 | 12 | LABEL maintainer="Kleis Auke Wolthuizen " 13 | 14 | ARG NGINX_VERSION=1.29.0 15 | 16 | # Copy the contents of this repository to the container 17 | COPY --from=source /app /var/www/imagesweserv 18 | WORKDIR /var/www/imagesweserv 19 | 20 | # Create nginx user/group 21 | RUN addgroup -g 101 -S nginx \ 22 | && adduser -S -D -H -u 101 -h /var/cache/nginx -s /sbin/nologin -G nginx -g nginx nginx \ 23 | # Bring in build dependencies 24 | && apk add --no-cache --virtual .build-deps \ 25 | build-base \ 26 | cmake \ 27 | git \ 28 | openssl-dev \ 29 | pcre2-dev \ 30 | vips-dev \ 31 | # Build CMake-based project 32 | && cmake -S . -B _build \ 33 | -DCMAKE_BUILD_TYPE=Release \ 34 | -DBUILD_TOOLS=ON \ 35 | -DNGX_VERSION=$NGINX_VERSION \ 36 | -DCUSTOM_NGX_FLAGS="--prefix=/etc/nginx;\ 37 | --sbin-path=/usr/sbin/nginx;\ 38 | --modules-path=/usr/lib/nginx/modules;\ 39 | --conf-path=/etc/nginx/nginx.conf;\ 40 | --error-log-path=/var/log/nginx/error.log;\ 41 | --http-log-path=/var/log/nginx/access.log;\ 42 | --http-client-body-temp-path=/var/cache/nginx/client_temp;\ 43 | --http-proxy-temp-path=/var/cache/nginx/proxy_temp;\ 44 | --http-fastcgi-temp-path=/var/cache/nginx/fastcgi_temp;\ 45 | --http-uwsgi-temp-path=/var/cache/nginx/uwsgi_temp;\ 46 | --http-scgi-temp-path=/var/cache/nginx/scgi_temp;\ 47 | --pid-path=/run/nginx.pid;\ 48 | --lock-path=/run/nginx.lock;\ 49 | --user=nginx;\ 50 | --group=nginx" \ 51 | && cmake --build _build -- -j$(nproc) \ 52 | # Remove build directory and dependencies 53 | && rm -rf _build \ 54 | && apk del --no-network .build-deps \ 55 | # Bring in runtime dependencies 56 | && apk add --no-cache \ 57 | openssl \ 58 | pcre2 \ 59 | vips-cpp \ 60 | vips-heif \ 61 | vips-magick \ 62 | vips-poppler \ 63 | # Bring in tzdata so users could set the timezones through the environment variables 64 | && apk add --no-cache tzdata \ 65 | # Ensure nginx cache directory exist with the correct permissions 66 | && mkdir -m 700 /var/cache/nginx \ 67 | # Forward request and error logs to docker log collector 68 | && ln -sf /dev/stdout /var/log/nginx/weserv-access.log \ 69 | && ln -sf /dev/stderr /var/log/nginx/weserv-error.log \ 70 | # Copy nginx configuration to the appropriate location 71 | && cp ngx_conf/*.conf /etc/nginx 72 | 73 | # Set default timezone (can be overridden with -e "TZ=Continent/City") 74 | ENV TZ=Europe/Amsterdam \ 75 | # Increase the minimum stack size to 2MB 76 | VIPS_MIN_STACK_SIZE=2m 77 | 78 | EXPOSE 80 79 | 80 | STOPSIGNAL SIGQUIT 81 | 82 | CMD ["nginx", "-g", "daemon off;"] 83 | -------------------------------------------------------------------------------- /.github/instructions/basic.instructions.md: -------------------------------------------------------------------------------- 1 | --- 2 | applyTo: '**' 3 | --- 4 | 5 | # 角色设定 6 | 7 | 作为一名高级开发人员,你是一位经验丰富的软件开发专家与编码助手,精通所有主流编程语言与框架。你的用户是一名独立开发者,正在进行个人或自由职业项目开发。你的职责是协助生成高质量代码、优化性能、并主动发现和解决技术问题。 8 | 9 | --- 10 | 11 | # 核心目标 12 | 13 | 高效协助用户开发代码,并在无需反复提示的前提下主动解决问题。关注以下核心任务: 14 | 15 | - 编写代码 16 | - 优化代码 17 | - 调试与问题解决 18 | 19 | 确保所有解决方案都清晰易懂,逻辑严密。 20 | 21 | --- 22 | 23 | ## 阶段一:初始评估 24 | 25 | 1. 用户发出请求时,优先检查项目中的 `README.md` 文档以理解整体架构与目标。 26 | 2. 若无文档,主动创建一份 `README.md`,包括功能说明、使用方式和核心参数。 27 | 3. 利用已有上下文(文件、代码)充分理解需求,避免偏差。 28 | 29 | --- 30 | 31 | ## 阶段二:代码实现 32 | 33 | ### 1. 明确需求 34 | - 主动确认需求是否清晰,若有疑问,应立即询问。 35 | - 推荐最简单有效的方案,避免不必要的复杂设计。 36 | 37 | ### 2. 编写代码 38 | - 阅读现有代码,明确实现步骤。 39 | - 选择合适语言与框架,并遵循最佳实践(如 SOLID 原则)。 40 | - 编写简洁、可读、带注释的代码。 41 | - 优化可维护性与性能。 42 | - 按需提供单元测试。 43 | - 遵循语言标准编码规范(如 Python 使用 PEP 8)。 44 | 45 | ### 3. 调试与问题解决 46 | - 系统化分析问题,找出根因。 47 | - 明确说明问题来源及解决方式。 48 | - 在问题解决过程中持续与用户沟通,如需求变动能快速适应。 49 | 50 | --- 51 | 52 | ## 阶段三:完成与总结 53 | 54 | 1. 清晰总结本轮改动、完成目标与优化内容。 55 | 2. 标注潜在风险或需留意的边界情况。 56 | 3. 更新项目文档(如 `README.md`)以反映最新进展。 57 | 58 | --- 59 | 60 | # 最佳实践 61 | 62 | ### Sequential Thinking(逐步思考工具) 63 | 64 | 使用 [Sequential Thinking](https://github.com/smithery-ai/reference-servers/tree/main/src/sequentialthinking) 工具,以结构化的思维方式处理复杂、开放性问题。 65 | 66 | - 将任务拆解为若干 **思维步骤(thought steps)**。 67 | - 每一步应包括: 68 | 1.**明确当前目标或假设**(如:“分析登录方案”,“优化状态管理结构”)。 69 | 2.**调用合适的 MCP 工具**(如 `search_docs`、`code_generator`、`error_explainer`),用于执行查文档、生成代码或解释错误等操作。Sequential Thinking 本身不产出代码,而是协调过程。 70 | 3.**清晰记录本步骤的结果与输出**。 71 | 4.**确定下一步目标或是否分支**,并继续流程。 72 | 73 | - 在面对不确定或模糊任务时: 74 | - 使用“分支思考”探索多种方案。 75 | - 比较不同路径的优劣,必要时回滚或修改已完成的步骤。 76 | 77 | - 每个步骤可带有如下结构化元数据: 78 | -`thought`: 当前思考内容 79 | -`thoughtNumber`: 当前步骤编号 80 | -`totalThoughts`: 预估总步骤数 81 | -`nextThoughtNeeded`, `needsMoreThoughts`: 是否需要继续思考 82 | -`isRevision`, `revisesThought`: 是否为修订行为,及其修订对象 83 | -`branchFromThought`, `branchId`: 分支起点编号及标识 84 | 85 | - 推荐在以下场景使用: 86 | - 问题范围模糊或随需求变化 87 | - 需要不断迭代、修订、探索多解 88 | - 跨步骤上下文保持一致尤为重要 89 | - 需要过滤不相关或干扰性信息 90 | 91 | --- 92 | 93 | ### Context7(最新文档集成工具) 94 | 95 | 使用 [Context7](https://github.com/upstash/context7) 工具获取特定版本的最新官方文档与代码示例,用于提升生成代码的准确性与当前性。 96 | 97 | -**目的**:解决模型知识过时问题,避免生成已废弃或错误的 API 用法。 98 | 99 | -**使用方式**: 100 | 1.**调用方式**:在提示词中加入 `use context7` 触发文档检索。 101 | 2.**获取文档**:Context7 会拉取当前使用框架/库的相关文档片段。 102 | 3.**集成内容**:将获取的示例与说明合理集成到你的代码生成或分析中。 103 | 104 | -**按需使用**:**仅在需要时调用 Context7**,例如遇到 API 模糊、版本差异大或用户请求查阅官方用法。避免不必要的调用,以节省 token 并提高响应效率。 105 | 106 | -**集成方式**: 107 | - 支持 Cursor、Claude Desktop、Windsurf 等 MCP 客户端。 108 | - 通过配置服务端集成 Context7,即可在上下文中获取最新参考资料。 109 | 110 | -**优势**: 111 | - 提升代码准确性,减少因知识过时造成的幻觉与报错。 112 | - 避免依赖训练时已过期的框架信息。 113 | - 提供明确、权威的技术参考材料。 114 | 115 | --- 116 | 117 | # 沟通规范 118 | 119 | - 所有内容必须使用 **中文** 交流(包括代码注释),但是文案与错误提示要使用英文。 120 | - 遇到不清楚的内容应立即向用户提问。 121 | - 表达清晰、简洁、技术准确。 122 | - 在代码中应添加必要的注释解释关键逻辑。 123 | -------------------------------------------------------------------------------- /apps/memogram/README.md: -------------------------------------------------------------------------------- 1 | # Memogram 2 | 3 | > Memos 的 Telegram 机器人集成,让您可以通过 Telegram 轻松管理和分享您的备忘录 4 | 5 | [![Docker Pulls](https://img.shields.io/docker/pulls/aliuq/memogram)](https://hub.docker.com/r/aliuq/memogram) 6 | [![Docker Image Size](https://img.shields.io/docker/image-size/aliuq/memogram)](https://hub.docker.com/r/aliuq/memogram) 7 | 8 | ## 项目信息 9 | 10 | - **上游仓库**: [usememos/telegram-integration](https://github.com/usememos/telegram-integration) 11 | - **Docker 镜像**: [aliuq/memogram](https://hub.docker.com/r/aliuq/memogram) 12 | - **Dockerfile**: [查看构建文件](https://github.com/aliuq/apps-image/tree/master/apps/memogram) 13 | 14 | ## 快速开始 15 | 16 | ### 使用 Docker Compose 17 | 18 | 创建 `docker-compose.yml` 文件: 19 | 20 | ```yaml 21 | name: memos 22 | services: 23 | memos: 24 | image: ghcr.io/usememos/memos:latest 25 | restart: unless-stopped 26 | container_name: memos 27 | ports: 28 | - 5230:5230 29 | volumes: 30 | - ./data:/var/opt/memos 31 | env_file: .env 32 | 33 | memogram: 34 | image: aliuq/memogram:latest 35 | restart: unless-stopped 36 | container_name: memogram 37 | environment: 38 | - SERVER_ADDR=dns:memos:5230 39 | - BOT_TOKEN=${BOT_TOKEN} 40 | depends_on: 41 | - memos 42 | ``` 43 | 44 | 运行服务: 45 | 46 | ```bash 47 | docker-compose up -d 48 | ``` 49 | 50 | ## 功能特性 51 | 52 | - 🤖 **Telegram 机器人**: 通过 Telegram 创建、查看和管理备忘录 53 | - 📝 **快速记录**: 发送消息即可快速创建备忘录 54 | - 🔍 **搜索功能**: 在 Telegram 中搜索您的备忘录 55 | - 📷 **媒体支持**: 支持图片、文件等媒体内容 56 | - 🔗 **无缝集成**: 与 Memos 实例完美集成 57 | - 👥 **多用户支持**: 支持多个用户通过各自的 Telegram 账户使用 58 | 59 | ## 配置选项 60 | 61 | ### 环境变量 62 | 63 | | 变量名 | 必需 | 默认值 | 描述 | 64 | |--------|------|--------|------| 65 | | `SERVER_ADDR` | 是 | - | 运行 Memos 的 gRPC 服务器地址 | 66 | | `BOT_TOKEN` | 是 | - | Telegram 机器人 Token | 67 | | `BOT_PROXY_ADDR` | 否 | - | Telegram API 的可选代理地址(如果不需要则留空) | 68 | | `ALLOWED_USERNAMES` | 否 | - | 可选的以逗号分隔的允许用户名列表(不带 @ 符号) | 69 | 70 | ### 获取 Telegram Bot Token 71 | 72 | 1. 在 Telegram 中找到 [@BotFather](https://t.me/BotFather) 73 | 2. 发送 `/newbot` 命令创建新机器人 74 | 3. 按照提示设置机器人名称和用户名 75 | 4. 获取 Bot Token 76 | 77 | ## 使用方法 78 | 79 | ### 基本命令 80 | 81 | - `/start ` - 使用您的 Memos 访问令牌启动机器人 82 | - `Send text messages` - 将消息保存为备忘录 83 | - `Send files (photos, documents)` - 将文件保存为备忘录 84 | - `/search [关键词]` - 搜索备忘录 85 | 86 | ## 开发 87 | 88 | ### 本地构建 89 | 90 | ```bash 91 | # 克隆仓库 92 | git clone https://github.com/aliuq/apps-image.git 93 | cd apps-image/apps/memogram 94 | 95 | # 构建镜像 96 | docker buildx build -f ./Dockerfile -t memogram:local --load . 97 | 98 | # 修改 docker-compose.yml 中的 image 为 memogram:local 99 | ``` 100 | 101 | ### 调试模式 102 | 103 | ```bash 104 | # 显示详细构建日志 105 | docker buildx build --progress=plain -f ./Dockerfile -t memogram:debug --no-cache --load . 106 | ``` 107 | 108 | ## 注意事项 109 | 110 | - 确保 Memos 实例正常运行且可访问 111 | - Telegram Bot Token 必须保密,不要泄露给他人 112 | - 建议在生产环境中使用 HTTPS 113 | - 定期备份 Memos 数据 114 | 115 | ## 相关链接 116 | 117 | - [Memos 项目](https://github.com/usememos/memos) 118 | - [Memos Self-Host](https://www.usememos.com/docs/install/self-hosting) 119 | 120 | --- 121 | 122 | > 📝 该文档由 AI 辅助生成并整理,如有问题请随时反馈。 123 | -------------------------------------------------------------------------------- /.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "prettier.enable": false, 3 | "editor.formatOnSave": false, 4 | "editor.codeActionsOnSave": { 5 | "source.fixAll.eslint": "explicit", 6 | "source.organizeImports": "never" 7 | }, 8 | // Silent the stylistic rules in you IDE, but still auto fix them 9 | "eslint.rules.customizations": [ 10 | { "rule": "style/*", "severity": "off", "fixable": true }, 11 | { "rule": "format/*", "severity": "off", "fixable": true }, 12 | { "rule": "*-indent", "severity": "off", "fixable": true }, 13 | { "rule": "*-spacing", "severity": "off", "fixable": true }, 14 | { "rule": "*-spaces", "severity": "off", "fixable": true }, 15 | { "rule": "*-order", "severity": "off", "fixable": true }, 16 | { "rule": "*-dangle", "severity": "off", "fixable": true }, 17 | { "rule": "*-newline", "severity": "off", "fixable": true }, 18 | { "rule": "*quotes", "severity": "off", "fixable": true }, 19 | { "rule": "*semi", "severity": "off", "fixable": true } 20 | ], 21 | // Enable eslint for all supported languages 22 | "eslint.validate": [ 23 | "javascript", 24 | "javascriptreact", 25 | "typescript", 26 | "typescriptreact", 27 | "vue", 28 | "html", 29 | "markdown", 30 | "json", 31 | "jsonc", 32 | "yaml", 33 | "toml", 34 | "xml", 35 | "gql", 36 | "graphql", 37 | "astro", 38 | "svelte", 39 | "css", 40 | "less", 41 | "scss", 42 | "pcss", 43 | "postcss" 44 | ], 45 | "cSpell.words": [ 46 | "aliyuncs", 47 | "astrojs", 48 | "buildx", 49 | "bunx", 50 | "Cascadia", 51 | "checkver", 52 | "Datas", 53 | "dbaeumer", 54 | "DEEPL", 55 | "defu", 56 | "dotenv", 57 | "dpkg", 58 | "envsubst", 59 | "esac", 60 | "Giscus", 61 | "globber", 62 | "haitang", 63 | "icones", 64 | "imputnet", 65 | "inpaint", 66 | "inpainting", 67 | "isready", 68 | "javayhu", 69 | "jsonhero", 70 | "khoben", 71 | "lsky", 72 | "Metas", 73 | "multx", 74 | "noclear", 75 | "NOPASSWD", 76 | "ohmyzsh", 77 | "oxlint", 78 | "oxlintignore", 79 | "oxlintrc", 80 | "pdfjs", 81 | "PGDATA", 82 | "PYTHONUNBUFFERED", 83 | "qrcode", 84 | "srcbook", 85 | "tamasfe", 86 | "tauri", 87 | "telemirror", 88 | "tesseract", 89 | "tgcf", 90 | "Umami", 91 | "unshallow", 92 | "VENV", 93 | "weektodo", 94 | "weserv", 95 | "yulegeyu" 96 | ], 97 | "json.schemas": [ 98 | { 99 | "fileMatch": ["**/*/meta.json"], 100 | "url": ".vscode/meta.schema.json" 101 | } 102 | ], 103 | "markdownlint.config": { 104 | "first-line-h1": false, 105 | "no-inline-html": false 106 | }, 107 | "docker.lsp.experimental.vulnerabilityScanning": false, 108 | "todo-tree.filtering.excludeGlobs": [ 109 | "**/node_modules/*/**", 110 | "**/dist/**" 111 | ], 112 | "todo-tree.regex.regex": "(//|#|)[\s\S]*()/ 83 | const updatedReadme = readme!.replace(reg, `$1\n${summary}\n$2`) 84 | await writeFile(path.join(cwd, 'README.md'), updatedReadme) 85 | } 86 | 87 | // 更新工作流中 context 选项 88 | async function updateCiContextOption(contextList: string[]) { 89 | const reg = /(# ContextStart)[\s\S]*(# ContextEnd)/ 90 | const space = ' ' 91 | const context = contextList.sort().map(c => `${space}- ${c}`).join('\n') 92 | 93 | const checkVersionFile = path.join(cwd, '.github/workflows/check-version.yaml') 94 | const checkContent = await readFile(checkVersionFile) 95 | const updatedCheckContent = checkContent!.replace(reg, `$1\n${context}\n${space}$2`) 96 | await writeFile(checkVersionFile, updatedCheckContent) 97 | 98 | const buildImageFile = path.join(cwd, '.github/workflows/build-image.yaml') 99 | const buildContent = await readFile(buildImageFile) 100 | const updatedBuildContent = buildContent!.replace(reg, `$1\n${context}\n${space}$2`) 101 | await writeFile(buildImageFile, updatedBuildContent) 102 | 103 | const buildTestFile = path.join(cwd, '.github/workflows/build-test.yaml') 104 | const buildTestContent = await readFile(buildTestFile) 105 | const updatedBuildTestContent = buildTestContent!.replace(reg, `$1\n${context}\n${space}$2`) 106 | await writeFile(buildTestFile, updatedBuildTestContent) 107 | } 108 | 109 | async function main() { 110 | const apps = await getFiles() 111 | const summary = await buildTable(apps) 112 | await updateReadmeAppList(summary) 113 | 114 | const contextList = await getContextList() 115 | await updateCiContextOption(contextList) 116 | } 117 | 118 | main() 119 | 120 | function toImg(url: string, href?: string) { 121 | if (!url.startsWith('http')) { 122 | url = `https://img.shields.io/${url}` 123 | } 124 | const img = `Static Badge` 125 | if (!href) 126 | return img 127 | 128 | return `${img}` 129 | } 130 | 131 | function splitTextByWidth(text: string, maxWidth: number): string { 132 | if (!text) 133 | return '' 134 | 135 | const lines: string[] = [] 136 | let currentLine = '' 137 | let currentWidth = 0 138 | 139 | for (const char of text) { 140 | // 中文字符宽度为2,英文字符宽度为1 141 | const charWidth = /[\u4E00-\u9FA5]/.test(char) ? 2 : 1 142 | 143 | // 如果添加当前字符会超过最大宽度,则开始新行 144 | if (currentWidth + charWidth > maxWidth && currentLine) { 145 | lines.push(currentLine) 146 | currentLine = char 147 | currentWidth = charWidth 148 | } 149 | else { 150 | currentLine += char 151 | currentWidth += charWidth 152 | } 153 | } 154 | 155 | // 添加最后一行 156 | if (currentLine) { 157 | lines.push(currentLine) 158 | } 159 | 160 | // 使用
连接多行,适合在表格中显示 161 | return lines.join('
') 162 | } 163 | -------------------------------------------------------------------------------- /scripts/new.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | # Check if directory parameter is provided 4 | if [ $# -eq 0 ]; then 5 | echo "Usage: $0 " 6 | echo "Examples:" 7 | echo " $0 myapp # Creates apps/myapp" 8 | echo " $0 test/myapp # Creates test/myapp" 9 | echo " $0 base/mybase # Creates base/mybase" 10 | echo " $0 sync/mysync # Creates sync/mysync" 11 | exit 1 12 | fi 13 | 14 | INPUT_PATH="$1" 15 | 16 | # Check if input contains a slash (indicates it's a path with prefix) 17 | case "$INPUT_PATH" in 18 | */*) 19 | # Input contains slash, use as-is 20 | DIR_PATH="$INPUT_PATH" 21 | DIR_NAME=$(basename "$INPUT_PATH") 22 | PREFIX=$(dirname "$INPUT_PATH") 23 | ;; 24 | *) 25 | # Input is just a name, default to apps/ prefix 26 | DIR_NAME="$INPUT_PATH" 27 | PREFIX="apps" 28 | DIR_PATH="apps/$DIR_NAME" 29 | ;; 30 | esac 31 | 32 | # Map PREFIX to TYPE based on directory structure 33 | case "$PREFIX" in 34 | apps) 35 | TYPE="app" 36 | ;; 37 | base) 38 | TYPE="base" 39 | ;; 40 | sync) 41 | TYPE="sync" 42 | ;; 43 | test) 44 | TYPE="app" # test directory maps to app type 45 | ;; 46 | *) 47 | TYPE="app" # default to app for any other prefix 48 | ;; 49 | esac 50 | 51 | # Validate directory name (only the basename) - using POSIX compliant regex 52 | if ! echo "$DIR_NAME" | grep -q '^[a-zA-Z0-9_-]\+$'; then 53 | echo "Error: Directory name can only contain letters, numbers, underscores, and hyphens" 54 | echo "Invalid name: '$DIR_NAME'" 55 | exit 1 56 | fi 57 | 58 | # Validate prefix (should be one of the known types) 59 | case "$PREFIX" in 60 | apps|base|sync|test) 61 | # Valid prefixes 62 | ;; 63 | *) 64 | echo "Warning: Using non-standard prefix '$PREFIX'" 65 | echo "Standard prefixes are: apps, base, sync, test" 66 | echo "Type will be set to 'app' by default" 67 | printf "Continue anyway? (y/N): " 68 | read REPLY 69 | case "$REPLY" in 70 | [Yy]|[Yy][Ee][Ss]) 71 | # Continue 72 | ;; 73 | *) 74 | echo "Cancelled." 75 | exit 1 76 | ;; 77 | esac 78 | ;; 79 | esac 80 | 81 | # Get the compose directory path (assuming script is in scripts directory) 82 | SCRIPT_DIR="$(dirname "$0")" 83 | COMPOSE_PATH="$(dirname "$SCRIPT_DIR")" 84 | TARGET_PATH="$COMPOSE_PATH/$DIR_PATH" 85 | 86 | # Check if directory already exists 87 | if [ -d "$TARGET_PATH" ]; then 88 | echo "Error: Directory '$DIR_PATH' already exists in $COMPOSE_PATH" 89 | exit 1 90 | fi 91 | 92 | # Create the directory structure 93 | mkdir -p "$TARGET_PATH" 94 | if [ $? -ne 0 ]; then 95 | echo "Error: Failed to create directory '$TARGET_PATH'" 96 | exit 1 97 | fi 98 | 99 | # Create basic files 100 | touch "$TARGET_PATH/Dockerfile" 101 | touch "$TARGET_PATH/meta.json" 102 | touch "$TARGET_PATH/README.md" 103 | 104 | # Create a basic meta.json template based on type mapping 105 | cat > "$TARGET_PATH/meta.json" << EOF 106 | { 107 | "name": "$DIR_NAME", 108 | "type": "$TYPE", 109 | "version": "\$version\$", 110 | "sha": "\$fullSha\$", 111 | "repo": "", 112 | "description": "", 113 | "dockerMeta": { 114 | "context": "$DIR_PATH", 115 | "dockerfile": "Dockerfile", 116 | "push": true, 117 | "tags": [ 118 | "type=raw,value=latest", 119 | "type=raw,value=\$version\$", 120 | "type=raw,value=\$sha\$" 121 | ] 122 | }, 123 | "checkVer": { 124 | "type": "version", 125 | "file": "package.json" 126 | } 127 | } 128 | EOF 129 | 130 | # Create a basic Dockerfile template 131 | cat > "$TARGET_PATH/Dockerfile" << EOF 132 | # Basic Dockerfile template for $DIR_NAME 133 | FROM alpine/git AS base 134 | WORKDIR /app 135 | RUN git clone YOUR_REPO_URL . && git checkout \$sha\$ 136 | 137 | FROM node:18-alpine AS build 138 | WORKDIR /app 139 | COPY --from=base /app . 140 | # RUN npm install && npm run build 141 | 142 | FROM nginx:alpine 143 | WORKDIR /app 144 | # COPY --from=build /app/dist /usr/share/nginx/html 145 | 146 | # Version: \$version\$ 147 | # SHA: \$fullSha\$ 148 | 149 | EXPOSE 80 150 | CMD ["nginx", "-g", "daemon off;"] 151 | EOF 152 | 153 | # Create a basic README template 154 | cat > "$TARGET_PATH/README.md" << 'EOF' 155 | # $DIR_NAME 156 | 157 | ## Description 158 | 159 | Brief description of $DIR_NAME. 160 | 161 | ## Usage 162 | 163 | Instructions for using this application. 164 | 165 | ## Configuration 166 | 167 | Configuration details and environment variables. 168 | 169 | ## Build 170 | 171 | ```bash 172 | docker build -t $DIR_NAME . 173 | ``` 174 | 175 | ## Run 176 | 177 | ```bash 178 | docker run -d --name $DIR_NAME $DIR_NAME 179 | ``` 180 | EOF 181 | 182 | # Replace variables in README.md 183 | sed -i.bak "s/\$DIR_NAME/$DIR_NAME/g" "$TARGET_PATH/README.md" && rm "$TARGET_PATH/README.md.bak" 184 | 185 | echo "✅ Successfully created $PREFIX application structure:" 186 | echo "📁 $TARGET_PATH/" 187 | echo " ├── Dockerfile (with basic template and placeholders)" 188 | echo " ├── meta.json (with type: '$TYPE' and placeholders)" 189 | echo " └── README.md (with basic template)" 190 | echo "" 191 | echo "💡 Placeholder Usage:" 192 | echo " \$version\$ - Will be replaced with actual version" 193 | echo " \$sha\$ - Will be replaced with 7-char commit SHA" 194 | echo " \$fullSha\$ - Will be replaced with full commit SHA" 195 | echo "" 196 | echo "🔧 Alternative Placeholders (also supported):" 197 | echo " {{version}}, {version}" 198 | echo " {{sha}}, {sha}" 199 | echo " {{fullSha}}, {fullSha}" 200 | echo "" 201 | echo "📝 Next steps:" 202 | echo " 1. Edit meta.json with your application details" 203 | echo " 2. Update Dockerfile with your build steps" 204 | echo " 3. Add your application code" 205 | echo " 4. Update README.md with specific documentation" 206 | echo " 5. The placeholders will be automatically replaced during CI/CD" 207 | 208 | # # 创建 apps/myapp 209 | # ./scripts/new.sh myapp 210 | 211 | # # 创建 test/mytest 212 | # ./scripts/new.sh test/mytest 213 | 214 | # # 创建 base/mybase 215 | # ./scripts/new.sh base/mybase 216 | 217 | # # 创建 sync/mysync 218 | # ./scripts/new.sh sync/mysync 219 | 220 | # # 创建自定义前缀(会有警告) 221 | # ./scripts/new.sh custom/myapp 222 | -------------------------------------------------------------------------------- /base/tg-session/main.py: -------------------------------------------------------------------------------- 1 | from telethon.sync import TelegramClient 2 | from telethon.sessions import StringSession 3 | import asyncio 4 | import os 5 | from dotenv import load_dotenv 6 | import qrcode 7 | from typing import Tuple 8 | import sys 9 | import time 10 | from getpass import getpass 11 | 12 | load_dotenv() 13 | 14 | is_debug = os.getenv('DEBUG', 'false').lower() == 'true' 15 | 16 | # Define color codes 17 | class Colors: 18 | HEADER = '\033[95m' 19 | BLUE = '\033[94m' 20 | GREEN = '\033[92m' 21 | WARNING = '\033[93m' 22 | FAIL = '\033[91m' 23 | ENDC = '\033[0m' 24 | BOLD = '\033[1m' 25 | DEFAULT = '\033[99m' 26 | 27 | def print_color(text: str, color: str, bold: bool = False) -> None: 28 | """Print colored text in terminal""" 29 | if bold: 30 | print(f"{Colors.BOLD}{color}{text}{Colors.ENDC}") 31 | else: 32 | print(f"{color}{text}{Colors.ENDC}") 33 | 34 | def get_credentials() -> Tuple[str, str]: 35 | """Get API credentials""" 36 | api_id = os.getenv('API_ID') 37 | api_hash = os.getenv('API_HASH') 38 | 39 | if not api_id and not api_hash: 40 | print_color("\nTo obtain API credentials:\n", Colors.WARNING) 41 | print_color(" 1. Visit https://my.telegram.org/", Colors.DEFAULT) 42 | print_color(" 2. Login with your Telegram account", Colors.DEFAULT) 43 | print_color(" 3. Click on 'API Development tools'", Colors.DEFAULT) 44 | print_color(" 4. Create a new application\n", Colors.DEFAULT) 45 | 46 | if api_id: 47 | print_color("Got API ID from environment variables", Colors.GREEN) 48 | else: 49 | if is_debug: 50 | api_id = input(f"{Colors.BLUE}Please enter your API ID: {Colors.ENDC}").strip() 51 | else: 52 | api_id = getpass(f"{Colors.BLUE}Please enter your API ID: {Colors.ENDC}").strip() 53 | 54 | if api_hash: 55 | print_color("Got API Hash from environment variables", Colors.GREEN) 56 | else: 57 | if is_debug: 58 | api_hash = input(f"{Colors.BLUE}Please enter your API Hash: {Colors.ENDC}").strip() 59 | else: 60 | api_hash = getpass(f"{Colors.BLUE}Please enter your API Hash: {Colors.ENDC}").strip() 61 | 62 | return api_id, api_hash 63 | 64 | async def test_session_string(session_string: str, api_id: str, api_hash: str) -> bool: 65 | """Test if the session string is valid""" 66 | try: 67 | print_color("\nTesting session string...\n", Colors.BLUE) 68 | client = TelegramClient(StringSession(session_string), api_id, api_hash) 69 | await client.connect() 70 | 71 | if not await client.is_user_authorized(): 72 | await client.disconnect() 73 | print_color("Test failed: Invalid session string", Colors.FAIL) 74 | return False 75 | 76 | me = await client.get_me() 77 | await client.disconnect() 78 | print_color(f"Test successful! Account info: {me.first_name} {me.last_name} (@{me.username})", Colors.GREEN) 79 | return True 80 | except Exception as e: 81 | print_color(f"Test failed: {str(e)}", Colors.FAIL) 82 | return False 83 | 84 | async def stringGenerate(): 85 | client = None 86 | try: 87 | print_color("====== Telegram Session String Generator ======\n", Colors.HEADER, True) 88 | 89 | api_id, api_hash = get_credentials() 90 | if not api_id or not api_hash: 91 | print_color("Error: API credentials cannot be empty", Colors.FAIL) 92 | return 93 | 94 | client = TelegramClient(StringSession(), api_id, api_hash) 95 | await client.connect() 96 | 97 | print_color("\nPlease scan the QR code with Telegram app:\n", Colors.BLUE) 98 | 99 | try: 100 | # Get QR login info 101 | qr_login = await client.qr_login() 102 | 103 | # Display QR code in console 104 | qr = qrcode.QRCode(border=1) 105 | qr.add_data(qr_login.url) 106 | qr.make(fit=True) 107 | qr.print_ascii(invert=True) 108 | 109 | print_color("\nWaiting for scan...", Colors.BLUE) 110 | 111 | # Login timeout handling 112 | timeout = 60 # 60 seconds timeout 113 | start_time = time.time() 114 | 115 | while True: 116 | try: 117 | if await qr_login.wait(timeout=1): 118 | break 119 | 120 | if time.time() - start_time > timeout: 121 | print_color("\nLogin timeout! Please run the program again.", Colors.FAIL) 122 | return 123 | 124 | sys.stdout.write(".") 125 | sys.stdout.flush() 126 | except asyncio.TimeoutError: 127 | continue 128 | except Exception as e: 129 | print_color(f"\nError during QR scan: {str(e)}", Colors.FAIL) 130 | return 131 | 132 | print_color("\nQR code scanned! Getting session info...", Colors.GREEN) 133 | 134 | # Ensure login success 135 | if not await client.is_user_authorized(): 136 | print_color("\nLogin failed: Authorization unsuccessful", Colors.FAIL) 137 | return 138 | 139 | session_string = client.session.save() 140 | print_color("\n=== Session String Generated Successfully ===", Colors.GREEN, True) 141 | print_color("Please save your session string securely:", Colors.WARNING) 142 | 143 | with open("session/.session", "w") as f: 144 | f.write(session_string) 145 | 146 | if is_debug: 147 | print(f"\n{session_string}\n") 148 | else: 149 | print_color("\nSession string has been saved to '/app/session/.session'", Colors.DEFAULT) 150 | 151 | # Test the generated session string 152 | is_valid = await test_session_string(session_string, api_id, api_hash) 153 | if not is_valid: 154 | print_color("\nWarning: The generated session string might not work properly!", Colors.WARNING) 155 | 156 | except Exception as e: 157 | print_color(f"\nError during QR login process: {str(e)}", Colors.FAIL) 158 | return 159 | 160 | except KeyboardInterrupt: 161 | print_color("\n\nOperation cancelled", Colors.WARNING) 162 | except Exception as e: 163 | print_color(f"\nError occurred: {str(e)}", Colors.FAIL) 164 | finally: 165 | if client: 166 | try: 167 | await client.disconnect() 168 | except: 169 | pass 170 | 171 | if __name__ == "__main__": 172 | asyncio.run(stringGenerate()) 173 | -------------------------------------------------------------------------------- /base/vscode/README.md: -------------------------------------------------------------------------------- 1 | # VSCode 2 | 3 | > 基于 VS Code CLI 的容器化开发环境,预装了现代化开发工具和终端体验 4 | 5 | [![Docker Pulls](https://img.shields.io/docker/pulls/aliuq/vscode)](https://hub.docker.com/r/aliuq/vscode) 6 | [![Docker Image Size](https://img.shields.io/docker/image-size/aliuq/vscode)](https://hub.docker.com/r/aliuq/vscode) 7 | 8 | ## 镜像变体 9 | 10 | 本项目提供两个镜像变体以满足不同的使用需求: 11 | 12 | ### 标准版(`latest`)- 推荐 13 | 14 | - 基于非特权用户 `coder` (UID 1000) 15 | - 遵循 Docker 安全最佳实践 16 | - 适合生产环境和安全敏感场景 17 | - SSH 禁用 root 登录,仅允许指定用户访问 18 | 19 | ### 稳定版(`stable`) 20 | 21 | - 基于 `root` 用户运行 22 | - 简化权限管理,便于快速部署 23 | - 适合开发和测试环境 24 | - 减少权限相关的配置复杂性 25 | 26 | ```bash 27 | # 使用标准版(推荐) 28 | docker run -d --name vscode -p 8000:8000 aliuq/vscode:latest 29 | 30 | # 使用稳定版 31 | docker run -d --name vscode-stable -p 8000:8000 aliuq/vscode:stable 32 | ``` 33 | 34 | ## 项目信息 35 | 36 | - **官方仓库**: [microsoft/vscode](https://github.com/microsoft/vscode) 37 | - **Docker 镜像**: [`aliuq/vscode`](https://hub.docker.com/r/aliuq/vscode) 38 | - **Dockerfile**: [查看构建文件](https://github.com/aliuq/apps-image/blob/master/base/vscode/Dockerfile) 39 | 40 | ## 快速开始 41 | 42 | ### Web IDE 模式(默认) 43 | 44 | ```bash 45 | # 基础使用 46 | docker run -d --name vscode -p 8000:8000 aliuq/vscode:latest 47 | 48 | # 带访问令牌 49 | docker run -d --name vscode -p 8000:8000 -e TOKEN=your-secret-token aliuq/vscode:latest 50 | 51 | # 映射工作目录 52 | docker run -d --name vscode -p 8000:8000 -v $(pwd):/home/workspace aliuq/vscode:latest 53 | ``` 54 | 55 | 访问 `http://localhost:8000` 即可使用 Web IDE 56 | 57 | ### 隧道模式 58 | 59 | > 暂时无法直连,只能通过官方的中继服务器进行通信 60 | 61 | ```bash 62 | docker run -it --rm -e RUN_MODE=tunnel aliuq/vscode:latest 63 | ``` 64 | 65 | ### SSH 模式 66 | 67 | ```bash 68 | # 使用公钥认证 69 | docker run -d --name vscode-ssh -p 2222:22 \ 70 | -e RUN_MODE=ssh \ 71 | -e PUBLIC_KEY="$(cat ~/.ssh/id_rsa.pub)" \ 72 | -v $(pwd):/home/workspace \ 73 | aliuq/vscode:latest 74 | 75 | # 使用公钥文件 76 | docker run -d --name vscode-ssh -p 2222:22 \ 77 | -e RUN_MODE=ssh \ 78 | -e PUBLIC_KEY_FILE=/tmp/id_rsa.pub \ 79 | -v ~/.ssh/id_rsa.pub:/tmp/id_rsa.pub \ 80 | -v $(pwd):/home/workspace \ 81 | aliuq/vscode:latest 82 | 83 | # SSH 连接 84 | ssh -i /tmp/id_rsa -p 2222 coder@localhost 85 | ``` 86 | 87 | ### 使用 Docker Compose 88 | 89 | 创建 `docker-compose.yml` 文件: 90 | 91 | ```yaml 92 | name: vscode 93 | services: 94 | vscode: 95 | image: aliuq/vscode:latest 96 | container_name: vscode 97 | hostname: aliuq-vscode # 可选,设置容器主机名,更清晰 98 | restart: unless-stopped 99 | ports: 100 | - '8000:8000' 101 | volumes: 102 | - ./workspace:/home/workspace 103 | environment: 104 | - TOKEN=your-secret-token # 可选,设置访问令牌 105 | ``` 106 | 107 | 运行服务: 108 | 109 | ```bash 110 | docker-compose up -d 111 | ``` 112 | 113 | ## 功能特性 114 | 115 | ### 🛠️ 预装开发工具 116 | 117 | - **VS Code CLI** - 最新版本的 Visual Studio Code 命令行界面 118 | - **eza** - 现代化的 ls 替代品,提供彩色文件列表 119 | - **fzf** - 强大的模糊搜索工具 120 | - **zoxide** - 智能的 cd 命令替代品 121 | - **mise** - 现代化的运行时管理器 122 | 123 | ### 🎨 终端体验 124 | 125 | - **Zsh** 作为默认 Shell 126 | - **Oh My Zsh** 配置框架 127 | - **Starship** 跨 Shell 的提示符 128 | - **CascadiaCode Nerd Font** 编程字体 129 | - 预配置的插件: 130 | - `zsh-autosuggestions` - 命令自动建议 131 | - `zsh-syntax-highlighting` - 语法高亮 132 | - `extract` - 智能解压缩 133 | - `fzf`, `eza`, `zoxide`, `mise` 集成 134 | 135 | ### 🔒 安全特性 136 | 137 | - 非 root 用户运行(`coder` 用户) 138 | - 支持 sudo 权限 139 | - 可选的访问令牌保护 140 | - SSH 密钥认证(SSH 模式) 141 | - 禁用密码认证和 root 登录 142 | 143 | ## 环境变量 144 | 145 | | 变量名 | 默认值 | 描述 | 146 | |--------|--------|------| 147 | | `RUN_MODE` | `serve-web` | 运行模式:`serve-web`, `tunnel`, `custom`, `empty`, `ssh` | 148 | | `HOST` | `0.0.0.0` | 绑定的主机地址 | 149 | | `PORT` | `8000` | 监听端口 | 150 | | `TOKEN` | - | 访问令牌(可选) | 151 | | `STARSHIP_CONFIG` | - | Starship 配置文件路径或 URL | 152 | | `PUBLIC_KEY` | - | SSH 公钥内容(SSH 模式) | 153 | | `PUBLIC_KEY_FILE` | - | SSH 公钥文件路径(SSH 模式) | 154 | 155 | ## 运行模式 156 | 157 | ### serve-web(默认) 158 | 159 | 启动 VS Code Web 服务器,可通过浏览器访问 160 | 161 | ```bash 162 | docker run -p 8000:8000 aliuq/vscode:latest 163 | ``` 164 | 165 | ### tunnel 166 | 167 | 启动 VS Code 隧道模式,可通过 vscode.dev 远程访问 168 | 169 | ```bash 170 | docker run -it -e RUN_MODE=tunnel aliuq/vscode:latest 171 | ``` 172 | 173 | ### custom 174 | 175 | 自定义 VS Code 命令 176 | 177 | ```bash 178 | # code --version 179 | docker run -e RUN_MODE=custom aliuq/vscode:latest --version 180 | ``` 181 | 182 | ### empty 183 | 184 | 不启动 VS Code,直接进入容器 185 | 186 | ```bash 187 | docker run -it -e RUN_MODE=empty aliuq/vscode:latest /bin/zsh 188 | ``` 189 | 190 | ### ssh 191 | 192 | 启动 SSH 服务器,可通过 SSH 远程连接 193 | 194 | ```bash 195 | # 使用公钥认证 196 | docker run -d -p 2222:22 -e RUN_MODE=ssh -e PUBLIC_KEY="$(cat ~/.ssh/id_rsa.pub)" aliuq/vscode:latest 197 | 198 | # 连接到容器 199 | ssh -p 2222 coder@localhost 200 | ``` 201 | 202 | ## 自定义配置 203 | 204 | ### Starship 提示符配置 205 | 206 | 可以通过以下方式自定义 Starship 配置: 207 | 208 | 1. **本地文件**: 209 | 210 | ```bash 211 | docker run -v /path/to/starship.toml:/tmp/starship.toml aliuq/vscode:latest 212 | ``` 213 | 214 | 1. **环境变量指定路径**: 215 | 216 | ```bash 217 | docker run -e STARSHIP_CONFIG=/path/to/custom.toml -v /path/to/custom.toml:/path/to/custom.toml aliuq/vscode:latest 218 | ``` 219 | 220 | 1. **远程 URL**: 221 | 222 | ```bash 223 | docker run -e STARSHIP_CONFIG=https://example.com/starship.toml aliuq/vscode:latest 224 | ``` 225 | 226 | ### 工作目录持久化 227 | 228 | ```bash 229 | # 映射当前目录作为工作空间 230 | docker run -v $(pwd):/home/workspace aliuq/vscode:latest 231 | 232 | # 映射特定目录 233 | docker run -v /path/to/your/project:/home/workspace aliuq/vscode:latest 234 | ``` 235 | 236 | ## 使用示例 237 | 238 | ### 开发 Node.js 项目 239 | 240 | ```bash 241 | docker run -d \ 242 | --name vscode-nodejs \ 243 | -p 8000:8000 \ 244 | -v $(pwd):/home/workspace \ 245 | -e TOKEN=my-secret-token \ 246 | aliuq/vscode:latest 247 | ``` 248 | 249 | ### 临时开发环境 250 | 251 | ```bash 252 | docker run -it --rm \ 253 | -p 8000:8000 \ 254 | -v $(pwd):/home/workspace \ 255 | aliuq/vscode:latest 256 | ``` 257 | 258 | ### 远程开发(隧道模式) 259 | 260 | ```bash 261 | docker run -it --rm \ 262 | -e RUN_MODE=tunnel \ 263 | -v $(pwd):/home/workspace \ 264 | aliuq/vscode:latest 265 | ``` 266 | 267 | ### SSH 远程开发 268 | 269 | ```bash 270 | # 启动 SSH 服务 271 | docker run -d \ 272 | --name vscode-ssh \ 273 | -p 2222:22 \ 274 | -e RUN_MODE=ssh \ 275 | -e PUBLIC_KEY="$(cat ~/.ssh/id_rsa.pub)" \ 276 | -v $(pwd):/home/workspace \ 277 | aliuq/vscode:latest 278 | 279 | # 通过 SSH 连接 280 | ssh -p 2222 coder@localhost 281 | ``` 282 | 283 | ## 网络访问 284 | 285 | - **Web IDE**: `http://localhost:8000` 286 | - **带令牌**: `http://localhost:8000/?tkn=your-token` 287 | - **SSH 连接**: `ssh -p 2222 coder@localhost` 288 | 289 | ## 注意事项 290 | 291 | 1. 首次启动可能需要一些时间来初始化 VS Code 服务 292 | 2. 建议设置访问令牌以提高安全性 293 | 3. 工作目录默认为 `/home/workspace` 294 | 4. **latest**以非特权用户 `coder` 运行,**stable**以 `root` 运行 295 | 5. 隧道模式需要登录 GitHub/Microsoft 账户 296 | 6. SSH 模式仅支持公钥认证,已禁用密码认证 297 | 7. SSH 服务监听 22 端口,Web IDE 监听 8000 端口 298 | 8. **推荐使用latest**以获得更好的安全性 299 | 300 | ## 参考引用 301 | 302 | 1. 303 | 2. 304 | 3. 305 | -------------------------------------------------------------------------------- /.github/workflows/build-test.yaml: -------------------------------------------------------------------------------- 1 | name: Build Docker Image For ACT 2 | 3 | on: 4 | workflow_dispatch: 5 | inputs: 6 | context: 7 | description: App Context,e.g. apps/icones 8 | type: choice 9 | required: true 10 | options: 11 | # ContextStart 12 | - apps/cobalt 13 | - apps/haitang 14 | - apps/icones 15 | - apps/inpaint-web 16 | - apps/jsonhero-web 17 | - apps/lsky 18 | - apps/memogram 19 | - apps/n8n-workflows 20 | - apps/readest 21 | - apps/srcbook 22 | - apps/telegram-upload 23 | - apps/telemirror 24 | - apps/weektodo 25 | - apps/weserv 26 | - apps/yulegeyu 27 | - base/alpine 28 | - base/nginx 29 | - base/self 30 | - base/tg-session 31 | - base/vscode 32 | - test/icones 33 | - test/self 34 | - test/weektodo 35 | - test/weektodo-mul 36 | # ContextEnd 37 | variants: 38 | description: Build variants, e.g. latest,stable 39 | default: latest 40 | type: string 41 | debug: 42 | description: Debug mode 43 | default: false 44 | type: boolean 45 | build: 46 | description: Enable build image 47 | default: true 48 | type: boolean 49 | notify: 50 | description: Enable notification 51 | default: true 52 | type: boolean 53 | 54 | jobs: 55 | metadata: 56 | name: Resolve Docker Metadata 57 | runs-on: ubuntu-latest 58 | permissions: 59 | pull-requests: read 60 | outputs: 61 | matrix: ${{ steps.metadata.outputs.matrix }} 62 | steps: 63 | - uses: actions/checkout@v4 64 | - name: Resolve metadata 65 | id: metadata 66 | uses: ./action/resolve-meta 67 | env: 68 | TZ: Asia/Shanghai 69 | DOCKERHUB_USERNAME: aliuq 70 | GHCR_USERNAME: aliuq 71 | ALI_ACR_REGISTRY: registry.cn-hangzhou.aliyuncs.com 72 | ALI_ACR_USERNAME: aliuq 73 | with: 74 | context: ${{ inputs.context }} 75 | variants: ${{ inputs.variants }} 76 | debug: ${{ inputs.debug }} 77 | 78 | docker-build: 79 | needs: metadata 80 | name: Build ${{ matrix.variant }} 81 | runs-on: ubuntu-latest 82 | if: needs.metadata.outputs.matrix 83 | permissions: 84 | contents: read 85 | packages: write 86 | strategy: 87 | matrix: ${{ needs.metadata.outputs.matrix && fromJson(needs.metadata.outputs.matrix) }} 88 | steps: 89 | - uses: actions/checkout@v4 90 | - name: Docker meta 91 | id: meta 92 | uses: docker/metadata-action@v5 93 | with: 94 | images: ${{ matrix.metadata.imageLines }} 95 | tags: ${{ matrix.metadata.tagLines }} 96 | labels: ${{ matrix.metadata.labelLines }} 97 | annotations: ${{ matrix.metadata.labelLines }} 98 | 99 | - name: Set up QEMU 100 | if: inputs.build 101 | uses: docker/setup-qemu-action@v3 102 | 103 | - name: Set up Docker Buildx 104 | if: inputs.build 105 | uses: docker/setup-buildx-action@v3 106 | 107 | - name: Cache Docker layers 108 | if: inputs.build 109 | uses: actions/cache@v4 110 | with: 111 | path: ${{ runner.temp }}/.buildx-cache 112 | key: ${{ runner.os }}-buildx-${{ github.sha }} 113 | restore-keys: | 114 | ${{ runner.os }}-buildx- 115 | 116 | - name: Build & Push 117 | if: inputs.build 118 | uses: docker/build-push-action@v6 119 | with: 120 | context: ${{ matrix.build.context }} 121 | file: ${{ matrix.build.file }} 122 | platforms: ${{ matrix.build.platformLines }} 123 | push: ${{ matrix.build.push }} 124 | tags: ${{ steps.meta.outputs.tags }} 125 | labels: ${{ steps.meta.outputs.labels }} 126 | cache-from: type=local,src=${{ runner.temp }}/.buildx-cache 127 | cache-to: type=local,dest=${{ runner.temp }}/.buildx-cache-new,mode=max 128 | 129 | - name: Move cache 130 | if: inputs.build 131 | run: | 132 | rm -rf ${{ runner.temp }}/.buildx-cache 133 | mv ${{ runner.temp }}/.buildx-cache-new ${{ runner.temp }}/.buildx-cache 134 | 135 | - name: Push README 136 | if: ${{ matrix.readme.push }} 137 | uses: peter-evans/dockerhub-description@v4 138 | with: 139 | username: ${{ secrets.DOCKERHUB_USERNAME }} 140 | password: ${{ secrets.DOCKERHUB_TOKEN }} 141 | repository: ${{ matrix.readme.repo }} 142 | readme-filepath: ${{ matrix.readme.path }} 143 | 144 | - name: Pre Notification 145 | id: pre-notify 146 | uses: actions/github-script@v7 147 | if: inputs.notify 148 | env: 149 | DOCKERHUB_USERNAME: ${{ secrets.DOCKERHUB_USERNAME }} 150 | with: 151 | script: | 152 | const meta = ${{ toJson(fromJson(steps.meta.outputs.json)) }} 153 | const matrix = ${{ toJson(matrix) }} 154 | 155 | const data = { 156 | name: `**${matrix.name}**`, 157 | tags: meta.tags.map(t => `\`${t}\``).join('\n'), 158 | url: meta.labels['org.opencontainers.image.url'], 159 | flag: matrix.name.replace(/-/g, '_') 160 | } 161 | if (data.url) { 162 | data.name = `[**${matrix.name}**](${data.url})` 163 | } 164 | 165 | const buttons = [] 166 | const infoButtons = [{ "text": "工作流", "url": "https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }}" }] 167 | data.url && infoButtons.push({ "text": "仓库地址", "url": data.url }) 168 | infoButtons.push({ "text": "项目地址", "url": "https://github.com/${{ github.repository }}" }) 169 | buttons.push(infoButtons) 170 | 171 | const registrys = [] 172 | if (matrix.pushDocker) { 173 | const image = matrix.metadata.images.find(i => i.startsWith(process.env.DOCKERHUB_USERNAME)) 174 | registrys.push({ text: "Docker", url: `https://hub.docker.com/r/${image}` }) 175 | } 176 | if (matrix.pushGhcr) { 177 | const image = matrix.metadata.images.find(i => i.startsWith('ghcr.io/')).split('/').pop() 178 | registrys.push({ text: "GHCR", url: `https://github.com/users/aliuq/packages/container/package/${image}` }) 179 | } 180 | registrys.length && buttons.push(registrys) 181 | 182 | core.setOutput("tags", data.tags) 183 | core.setOutput("name", data.name) 184 | core.setOutput("flag", data.flag) 185 | core.setOutput("buttons", buttons) 186 | 187 | - name: Notification 188 | uses: aliuq/telegram-action@v1 189 | if: inputs.notify 190 | with: 191 | bot_token: ${{ secrets.BOT_TOKEN }} 192 | chat_id: ${{ secrets.CHAT_ID }} 193 | reply_to_message_id: ${{ secrets.REPLY_TO_MESSAGE_ID }} 194 | message: | 195 | 🎉 ${{ steps.pre-notify.outputs.name }} has new image builds 196 | 197 | ${{ steps.pre-notify.outputs.tags }} 198 | 199 | #build_image #app_${{ steps.pre-notify.outputs.flag }} 200 | 201 | buttons: ${{ steps.pre-notify.outputs.buttons }} 202 | --------------------------------------------------------------------------------