mirror of
https://github.com/bbernhard/signal-cli-rest-api.git
synced 2026-05-18 13:24:15 +00:00
Compare commits
38 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
5c0bd056a7 | ||
|
|
ad5d3b76db | ||
|
|
0aaab36e5f | ||
|
|
44ac16d49c | ||
|
|
e8c8b54d52 | ||
|
|
91bdd60c7a | ||
|
|
a7c91737b8 | ||
|
|
af48a4304b | ||
|
|
9155e505af | ||
|
|
d0ec5b1b28 | ||
|
|
fa0f67fa69 | ||
|
|
7aa70683aa | ||
|
|
82f7151212 | ||
|
|
e68cabf88f | ||
|
|
4bbadbf29e | ||
|
|
b37aac4d5f | ||
|
|
db63fd15e0 | ||
|
|
650367e88a | ||
|
|
69457e8f81 | ||
|
|
2e8171d84c | ||
|
|
419b18331d | ||
|
|
16c3214862 | ||
|
|
a168cf5547 | ||
|
|
1f222d7261 | ||
|
|
6ac432b509 | ||
|
|
948a522ad8 | ||
|
|
6fa06f9611 | ||
|
|
eda99213a7 | ||
|
|
2ac55eec07 | ||
|
|
cb5e64a6d5 | ||
|
|
0a7c53a10a | ||
|
|
09252b4b87 | ||
|
|
881e9203c1 | ||
|
|
e2523b102c | ||
|
|
0f2c12f28e | ||
|
|
e712494d7f | ||
|
|
e0af0091c9 | ||
|
|
252389efbe |
28
.github/workflows/check-docs.yml
vendored
Normal file
28
.github/workflows/check-docs.yml
vendored
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
name: Check Generated Docs
|
||||||
|
|
||||||
|
on:
|
||||||
|
workflow_call:
|
||||||
|
|
||||||
|
permissions:
|
||||||
|
contents: read
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
check-docs:
|
||||||
|
runs-on: ubuntu-24.04
|
||||||
|
steps:
|
||||||
|
- name: Checkout
|
||||||
|
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
||||||
|
|
||||||
|
- name: Set up Go
|
||||||
|
uses: actions/setup-go@4a3601121dd01d1626a1e23e37211e3254c1c06c # v6.0.0
|
||||||
|
with:
|
||||||
|
go-version-file: src/go.mod
|
||||||
|
cache-dependency-path: src/go.sum
|
||||||
|
|
||||||
|
- name: Regenerate docs
|
||||||
|
working-directory: src
|
||||||
|
run: go run github.com/swaggo/swag/cmd/swag@v1.16.6 init --requiredByDefault
|
||||||
|
|
||||||
|
- name: Fail if docs are out of date
|
||||||
|
run: |
|
||||||
|
git diff --exit-code -- src/docs/docs.go src/docs/swagger.json src/docs/swagger.yaml
|
||||||
10
.github/workflows/ci.yml
vendored
10
.github/workflows/ci.yml
vendored
@ -8,14 +8,16 @@ on:
|
|||||||
branches:
|
branches:
|
||||||
- '**' #every branch
|
- '**' #every branch
|
||||||
|
|
||||||
|
permissions: {}
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
setup:
|
setup:
|
||||||
runs-on: ubuntu-24.04
|
runs-on: ubuntu-24.04
|
||||||
steps:
|
steps:
|
||||||
- name: Set up QEMU
|
- name: Set up QEMU
|
||||||
uses: docker/setup-qemu-action@v3
|
uses: docker/setup-qemu-action@ce360397dd3f832beb865e1373c09c0e9f86d70a # v4.0.0
|
||||||
- name: Set up Docker Buildx
|
- name: Set up Docker Buildx
|
||||||
uses: docker/setup-buildx-action@v3
|
uses: docker/setup-buildx-action@4d04d5d9486b7bd6fa91e7baf45bbb4f8b9deedd # v4.0.0
|
||||||
- name: Available platforms
|
- name: Available platforms
|
||||||
run: echo ${{ steps.buildx.outputs.platforms }}
|
run: echo ${{ steps.buildx.outputs.platforms }}
|
||||||
- name: Install Podman
|
- name: Install Podman
|
||||||
@ -25,11 +27,11 @@ jobs:
|
|||||||
runs-on: ubuntu-24.04
|
runs-on: ubuntu-24.04
|
||||||
needs: setup
|
needs: setup
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@master
|
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
||||||
with:
|
with:
|
||||||
ref: ${{ github.ref }}
|
ref: ${{ github.ref }}
|
||||||
- name: Login to Docker Hub
|
- name: Login to Docker Hub
|
||||||
uses: docker/login-action@v1
|
uses: docker/login-action@4907a6ddec9925e35a0a9e82d7399ccc52663121 # v4.1.0
|
||||||
with:
|
with:
|
||||||
username: ${{ secrets.DOCKERHUB_USERNAME }}
|
username: ${{ secrets.DOCKERHUB_USERNAME }}
|
||||||
password: ${{ secrets.DOCKERHUB_TOKEN }}
|
password: ${{ secrets.DOCKERHUB_TOKEN }}
|
||||||
|
|||||||
14
.github/workflows/release-dev-version.yml
vendored
14
.github/workflows/release-dev-version.yml
vendored
@ -7,15 +7,21 @@ on:
|
|||||||
description: 'Version'
|
description: 'Version'
|
||||||
required: true
|
required: true
|
||||||
|
|
||||||
|
permissions:
|
||||||
|
contents: read
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
|
check-docs:
|
||||||
|
uses: ./.github/workflows/check-docs.yml
|
||||||
|
|
||||||
setup:
|
setup:
|
||||||
runs-on: ubuntu-24.04
|
runs-on: ubuntu-24.04
|
||||||
|
needs: check-docs
|
||||||
steps:
|
steps:
|
||||||
- name: Set up QEMU
|
- name: Set up QEMU
|
||||||
uses: docker/setup-qemu-action@v3
|
uses: docker/setup-qemu-action@ce360397dd3f832beb865e1373c09c0e9f86d70a # v4.0.0
|
||||||
- name: Set up Docker Buildx
|
- name: Set up Docker Buildx
|
||||||
uses: docker/setup-buildx-action@v3
|
uses: docker/setup-buildx-action@4d04d5d9486b7bd6fa91e7baf45bbb4f8b9deedd # v4.0.0
|
||||||
- name: Available platforms
|
- name: Available platforms
|
||||||
run: echo ${{ steps.buildx.outputs.platforms }}
|
run: echo ${{ steps.buildx.outputs.platforms }}
|
||||||
- name: Install Podman
|
- name: Install Podman
|
||||||
@ -24,11 +30,11 @@ jobs:
|
|||||||
runs-on: ubuntu-24.04
|
runs-on: ubuntu-24.04
|
||||||
needs: setup
|
needs: setup
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@master
|
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
||||||
with:
|
with:
|
||||||
ref: ${{ github.ref }}
|
ref: ${{ github.ref }}
|
||||||
- name: Login to Docker Hub
|
- name: Login to Docker Hub
|
||||||
uses: docker/login-action@v1
|
uses: docker/login-action@4907a6ddec9925e35a0a9e82d7399ccc52663121 # v4.1.0
|
||||||
with:
|
with:
|
||||||
username: ${{ secrets.DOCKERHUB_USERNAME }}
|
username: ${{ secrets.DOCKERHUB_USERNAME }}
|
||||||
password: ${{ secrets.DOCKERHUB_TOKEN }}
|
password: ${{ secrets.DOCKERHUB_TOKEN }}
|
||||||
|
|||||||
14
.github/workflows/release-productive-version.yml
vendored
14
.github/workflows/release-productive-version.yml
vendored
@ -7,15 +7,21 @@ on:
|
|||||||
description: 'Version'
|
description: 'Version'
|
||||||
required: true
|
required: true
|
||||||
|
|
||||||
|
permissions:
|
||||||
|
contents: read
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
|
check-docs:
|
||||||
|
uses: ./.github/workflows/check-docs.yml
|
||||||
|
|
||||||
setup:
|
setup:
|
||||||
runs-on: ubuntu-24.04
|
runs-on: ubuntu-24.04
|
||||||
|
needs: check-docs
|
||||||
steps:
|
steps:
|
||||||
- name: Set up QEMU
|
- name: Set up QEMU
|
||||||
uses: docker/setup-qemu-action@v3
|
uses: docker/setup-qemu-action@ce360397dd3f832beb865e1373c09c0e9f86d70a # v4.0.0
|
||||||
- name: Set up Docker Buildx
|
- name: Set up Docker Buildx
|
||||||
uses: docker/setup-buildx-action@v3
|
uses: docker/setup-buildx-action@4d04d5d9486b7bd6fa91e7baf45bbb4f8b9deedd # v4.0.0
|
||||||
- name: Available platforms
|
- name: Available platforms
|
||||||
run: echo ${{ steps.buildx.outputs.platforms }}
|
run: echo ${{ steps.buildx.outputs.platforms }}
|
||||||
- name: Install Podman
|
- name: Install Podman
|
||||||
@ -24,11 +30,11 @@ jobs:
|
|||||||
runs-on: ubuntu-24.04
|
runs-on: ubuntu-24.04
|
||||||
needs: setup
|
needs: setup
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@master
|
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
||||||
with:
|
with:
|
||||||
ref: ${{ github.ref }}
|
ref: ${{ github.ref }}
|
||||||
- name: Login to Docker Hub
|
- name: Login to Docker Hub
|
||||||
uses: docker/login-action@v1
|
uses: docker/login-action@4907a6ddec9925e35a0a9e82d7399ccc52663121 # v4.1.0
|
||||||
with:
|
with:
|
||||||
username: ${{ secrets.DOCKERHUB_USERNAME }}
|
username: ${{ secrets.DOCKERHUB_USERNAME }}
|
||||||
password: ${{ secrets.DOCKERHUB_TOKEN }}
|
password: ${{ secrets.DOCKERHUB_TOKEN }}
|
||||||
|
|||||||
83
Dockerfile
83
Dockerfile
@ -1,9 +1,7 @@
|
|||||||
ARG SIGNAL_CLI_VERSION=0.14.3
|
ARG SIGNAL_CLI_VERSION=0.14.3
|
||||||
ARG LIBSIGNAL_CLIENT_VERSION=0.92.1
|
ARG LIBSIGNAL_CLIENT_VERSION=0.92.1
|
||||||
ARG SIGNAL_CLI_NATIVE_PACKAGE_VERSION=0.14.3+morph027+1
|
|
||||||
|
|
||||||
ARG SWAG_VERSION=1.16.4
|
ARG SWAG_VERSION=1.16.4
|
||||||
ARG GRAALVM_VERSION=25.0.2
|
|
||||||
|
|
||||||
ARG BUILD_VERSION_ARG=unset
|
ARG BUILD_VERSION_ARG=unset
|
||||||
|
|
||||||
@ -12,9 +10,7 @@ FROM golang:1.26-trixie AS buildcontainer
|
|||||||
ARG SIGNAL_CLI_VERSION
|
ARG SIGNAL_CLI_VERSION
|
||||||
ARG LIBSIGNAL_CLIENT_VERSION
|
ARG LIBSIGNAL_CLIENT_VERSION
|
||||||
ARG SWAG_VERSION
|
ARG SWAG_VERSION
|
||||||
ARG GRAALVM_VERSION
|
|
||||||
ARG BUILD_VERSION_ARG
|
ARG BUILD_VERSION_ARG
|
||||||
ARG SIGNAL_CLI_NATIVE_PACKAGE_VERSION
|
|
||||||
|
|
||||||
RUN dpkg-reconfigure debconf --frontend=noninteractive \
|
RUN dpkg-reconfigure debconf --frontend=noninteractive \
|
||||||
&& apt-get update \
|
&& apt-get update \
|
||||||
@ -23,8 +19,6 @@ RUN dpkg-reconfigure debconf --frontend=noninteractive \
|
|||||||
file build-essential libz-dev zlib1g-dev binutils \
|
file build-essential libz-dev zlib1g-dev binutils \
|
||||||
&& rm -rf /var/lib/apt/lists/*
|
&& rm -rf /var/lib/apt/lists/*
|
||||||
|
|
||||||
COPY ext/libraries/libsignal-client/signal-cli-native.patch /tmp/signal-cli-native.patch
|
|
||||||
|
|
||||||
#COPY ext/libraries/libsignal-client/v${LIBSIGNAL_CLIENT_VERSION} /tmp/libsignal-client-libraries
|
#COPY ext/libraries/libsignal-client/v${LIBSIGNAL_CLIENT_VERSION} /tmp/libsignal-client-libraries
|
||||||
RUN wget https://github.com/bbernhard/libsignal-client-builds/releases/download/v${LIBSIGNAL_CLIENT_VERSION}/libsignal-client-build-v${LIBSIGNAL_CLIENT_VERSION}.tar.gz -O /tmp/libsignal-client.tar.gz
|
RUN wget https://github.com/bbernhard/libsignal-client-builds/releases/download/v${LIBSIGNAL_CLIENT_VERSION}/libsignal-client-build-v${LIBSIGNAL_CLIENT_VERSION}.tar.gz -O /tmp/libsignal-client.tar.gz
|
||||||
RUN cd /tmp && mkdir -p /tmp/libsignal-client-libraries && tar xf libsignal-client.tar.gz && mv x86-64 armv7 arm64 -t libsignal-client-libraries
|
RUN cd /tmp && mkdir -p /tmp/libsignal-client-libraries && tar xf libsignal-client.tar.gz && mv x86-64 armv7 arm64 -t libsignal-client-libraries
|
||||||
@ -46,71 +40,27 @@ ENV JAVA_OPTS="-Djdk.lang.Process.launchMechanism=vfork"
|
|||||||
|
|
||||||
ENV LANG en_US.UTF-8
|
ENV LANG en_US.UTF-8
|
||||||
|
|
||||||
#RUN cd /tmp/ \
|
|
||||||
# && git clone https://github.com/swaggo/swag.git swag-${SWAG_VERSION} \
|
|
||||||
# && cd swag-${SWAG_VERSION} \
|
|
||||||
# && git checkout -q v${SWAG_VERSION} \
|
|
||||||
# && make -s < /dev/null > /dev/null \
|
|
||||||
# && cp /tmp/swag-${SWAG_VERSION}/swag /usr/bin/swag \
|
|
||||||
# && rm -r /tmp/swag-${SWAG_VERSION}
|
|
||||||
|
|
||||||
|
|
||||||
RUN go install github.com/swaggo/swag/cmd/swag@v${SWAG_VERSION}
|
RUN go install github.com/swaggo/swag/cmd/swag@v${SWAG_VERSION}
|
||||||
|
|
||||||
|
|
||||||
RUN cd /tmp/ \
|
RUN cd /tmp/ \
|
||||||
&& wget -nv https://github.com/AsamK/signal-cli/releases/download/v${SIGNAL_CLI_VERSION}/signal-cli-${SIGNAL_CLI_VERSION}.tar.gz -O /tmp/signal-cli.tar.gz \
|
&& wget -nv https://github.com/AsamK/signal-cli/releases/download/v${SIGNAL_CLI_VERSION}/signal-cli-${SIGNAL_CLI_VERSION}.tar.gz -O /tmp/signal-cli.tar.gz \
|
||||||
&& tar xf signal-cli.tar.gz
|
&& tar xf signal-cli.tar.gz
|
||||||
|
|
||||||
# build native image with graalvm
|
|
||||||
|
|
||||||
RUN arch="$(uname -m)"; \
|
|
||||||
case "$arch" in \
|
|
||||||
aarch64) wget -nv https://github.com/graalvm/graalvm-ce-builds/releases/download/jdk-${GRAALVM_VERSION}/graalvm-community-jdk-${GRAALVM_VERSION}_linux-aarch64_bin.tar.gz -O /tmp/gvm.tar.gz ;; \
|
|
||||||
armv7l) echo "GRAALVM doesn't support 32bit" ;; \
|
|
||||||
x86_64) wget -nv https://github.com/graalvm/graalvm-ce-builds/releases/download/jdk-${GRAALVM_VERSION}/graalvm-community-jdk-${GRAALVM_VERSION}_linux-x64_bin.tar.gz -O /tmp/gvm.tar.gz ;; \
|
|
||||||
*) echo "Invalid architecture" ;; \
|
|
||||||
esac;
|
|
||||||
|
|
||||||
RUN if [ "$(uname -m)" = "x86_64" ]; then \
|
RUN if [ "$(uname -m)" = "x86_64" ]; then \
|
||||||
cd /tmp \
|
cd /tmp \
|
||||||
&& git clone https://github.com/AsamK/signal-cli.git signal-cli-${SIGNAL_CLI_VERSION}-source \
|
&& wget https://github.com/bbernhard/signal-cli-native-builds/releases/download/v${SIGNAL_CLI_VERSION}/signal-cli-native-v${SIGNAL_CLI_VERSION}.tar.gz \
|
||||||
&& cd signal-cli-${SIGNAL_CLI_VERSION}-source \
|
&& tar xvf signal-cli-native-v${SIGNAL_CLI_VERSION}.tar.gz \
|
||||||
&& git checkout -q v${SIGNAL_CLI_VERSION} \
|
&& cp signal-cli-native-v${SIGNAL_CLI_VERSION}/x86-64/signal-cli-native /tmp/signal-cli-native; \
|
||||||
&& cd /tmp && mkdir -p /tmp/graalvm && tar xf gvm.tar.gz -C /tmp/graalvm --strip-components=1 \
|
|
||||||
&& export GRAALVM_HOME=/tmp/graalvm \
|
|
||||||
&& export PATH=/tmp/graalvm/bin:$PATH \
|
|
||||||
&& cd /tmp/signal-cli-${SIGNAL_CLI_VERSION}-source \
|
|
||||||
&& sed -i 's/Signal-Android\/5.22.3/Signal-Android\/5.51.7/g' src/main/java/org/asamk/signal/BaseConfig.java \
|
|
||||||
&& ./gradlew build \
|
|
||||||
&& ./gradlew installDist \
|
|
||||||
&& ls build/install/signal-cli/lib/libsignal-client-${LIBSIGNAL_CLIENT_VERSION}.jar || (echo "\n\nsignal-client jar file with version ${LIBSIGNAL_CLIENT_VERSION} not found. Maybe the version needs to be bumped in the signal-cli-rest-api Dockerfile?\n\n" && echo "Available version: \n" && ls build/install/signal-cli/lib/libsignal-client-* && echo "\n\n" && exit 1) \
|
|
||||||
&& cd /tmp \
|
|
||||||
&& cp signal-cli-${SIGNAL_CLI_VERSION}-source/build/install/signal-cli/lib/libsignal-client-${LIBSIGNAL_CLIENT_VERSION}.jar libsignal-client.jar \
|
|
||||||
&& zip -qu libsignal-client.jar libsignal_jni.so \
|
|
||||||
&& cd /tmp/signal-cli-${SIGNAL_CLI_VERSION}-source \
|
|
||||||
&& git apply /tmp/signal-cli-native.patch \
|
|
||||||
&& ./gradlew -q nativeCompile; \
|
|
||||||
elif [ "$(uname -m)" = "aarch64" ] ; then \
|
elif [ "$(uname -m)" = "aarch64" ] ; then \
|
||||||
echo "Use native image from @morph027 (https://packaging.gitlab.io/signal-cli/) for arm64 - many thanks to @morph027" \
|
cd /tmp \
|
||||||
&& curl -fsSL https://packaging.gitlab.io/signal-cli/gpg.key | gpg -o /usr/share/keyrings/signal-cli-native.pgp --dearmor \
|
&& wget https://github.com/bbernhard/signal-cli-native-builds/releases/download/v${SIGNAL_CLI_VERSION}/signal-cli-native-v${SIGNAL_CLI_VERSION}.tar.gz \
|
||||||
&& echo "deb [signed-by=/usr/share/keyrings/signal-cli-native.pgp] https://packaging.gitlab.io/signal-cli signalcli main" > /etc/apt/sources.list.d/morph027-signal-cli.list \
|
&& tar xvf signal-cli-native-v${SIGNAL_CLI_VERSION}.tar.gz \
|
||||||
&& mkdir -p /tmp/signal-cli-native \
|
&& cp signal-cli-native-v${SIGNAL_CLI_VERSION}/arm64/signal-cli-native /tmp/signal-cli-native; \
|
||||||
&& cd /tmp/signal-cli-native \
|
|
||||||
&& wget https://gitlab.com/packaging/signal-cli/-/jobs/14049119045/artifacts/download?file_type=archive -O /tmp/signal-cli-native/archive.zip \
|
|
||||||
&& unzip archive.zip \
|
|
||||||
&& mv signal-cli-native-arm64-trigger/*deb . \
|
|
||||||
#&& apt-get update \
|
|
||||||
#&& apt-get download signal-cli-native=${SIGNAL_CLI_NATIVE_PACKAGE_VERSION} \
|
|
||||||
&& ar x *.deb \
|
|
||||||
&& tar xf data.tar.gz \
|
|
||||||
&& mkdir -p /tmp/signal-cli-${SIGNAL_CLI_VERSION}-source/build/native/nativeCompile \
|
|
||||||
&& cp /tmp/signal-cli-native/usr/bin/signal-cli-native /tmp/signal-cli-${SIGNAL_CLI_VERSION}-source/build/native/nativeCompile/signal-cli; \
|
|
||||||
elif [ "$(uname -m)" = "armv7l" ] ; then \
|
elif [ "$(uname -m)" = "armv7l" ] ; then \
|
||||||
echo "GRAALVM doesn't support 32bit" \
|
echo "GRAALVM doesn't support 32bit" \
|
||||||
&& echo "Creating temporary file, otherwise the below copy doesn't work for armv7" \
|
&& echo "Creating temporary file, otherwise the below copy doesn't work for armv7" \
|
||||||
&& mkdir -p /tmp/signal-cli-${SIGNAL_CLI_VERSION}-source/build/native/nativeCompile \
|
&& mkdir -p /tmp/signal-cli-${SIGNAL_CLI_VERSION}-source/build/native/nativeCompile \
|
||||||
&& touch /tmp/signal-cli-${SIGNAL_CLI_VERSION}-source/build/native/nativeCompile/signal-cli; \
|
&& touch /tmp/signal-cli-native; \
|
||||||
else \
|
else \
|
||||||
echo "Unknown architecture"; \
|
echo "Unknown architecture"; \
|
||||||
fi;
|
fi;
|
||||||
@ -142,10 +92,21 @@ COPY src/main.go /tmp/signal-cli-rest-api-src/
|
|||||||
COPY src/go.mod /tmp/signal-cli-rest-api-src/
|
COPY src/go.mod /tmp/signal-cli-rest-api-src/
|
||||||
COPY src/go.sum /tmp/signal-cli-rest-api-src/
|
COPY src/go.sum /tmp/signal-cli-rest-api-src/
|
||||||
COPY src/plugin_loader.go /tmp/signal-cli-rest-api-src/
|
COPY src/plugin_loader.go /tmp/signal-cli-rest-api-src/
|
||||||
|
COPY src/docs/add_v1_receive_schemas.go /tmp/signal-cli-rest-api-src/docs/add_v1_receive_schemas.go
|
||||||
|
|
||||||
|
RUN ls -la /tmp/signal-cli-rest-api-src
|
||||||
|
|
||||||
|
# build the docs
|
||||||
|
RUN cd /tmp/signal-cli-rest-api-src && ${GOPATH}/bin/swag init --requiredByDefault --outputTypes "go,json"
|
||||||
|
|
||||||
|
# manually add the json schemas for the receive V1 endpoint to the docs
|
||||||
|
RUN cd /tmp/signal-cli-rest-api-src/docs \
|
||||||
|
&& wget https://github.com/Gara-Dorta/signal-cli/releases/download/v${SIGNAL_CLI_VERSION}/signal-cli-${SIGNAL_CLI_VERSION}-json-schemas.tar.gz \
|
||||||
|
&& mkdir signal-cli-schemas \
|
||||||
|
&& tar xf signal-cli-${SIGNAL_CLI_VERSION}-json-schemas.tar.gz -C signal-cli-schemas \
|
||||||
|
&& go run add_v1_receive_schemas.go signal-cli-schemas
|
||||||
|
|
||||||
# build signal-cli-rest-api
|
# build signal-cli-rest-api
|
||||||
RUN ls -la /tmp/signal-cli-rest-api-src
|
|
||||||
RUN cd /tmp/signal-cli-rest-api-src && ${GOPATH}/bin/swag init --requiredByDefault
|
|
||||||
RUN cd /tmp/signal-cli-rest-api-src && go build -o signal-cli-rest-api main.go
|
RUN cd /tmp/signal-cli-rest-api-src && go build -o signal-cli-rest-api main.go
|
||||||
RUN cd /tmp/signal-cli-rest-api-src && go test ./client -v && go test ./utils -v
|
RUN cd /tmp/signal-cli-rest-api-src && go test ./client -v && go test ./utils -v
|
||||||
|
|
||||||
@ -180,7 +141,7 @@ RUN dpkg-reconfigure debconf --frontend=noninteractive \
|
|||||||
|
|
||||||
COPY --from=buildcontainer /tmp/signal-cli-rest-api-src/signal-cli-rest-api /usr/bin/signal-cli-rest-api
|
COPY --from=buildcontainer /tmp/signal-cli-rest-api-src/signal-cli-rest-api /usr/bin/signal-cli-rest-api
|
||||||
COPY --from=buildcontainer /opt/signal-cli-${SIGNAL_CLI_VERSION} /opt/signal-cli-${SIGNAL_CLI_VERSION}
|
COPY --from=buildcontainer /opt/signal-cli-${SIGNAL_CLI_VERSION} /opt/signal-cli-${SIGNAL_CLI_VERSION}
|
||||||
COPY --from=buildcontainer /tmp/signal-cli-${SIGNAL_CLI_VERSION}-source/build/native/nativeCompile/signal-cli /opt/signal-cli-${SIGNAL_CLI_VERSION}/bin/signal-cli-native
|
COPY --from=buildcontainer /tmp/signal-cli-native /opt/signal-cli-${SIGNAL_CLI_VERSION}/bin/signal-cli-native
|
||||||
COPY --from=buildcontainer /tmp/signal-cli-rest-api-src/scripts/jsonrpc2-helper /usr/bin/jsonrpc2-helper
|
COPY --from=buildcontainer /tmp/signal-cli-rest-api-src/scripts/jsonrpc2-helper /usr/bin/jsonrpc2-helper
|
||||||
COPY --from=buildcontainer /tmp/signal-cli-rest-api-src/signal-cli-rest-api_plugin_loader.so /usr/bin/signal-cli-rest-api_plugin_loader.so
|
COPY --from=buildcontainer /tmp/signal-cli-rest-api-src/signal-cli-rest-api_plugin_loader.so /usr/bin/signal-cli-rest-api_plugin_loader.so
|
||||||
COPY entrypoint.sh /entrypoint.sh
|
COPY entrypoint.sh /entrypoint.sh
|
||||||
|
|||||||
@ -4,44 +4,64 @@ These files are generated using the [swaggo/swag](https://github.com/swaggo/swag
|
|||||||
|
|
||||||
There are two steps, first generating the docs and then running the web server.
|
There are two steps, first generating the docs and then running the web server.
|
||||||
|
|
||||||
## Generating the docs
|
## With docker compose (recommended)
|
||||||
|
|
||||||
Regenerate the files with your local source code changes.
|
1. Build the docs
|
||||||
|
```bash
|
||||||
|
docker compose build
|
||||||
|
```
|
||||||
|
2. Serve the docs
|
||||||
|
```bash
|
||||||
|
docker compose up
|
||||||
|
```
|
||||||
|
3. Go to http://127.0.0.1:8080/swagger/index.html to view the docs
|
||||||
|
* If you get a Network error, replace the IP for the docker internal IP in the error, e.g: http://172.18.0.2:8080/swagger/index.html
|
||||||
|
|
||||||
|
## Locally
|
||||||
|
|
||||||
|
Install [go](https://go.dev/).
|
||||||
|
|
||||||
|
### Generating the docs
|
||||||
|
|
||||||
1. Set the current working dir to `src`
|
1. Set the current working dir to `src`
|
||||||
```bash
|
```bash
|
||||||
cd src
|
cd src
|
||||||
```
|
```
|
||||||
1. Run swag to generate the docs
|
1. Run swag to generate the docs
|
||||||
* Option 1, via docker
|
* Option 1, via go
|
||||||
```bash
|
```bash
|
||||||
docker run --rm -v $(pwd):/code ghcr.io/swaggo/swag:latest init --requiredByDefault
|
go run github.com/swaggo/swag/cmd/swag@v1.16.6 init --requiredByDefault --outputTypes "go,json"
|
||||||
```
|
```
|
||||||
* Option 2, install swag and run the command line tool
|
* Option 2, directly with swag
|
||||||
```bash
|
```bash
|
||||||
swag init --requiredByDefault
|
swag init --requiredByDefault --outputTypes "go,json"
|
||||||
|
```
|
||||||
|
* Option 3, swag via docker
|
||||||
|
```bash
|
||||||
|
docker run --rm -v $(pwd):/code ghcr.io/swaggo/swag:latest init --requiredByDefault --outputTypes "go,json"
|
||||||
|
```
|
||||||
|
1. Set the current working dir to `src/docs`
|
||||||
|
```bash
|
||||||
|
cd docs
|
||||||
|
```
|
||||||
|
1. Add the signal-cli receive V1 schemas
|
||||||
|
* Download the `signal-cli-x.y.z-json-schemas.tar.gz` schema files from https://github.com/Gara-Dorta/signal-cli/releases
|
||||||
|
* Extract the files
|
||||||
|
* Run the script to add the schemas
|
||||||
|
```bash
|
||||||
|
go run add_v1_receive_schemas.go ./path-to-signal-cli-json-schema-folder
|
||||||
```
|
```
|
||||||
|
|
||||||
## Run the web server
|
### Run the web server
|
||||||
|
|
||||||
Run the web server to visualize the generated docs.
|
Run the web server to visualize the generated docs.
|
||||||
|
|
||||||
|
1. Navigate to the `src` folder
|
||||||
|
```bash
|
||||||
|
cd src
|
||||||
|
```
|
||||||
1. Run the main script
|
1. Run the main script
|
||||||
* Option 1, via docker, run the command at the root of the repository
|
```bash
|
||||||
```bash
|
go run main.go
|
||||||
docker compose up
|
```
|
||||||
```
|
1. Go to http://127.0.0.1:8080/swagger/index.html
|
||||||
* Option 2, install go and run the command line tool
|
|
||||||
```bash
|
|
||||||
cd src
|
|
||||||
```
|
|
||||||
```bash
|
|
||||||
go run main.go
|
|
||||||
```
|
|
||||||
|
|
||||||
|
|
||||||
## Navigate to the docs
|
|
||||||
|
|
||||||
The docs are served at: http://127.0.0.1:8080/swagger/index.html
|
|
||||||
|
|
||||||
When serving with docker, if you get a Network error, replace the IP for the docker internal IP in the error, e.g: http://172.18.0.2:8080/swagger/index.html
|
|
||||||
|
|||||||
327
src/docs/add_v1_receive_schemas.go
Normal file
327
src/docs/add_v1_receive_schemas.go
Normal file
@ -0,0 +1,327 @@
|
|||||||
|
//go:build ignore
|
||||||
|
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
"fmt"
|
||||||
|
"os"
|
||||||
|
"path/filepath"
|
||||||
|
"sort"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
_ "github.com/bbernhard/signal-cli-rest-api/docs"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
goDocsPath = "docs.go"
|
||||||
|
jsonDocsPath = "swagger.json"
|
||||||
|
openMarker = "const docTemplate = `"
|
||||||
|
closeMarker = "`\n\n// SwaggerInfo"
|
||||||
|
schemesTemplateValue = "{{ marshal .Schemes }}"
|
||||||
|
schemesPlaceholderToken = "__SWAG_SCHEMES_PLACEHOLDER__"
|
||||||
|
receivePrefix = "receive."
|
||||||
|
receivePathKey = "/v1/receive/{number}"
|
||||||
|
receiveWrapper = "data.Message"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
if len(os.Args) != 2 {
|
||||||
|
fmt.Fprintf(os.Stderr, "usage: go run update_receive_docs.go <receiveDir>\n")
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
|
receiveDir := os.Args[1]
|
||||||
|
|
||||||
|
if err := run(receiveDir); err != nil {
|
||||||
|
fmt.Fprintf(os.Stderr, "error: %v\n", err)
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func run(receiveDir string) error {
|
||||||
|
definitions := make(map[string]interface{})
|
||||||
|
|
||||||
|
titleByFile, err := addReceiveSchemas(definitions, receiveDir)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
updateReceiveSchemaRefs(definitions, titleByFile)
|
||||||
|
|
||||||
|
addEnvelopeWrapperDefinition(definitions)
|
||||||
|
|
||||||
|
if err := updateDocsGo(definitions); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := updateSwaggerJSON(definitions); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
fmt.Printf("updated %s\n", goDocsPath)
|
||||||
|
fmt.Printf("updated %s\n", jsonDocsPath)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func updateDocsGo(receiveDefinitions map[string]interface{}) error {
|
||||||
|
content, err := os.ReadFile(goDocsPath)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("read %s: %w", goDocsPath, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
template, templateStart, templateEnd, err := extractDocTemplate(string(content))
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
updatedTemplate, err := updateJSONDocument(toValidJson(template), receiveDefinitions)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
updatedTemplate = encodeForGoRawString(updatedTemplate)
|
||||||
|
|
||||||
|
updated := string(content[:templateStart]) + updatedTemplate + string(content[templateEnd:])
|
||||||
|
if err := os.WriteFile(goDocsPath, []byte(updated), 0644); err != nil {
|
||||||
|
return fmt.Errorf("write %s: %w", goDocsPath, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func updateSwaggerJSON(receiveDefinitions map[string]interface{}) error {
|
||||||
|
content, err := os.ReadFile(jsonDocsPath)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("read %s: %w", jsonDocsPath, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
updated, err := updateJSONDocument(string(content), receiveDefinitions)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := os.WriteFile(jsonDocsPath, []byte(updated), 0644); err != nil {
|
||||||
|
return fmt.Errorf("write %s: %w", jsonDocsPath, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func extractDocTemplate(content string) (string, int, int, error) {
|
||||||
|
start := strings.Index(content, openMarker)
|
||||||
|
if start == -1 {
|
||||||
|
return "", -1, -1, fmt.Errorf("could not find docTemplate start in %s", goDocsPath)
|
||||||
|
}
|
||||||
|
|
||||||
|
start += len(openMarker)
|
||||||
|
endOffset := strings.Index(content[start:], closeMarker)
|
||||||
|
if endOffset == -1 {
|
||||||
|
return "", -1, -1, fmt.Errorf("could not find docTemplate end in %s", goDocsPath)
|
||||||
|
}
|
||||||
|
|
||||||
|
end := start + endOffset
|
||||||
|
return content[start:end], start, end, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func toValidJson(content string) string {
|
||||||
|
content = strings.ReplaceAll(content, "` + \"`\" + `", "`")
|
||||||
|
content = strings.Replace(content, schemesTemplateValue, `"`+schemesPlaceholderToken+`"`, 1)
|
||||||
|
return content
|
||||||
|
}
|
||||||
|
|
||||||
|
func encodeForGoRawString(content string) string {
|
||||||
|
content = strings.ReplaceAll(content, "`", "` + \"`\" + `")
|
||||||
|
content = strings.Replace(content, `"`+schemesPlaceholderToken+`"`, schemesTemplateValue, 1)
|
||||||
|
return content
|
||||||
|
}
|
||||||
|
|
||||||
|
func updateJSONDocument(content string, receiveDefinitions map[string]interface{}) (string, error) {
|
||||||
|
var document map[string]interface{}
|
||||||
|
if err := json.Unmarshal([]byte(content), &document); err != nil {
|
||||||
|
return "", fmt.Errorf("parse document: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := applyReceiveSchemaUpdates(document, receiveDefinitions); err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
|
||||||
|
raw, err := json.MarshalIndent(document, "", " ")
|
||||||
|
if err != nil {
|
||||||
|
return "", fmt.Errorf("marshal document: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return string(raw), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func addReceiveSchemas(definitions map[string]interface{}, receiveDir string) (map[string]string, error) {
|
||||||
|
entries, err := os.ReadDir(receiveDir)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("read %s: %w", receiveDir, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
files := make([]string, 0)
|
||||||
|
for _, entry := range entries {
|
||||||
|
if entry.IsDir() || !strings.HasSuffix(entry.Name(), ".schema.json") {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
files = append(files, entry.Name())
|
||||||
|
}
|
||||||
|
sort.Strings(files)
|
||||||
|
titleByFile := make(map[string]string, len(files))
|
||||||
|
|
||||||
|
for _, name := range files {
|
||||||
|
fullPath := filepath.Join(receiveDir, name)
|
||||||
|
data, err := os.ReadFile(fullPath)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("read schema file %s: %w", fullPath, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
var schemaObj map[string]interface{}
|
||||||
|
if err := json.Unmarshal(data, &schemaObj); err != nil {
|
||||||
|
return nil, fmt.Errorf("parse schema file %s: %w", fullPath, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
title, ok := schemaObj["title"].(string)
|
||||||
|
if !ok || strings.TrimSpace(title) == "" {
|
||||||
|
return nil, fmt.Errorf("schema file %s is missing title", fullPath)
|
||||||
|
}
|
||||||
|
|
||||||
|
titleByFile[name] = title
|
||||||
|
definitions[receivePrefix+title] = removeSchemaKeysRecursive(schemaObj, "")
|
||||||
|
}
|
||||||
|
|
||||||
|
return titleByFile, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func removeSchemaKeysRecursive(value interface{}, parentKey string) interface{} {
|
||||||
|
switch typed := value.(type) {
|
||||||
|
case map[string]interface{}:
|
||||||
|
updated := make(map[string]interface{}, len(typed))
|
||||||
|
for key, item := range typed {
|
||||||
|
if key == "$schema" || key == "$id" {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if key == "title" && parentKey != "properties" {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
updated[key] = removeSchemaKeysRecursive(item, key)
|
||||||
|
}
|
||||||
|
return updated
|
||||||
|
case []interface{}:
|
||||||
|
updated := make([]interface{}, len(typed))
|
||||||
|
for idx, item := range typed {
|
||||||
|
updated[idx] = removeSchemaKeysRecursive(item, parentKey)
|
||||||
|
}
|
||||||
|
return updated
|
||||||
|
default:
|
||||||
|
return value
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func updateReceiveSchemaRefs(definitions map[string]interface{}, titleByFile map[string]string) {
|
||||||
|
for key, value := range definitions {
|
||||||
|
if !strings.HasPrefix(key, receivePrefix) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
definitions[key] = rewriteSchemaRefs(value, titleByFile)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func rewriteSchemaRefs(value interface{}, titleByFile map[string]string) interface{} {
|
||||||
|
switch typed := value.(type) {
|
||||||
|
case map[string]interface{}:
|
||||||
|
updated := make(map[string]interface{}, len(typed))
|
||||||
|
for k, v := range typed {
|
||||||
|
if k == "$ref" {
|
||||||
|
if refValue, ok := v.(string); ok {
|
||||||
|
if strings.HasSuffix(refValue, ".schema.json") {
|
||||||
|
base := filepath.Base(refValue)
|
||||||
|
if title, exists := titleByFile[base]; exists {
|
||||||
|
updated[k] = "#/definitions/" + receivePrefix + title
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
updated[k] = rewriteSchemaRefs(v, titleByFile)
|
||||||
|
}
|
||||||
|
return updated
|
||||||
|
case []interface{}:
|
||||||
|
updated := make([]interface{}, len(typed))
|
||||||
|
for idx, item := range typed {
|
||||||
|
updated[idx] = rewriteSchemaRefs(item, titleByFile)
|
||||||
|
}
|
||||||
|
return updated
|
||||||
|
default:
|
||||||
|
return value
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func addEnvelopeWrapperDefinition(definitions map[string]interface{}) {
|
||||||
|
definitions[receiveWrapper] = map[string]interface{}{
|
||||||
|
"type": "object",
|
||||||
|
"properties": map[string]interface{}{
|
||||||
|
"account": map[string]interface{}{"type": "string"},
|
||||||
|
"envelope": map[string]interface{}{"$ref": "#/definitions/receive.MessageEnvelope"},
|
||||||
|
},
|
||||||
|
"required": []interface{}{"account", "envelope"},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func applyReceiveSchemaUpdates(document map[string]interface{}, receiveDefinitions map[string]interface{}) error {
|
||||||
|
definitions, err := getObject(document, "definitions")
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
for key := range definitions {
|
||||||
|
if strings.HasPrefix(key, receivePrefix) || key == receiveWrapper {
|
||||||
|
delete(definitions, key)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for key, value := range receiveDefinitions {
|
||||||
|
definitions[key] = value
|
||||||
|
}
|
||||||
|
|
||||||
|
paths, err := getObject(document, "paths")
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
receivePath, err := getObject(paths, receivePathKey)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
receiveGet, err := getObject(receivePath, "get")
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
responses, err := getObject(receiveGet, "responses")
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
response200, err := getObject(responses, "200")
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
response200["schema"] = map[string]interface{}{
|
||||||
|
"$ref": "#/definitions/" + receiveWrapper,
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func getObject(parent map[string]interface{}, key string) (map[string]interface{}, error) {
|
||||||
|
value, ok := parent[key]
|
||||||
|
if !ok {
|
||||||
|
return nil, fmt.Errorf("missing key %q", key)
|
||||||
|
}
|
||||||
|
|
||||||
|
obj, ok := value.(map[string]interface{})
|
||||||
|
if !ok {
|
||||||
|
return nil, fmt.Errorf("key %q is not an object", key)
|
||||||
|
}
|
||||||
|
|
||||||
|
return obj, nil
|
||||||
|
}
|
||||||
7530
src/docs/docs.go
7530
src/docs/docs.go
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
Loading…
x
Reference in New Issue
Block a user