feat: up version
Signed-off-by: martabal <74269598+martabal@users.noreply.github.com>
This commit is contained in:
parent
cf29943ebe
commit
8a7ebfefa1
20 changed files with 336 additions and 322 deletions
|
@ -1,4 +1,7 @@
|
||||||
img/
|
img/
|
||||||
grafana/
|
grafana/
|
||||||
.github/
|
.github/
|
||||||
Dockerfile
|
Dockerfile
|
||||||
|
README.md
|
||||||
|
.env*
|
||||||
|
.gitignore
|
|
@ -1,3 +1,2 @@
|
||||||
IMMICH_USERNAME=
|
IMMICH_API_KEY=
|
||||||
IMMICH_PASSWORD=
|
|
||||||
IMMICH_BASE_URL=
|
IMMICH_BASE_URL=
|
17
.github/workflows/build.yml
vendored
Normal file
17
.github/workflows/build.yml
vendored
Normal file
|
@ -0,0 +1,17 @@
|
||||||
|
name: Build
|
||||||
|
on:
|
||||||
|
workflow_dispatch:
|
||||||
|
push:
|
||||||
|
branches: [ "main" ]
|
||||||
|
pull_request:
|
||||||
|
branches: [ "main" ]
|
||||||
|
jobs:
|
||||||
|
|
||||||
|
build:
|
||||||
|
name: Run build
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- name: Checkout code
|
||||||
|
uses: actions/checkout@v3
|
||||||
|
- name: Build
|
||||||
|
run: go build -o ./immich.out ./src
|
34
.github/workflows/codeql-analysis.yml
vendored
Normal file
34
.github/workflows/codeql-analysis.yml
vendored
Normal file
|
@ -0,0 +1,34 @@
|
||||||
|
name: CodeQL
|
||||||
|
|
||||||
|
on:
|
||||||
|
workflow_dispatch:
|
||||||
|
push:
|
||||||
|
branches: [ "main" ]
|
||||||
|
pull_request:
|
||||||
|
branches: [ "main" ]
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
analyze:
|
||||||
|
name: Analyze
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
permissions:
|
||||||
|
actions: read
|
||||||
|
contents: read
|
||||||
|
security-events: write
|
||||||
|
|
||||||
|
strategy:
|
||||||
|
fail-fast: false
|
||||||
|
matrix:
|
||||||
|
language: [ 'go' ]
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- name: Checkout repo
|
||||||
|
uses: actions/checkout@v2
|
||||||
|
|
||||||
|
- name: Initialize CodeQL
|
||||||
|
uses: github/codeql-action/init@v2
|
||||||
|
with:
|
||||||
|
languages: ${{ matrix.language }}
|
||||||
|
|
||||||
|
- name: CodeQL Analysis
|
||||||
|
uses: github/codeql-action/analyze@v2
|
|
@ -8,9 +8,7 @@ on:
|
||||||
type: string
|
type: string
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
|
build_docker_release:
|
||||||
|
|
||||||
build_push_monolith:
|
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout
|
- name: Checkout
|
||||||
|
@ -19,29 +17,34 @@ jobs:
|
||||||
ref: 'main'
|
ref: 'main'
|
||||||
fetch-depth: 0
|
fetch-depth: 0
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
- name: Set up QEMU
|
- name: Set up QEMU
|
||||||
uses: docker/setup-qemu-action@v2.1.0
|
uses: docker/setup-qemu-action@v2
|
||||||
|
|
||||||
- name: Set up Docker Buildx
|
- name: Set up Docker Buildx
|
||||||
id: buildx
|
id: buildx
|
||||||
uses: docker/setup-buildx-action@v2.2.1
|
uses: docker/setup-buildx-action@v2
|
||||||
|
|
||||||
- name: Login to Docker Hub
|
- name: Login to Docker Hub
|
||||||
uses: docker/login-action@v2
|
uses: docker/login-action@v2
|
||||||
with:
|
with:
|
||||||
username: martabal
|
username: martabal
|
||||||
password: ${{ secrets.DOCKERHUB_TOKEN }}
|
password: ${{ secrets.DOCKERHUB_TOKEN }}
|
||||||
|
|
||||||
|
- name: Login to GitHub Container Registry
|
||||||
|
uses: docker/login-action@v2
|
||||||
|
with:
|
||||||
|
registry: ghcr.io
|
||||||
|
username: ${{ github.repository_owner }}
|
||||||
|
password: ${{ secrets.GH_TOKEN }}
|
||||||
|
|
||||||
- name: Build and push immich
|
- name: Build and push
|
||||||
uses: docker/build-push-action@v3.2.0
|
uses: docker/build-push-action@v4
|
||||||
with:
|
with:
|
||||||
context: ./
|
context: ./
|
||||||
file: ./Dockerfile
|
|
||||||
platforms: linux/arm/v7,linux/amd64,linux/arm64
|
platforms: linux/arm/v7,linux/amd64,linux/arm64
|
||||||
push: ${{ github.event_name != 'pull_request' }}
|
push: ${{ github.event_name != 'pull_request' }}
|
||||||
tags: |
|
tags: |
|
||||||
martabal/immich-exporter:${{ inputs.tags }}
|
martabal/immich-exporter:${{ inputs.tags }}
|
||||||
martabal/immich-exporter:latest
|
martabal/immich-exporter:latest
|
||||||
|
ghcr.io/${{ github.repository_owner }}/immich-exporter:${{ inputs.tags }}
|
||||||
|
ghcr.io/${{ github.repository_owner }}/immich-exporter:latest
|
17
.github/workflows/test.yml
vendored
Normal file
17
.github/workflows/test.yml
vendored
Normal file
|
@ -0,0 +1,17 @@
|
||||||
|
name: Test
|
||||||
|
on:
|
||||||
|
workflow_dispatch:
|
||||||
|
push:
|
||||||
|
branches: [ "main" ]
|
||||||
|
pull_request:
|
||||||
|
branches: [ "main" ]
|
||||||
|
jobs:
|
||||||
|
|
||||||
|
test:
|
||||||
|
name: Run tests
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- name: Checkout code
|
||||||
|
uses: actions/checkout@v3
|
||||||
|
- name: Run formatter
|
||||||
|
run: test -z $(gofmt -l ./src)
|
11
Dockerfile
11
Dockerfile
|
@ -1,16 +1,17 @@
|
||||||
FROM golang:1.19-alpine3.17 AS builder
|
FROM golang:1.20-alpine3.18 AS builder
|
||||||
|
|
||||||
WORKDIR /app
|
WORKDIR /app
|
||||||
|
|
||||||
COPY . .
|
COPY . .
|
||||||
|
|
||||||
RUN go get -d -v ./src/ && \
|
RUN go build -o /go/bin/immich-exporter ./src
|
||||||
go build -o /go/bin/immich-exporter ./src
|
|
||||||
|
|
||||||
FROM alpine:3.17
|
|
||||||
|
FROM alpine:3.18
|
||||||
|
|
||||||
COPY --from=builder /go/bin/immich-exporter /go/bin/immich-exporter
|
COPY --from=builder /go/bin/immich-exporter /go/bin/immich-exporter
|
||||||
COPY package.json /go/bin/
|
COPY package.json /go/bin/
|
||||||
|
|
||||||
WORKDIR /go/bin
|
WORKDIR /go/bin
|
||||||
CMD ["/go/bin/immich-exporter"]
|
|
||||||
|
CMD ["/go/bin/immich-exporter"]
|
30
README.md
30
README.md
|
@ -1,6 +1,8 @@
|
||||||
# immich-exporter
|
# immich-exporter
|
||||||
|
|
||||||
[![Publish Release](https://github.com/martabal/immich-exporter/actions/workflows/push_docker.yml/badge.svg)](https://github.com/martabal/immich-exporter/actions/workflows/push_docker.yml)
|
[![Publish Release](https://github.com/martabal/immich-exporter/actions/workflows/docker.yml/badge.svg)](https://github.com/martabal/immich-exporter/actions/workflows/docker.yml)
|
||||||
|
[![Build](https://github.com/martabal/immich-exporter/actions/workflows/build.yml/badge.svg)](https://github.com/martabal/immich-exporter/actions/workflows/build.yml)
|
||||||
|
[![Test](https://github.com/martabal/immich-exporter/actions/workflows/test.yml/badge.svg)](https://github.com/martabal/immich-exporter/actions/workflows/test.yml)
|
||||||
|
|
||||||
<p align="center">
|
<p align="center">
|
||||||
<img src="img/immich.png" width=100> <img src="img/prometheus.png" width=100><img src="img/golang.png" width=100>
|
<img src="img/immich.png" width=100> <img src="img/prometheus.png" width=100><img src="img/golang.png" width=100>
|
||||||
|
@ -11,13 +13,14 @@ This app is made to be integrated with the [immich-grafana-dashboard](https://gi
|
||||||
|
|
||||||
## Run it
|
## Run it
|
||||||
|
|
||||||
|
Create an API key in your Immich settings and set `IMMICH_API_KEY` to is value.
|
||||||
|
|
||||||
### Docker-cli ([click here for more info](https://docs.docker.com/engine/reference/commandline/cli/))
|
### Docker-cli ([click here for more info](https://docs.docker.com/engine/reference/commandline/cli/))
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
docker run --name=immich-exporter \
|
docker run --name=immich-exporter \
|
||||||
-e IMMICH_URL=http://192.168.1.10:8080 \
|
-e IMMICH_URL=http://192.168.1.10:8080 \
|
||||||
-e IMMICH_PASSWORD='<your_password>' \
|
-e IMMICH_API_KEY=<your_api_key> \
|
||||||
-e IMMICH_USERNAME=admin \
|
|
||||||
-p 8090:8090 \
|
-p 8090:8090 \
|
||||||
martabal/immich-exporter
|
martabal/immich-exporter
|
||||||
```
|
```
|
||||||
|
@ -32,8 +35,7 @@ services:
|
||||||
container_name: immich-exporter
|
container_name: immich-exporter
|
||||||
environment:
|
environment:
|
||||||
- IMMICH_URL=http://192.168.1.10:8080
|
- IMMICH_URL=http://192.168.1.10:8080
|
||||||
- IMMICH_PASSWORD='<your_password>'
|
- IMMICH_API_KEY=<your_api_key>
|
||||||
- IMMICH_USERNAME=admin
|
|
||||||
ports:
|
ports:
|
||||||
- 8090:8090
|
- 8090:8090
|
||||||
restart: unless-stopped
|
restart: unless-stopped
|
||||||
|
@ -63,12 +65,24 @@ If you want to use an .env file, edit `.env.example` to match your setup, rename
|
||||||
| Parameters | Function |
|
| Parameters | Function |
|
||||||
| :-----: | ----- |
|
| :-----: | ----- |
|
||||||
| `-p 8090` | Webservice port |
|
| `-p 8090` | Webservice port |
|
||||||
| `-e IMMICH_USERNAME` | Immich username |
|
|
||||||
| `-e IMMICH_PASSWORD` | Immich password |
|
|
||||||
| `-e IMMICH_BASE_URL` | Immich base URL |
|
| `-e IMMICH_BASE_URL` | Immich base URL |
|
||||||
|
| `-e IMMICH_API_KEY` | Immich API key |
|
||||||
|
| `-e EXPORTER_PORT` | qbittorrent export port (optional) | `8090` |
|
||||||
|
| `-e LOG_LEVEL` | App log level (`TRACE`, `DEBUG`, `INFO`, `WARN` and `ERROR`) | `INFO` |
|
||||||
|
|
||||||
### Arguments
|
### Arguments
|
||||||
|
|
||||||
| Arguments | Function |
|
| Arguments | Function |
|
||||||
| :-----: | ----- |
|
| :-----: | ----- |
|
||||||
| -e | Use a .env file containing environment variables (.env file must be placed in the same directory) |
|
| -e | If qbittorrent-exporter detects a .env file in the same directory, the values in the .env will be used, `-e` forces the usage of environment variables |
|
||||||
|
|
||||||
|
### Setup
|
||||||
|
|
||||||
|
Add the target to your `scrape_configs` in your `prometheus.yml` file of your Prometheus instance.
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
scrape_configs:
|
||||||
|
- job_name: 'immich'
|
||||||
|
static_configs:
|
||||||
|
- targets: [ '<your_ip_address>:8090' ]
|
||||||
|
```
|
||||||
|
|
10
go.mod
10
go.mod
|
@ -1,15 +1,19 @@
|
||||||
module immich-exporter
|
module immich-exp
|
||||||
|
|
||||||
go 1.20
|
go 1.20
|
||||||
|
|
||||||
require github.com/joho/godotenv v1.5.1
|
require (
|
||||||
|
github.com/joho/godotenv v1.5.1
|
||||||
|
github.com/prometheus/client_golang v1.14.0
|
||||||
|
github.com/sirupsen/logrus v1.6.0
|
||||||
|
)
|
||||||
|
|
||||||
require (
|
require (
|
||||||
github.com/beorn7/perks v1.0.1 // indirect
|
github.com/beorn7/perks v1.0.1 // indirect
|
||||||
github.com/cespare/xxhash/v2 v2.1.2 // indirect
|
github.com/cespare/xxhash/v2 v2.1.2 // indirect
|
||||||
github.com/golang/protobuf v1.5.2 // indirect
|
github.com/golang/protobuf v1.5.2 // indirect
|
||||||
|
github.com/konsorten/go-windows-terminal-sequences v1.0.3 // indirect
|
||||||
github.com/matttproud/golang_protobuf_extensions v1.0.1 // indirect
|
github.com/matttproud/golang_protobuf_extensions v1.0.1 // indirect
|
||||||
github.com/prometheus/client_golang v1.14.0 // indirect
|
|
||||||
github.com/prometheus/client_model v0.3.0 // indirect
|
github.com/prometheus/client_model v0.3.0 // indirect
|
||||||
github.com/prometheus/common v0.37.0 // indirect
|
github.com/prometheus/common v0.37.0 // indirect
|
||||||
github.com/prometheus/procfs v0.8.0 // indirect
|
github.com/prometheus/procfs v0.8.0 // indirect
|
||||||
|
|
7
go.sum
7
go.sum
|
@ -52,6 +52,7 @@ github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMn
|
||||||
github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
|
github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
|
||||||
github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc=
|
github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc=
|
||||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||||
|
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||||
github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
|
github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
|
||||||
github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
|
github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
|
||||||
|
@ -109,6 +110,7 @@ github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/
|
||||||
github.com/google/go-cmp v0.5.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
github.com/google/go-cmp v0.5.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||||
github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||||
github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||||
|
github.com/google/go-cmp v0.5.8 h1:e6P7q2lk1O+qJJb4BtCQXlK8vWEO8V1ZeuEdJNOqZyg=
|
||||||
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
|
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
|
||||||
github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs=
|
github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs=
|
||||||
github.com/google/martian/v3 v3.0.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0=
|
github.com/google/martian/v3 v3.0.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0=
|
||||||
|
@ -138,6 +140,7 @@ github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7V
|
||||||
github.com/julienschmidt/httprouter v1.3.0/go.mod h1:JR6WtHb+2LUe8TCKY3cZOxFyyO8IZAc4RVcycCCAKdM=
|
github.com/julienschmidt/httprouter v1.3.0/go.mod h1:JR6WtHb+2LUe8TCKY3cZOxFyyO8IZAc4RVcycCCAKdM=
|
||||||
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
|
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
|
||||||
github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
|
github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
|
||||||
|
github.com/konsorten/go-windows-terminal-sequences v1.0.3 h1:CE8S1cTafDpPvMhIxNJKvHsGVBgn1xWYf1NbHQhywc8=
|
||||||
github.com/konsorten/go-windows-terminal-sequences v1.0.3/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
|
github.com/konsorten/go-windows-terminal-sequences v1.0.3/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
|
||||||
github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc=
|
github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc=
|
||||||
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
|
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
|
||||||
|
@ -155,6 +158,7 @@ github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f/go.mod h1:qRW
|
||||||
github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||||
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||||
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||||
|
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||||
github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw=
|
github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw=
|
||||||
github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo=
|
github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo=
|
||||||
|
@ -185,11 +189,13 @@ github.com/prometheus/procfs v0.8.0/go.mod h1:z7EfXMXOkbkqb9IINtpCn86r/to3BnA0ua
|
||||||
github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
|
github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
|
||||||
github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo=
|
github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo=
|
||||||
github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE=
|
github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE=
|
||||||
|
github.com/sirupsen/logrus v1.6.0 h1:UBcNElsrwanuuMsnGSlYmtmgbb23qDR5dG+6X6Oo89I=
|
||||||
github.com/sirupsen/logrus v1.6.0/go.mod h1:7uNnSEd1DgxDLC74fIahvMZmmYsHGZGEOFrfsX/uA88=
|
github.com/sirupsen/logrus v1.6.0/go.mod h1:7uNnSEd1DgxDLC74fIahvMZmmYsHGZGEOFrfsX/uA88=
|
||||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||||
github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||||
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
|
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
|
||||||
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
|
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
|
||||||
|
github.com/stretchr/testify v1.4.0 h1:2E4SXV/wtOkTonXsotYi4li6zVWxYlZuYNCXe9XRJyk=
|
||||||
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
|
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
|
||||||
github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
||||||
github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
||||||
|
@ -465,6 +471,7 @@ gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||||
gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||||
gopkg.in/yaml.v2 v2.2.5/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
gopkg.in/yaml.v2 v2.2.5/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||||
gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||||
|
gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=
|
||||||
gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
|
gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
|
||||||
honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
||||||
honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
{
|
{
|
||||||
"name": "immich-exporter",
|
"name": "immich-exporter",
|
||||||
"version": "0.1.2",
|
"version": "1.0.0",
|
||||||
"description": "exporter for immich",
|
"description": "exporter for immich",
|
||||||
"main": "src/main.go",
|
"main": "src/main.go",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
|
|
|
@ -1,60 +0,0 @@
|
||||||
package immich
|
|
||||||
|
|
||||||
import (
|
|
||||||
"encoding/json"
|
|
||||||
"fmt"
|
|
||||||
"immich-exporter/src/models"
|
|
||||||
"io/ioutil"
|
|
||||||
"log"
|
|
||||||
"net/http"
|
|
||||||
"strings"
|
|
||||||
)
|
|
||||||
|
|
||||||
func Auth() {
|
|
||||||
|
|
||||||
url := models.GetURL() + "/api/auth/login"
|
|
||||||
method := "POST"
|
|
||||||
|
|
||||||
payload := strings.NewReader(`{
|
|
||||||
"email": "` + models.GetUsername() + `",
|
|
||||||
"password": "` + models.Getpassword() + `"}`)
|
|
||||||
|
|
||||||
client := &http.Client{}
|
|
||||||
req, err := http.NewRequest(method, url, payload)
|
|
||||||
|
|
||||||
if err != nil {
|
|
||||||
fmt.Println(err)
|
|
||||||
return
|
|
||||||
} else {
|
|
||||||
req.Header.Add("Content-Type", "application/json")
|
|
||||||
req.Header.Add("Accept", "application/json")
|
|
||||||
|
|
||||||
res, err := client.Do(req)
|
|
||||||
if err != nil {
|
|
||||||
log.Println(err)
|
|
||||||
return
|
|
||||||
} else {
|
|
||||||
defer res.Body.Close()
|
|
||||||
|
|
||||||
body, err := ioutil.ReadAll(res.Body)
|
|
||||||
if err != nil {
|
|
||||||
log.Println(err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
if res.StatusCode == 400 {
|
|
||||||
log.Fatalln("Incorrect login")
|
|
||||||
} else {
|
|
||||||
var result models.StructLogin
|
|
||||||
if err := json.Unmarshal(body, &result); err != nil {
|
|
||||||
log.Println("Can not unmarshal JSON")
|
|
||||||
}
|
|
||||||
|
|
||||||
models.SetAccessToken(result.AccessToken)
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
|
@ -3,7 +3,7 @@ package immich
|
||||||
import (
|
import (
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
"immich-exporter/src/models"
|
"immich-exp/src/models"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"log"
|
"log"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
@ -25,9 +25,10 @@ func Allrequests(r *prometheus.Registry) {
|
||||||
|
|
||||||
func Analyze(r *prometheus.Registry) {
|
func Analyze(r *prometheus.Registry) {
|
||||||
defer wg.Done()
|
defer wg.Done()
|
||||||
allusers := make(chan func() (*models.StructAllUsers, error))
|
|
||||||
|
|
||||||
|
allusers := make(chan func() (*models.StructAllUsers, error))
|
||||||
serverinfo := make(chan func() (*models.StructServerInfo, error))
|
serverinfo := make(chan func() (*models.StructServerInfo, error))
|
||||||
|
|
||||||
wg.Add(1)
|
wg.Add(1)
|
||||||
go GetAllUsers(allusers)
|
go GetAllUsers(allusers)
|
||||||
res1, err := (<-allusers)()
|
res1, err := (<-allusers)()
|
||||||
|
@ -47,16 +48,7 @@ func Analyze(r *prometheus.Registry) {
|
||||||
func GetAllUsers(c chan func() (*models.StructAllUsers, error)) {
|
func GetAllUsers(c chan func() (*models.StructAllUsers, error)) {
|
||||||
defer wg.Done()
|
defer wg.Done()
|
||||||
resp, err := Apirequest("/api/user?isAll=true", "GET")
|
resp, err := Apirequest("/api/user?isAll=true", "GET")
|
||||||
if err != nil {
|
if err == nil {
|
||||||
if err.Error() == "403" {
|
|
||||||
log.Println("Cookie changed, try to reconnect ...")
|
|
||||||
Auth()
|
|
||||||
} else {
|
|
||||||
if models.GetPromptError() == false {
|
|
||||||
log.Println("Error : ", err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if models.GetPromptError() == true {
|
if models.GetPromptError() == true {
|
||||||
models.SetPromptError(false)
|
models.SetPromptError(false)
|
||||||
}
|
}
|
||||||
|
@ -71,25 +63,14 @@ func GetAllUsers(c chan func() (*models.StructAllUsers, error)) {
|
||||||
}
|
}
|
||||||
|
|
||||||
c <- (func() (*models.StructAllUsers, error) { return result, nil })
|
c <- (func() (*models.StructAllUsers, error) { return result, nil })
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func ServerVersion(r *prometheus.Registry) {
|
func ServerVersion(r *prometheus.Registry) {
|
||||||
defer wg.Done()
|
defer wg.Done()
|
||||||
resp, err := Apirequest("/api/server-info/version", "GET")
|
resp, err := Apirequest("/api/server-info/version", "GET")
|
||||||
if err != nil {
|
if err == nil {
|
||||||
if err.Error() == "403" {
|
|
||||||
log.Println("Cookie changed, try to reconnect ...")
|
|
||||||
Auth()
|
|
||||||
} else {
|
|
||||||
if models.GetPromptError() == false {
|
|
||||||
log.Println("Error : ", err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if models.GetPromptError() == true {
|
if models.GetPromptError() == true {
|
||||||
models.SetPromptError(false)
|
models.SetPromptError(false)
|
||||||
}
|
}
|
||||||
|
@ -100,14 +81,12 @@ func ServerVersion(r *prometheus.Registry) {
|
||||||
|
|
||||||
var result models.StructServerVersion
|
var result models.StructServerVersion
|
||||||
if err := json.Unmarshal(body, &result); err != nil { // Parse []byte to go struct pointer
|
if err := json.Unmarshal(body, &result); err != nil { // Parse []byte to go struct pointer
|
||||||
log.Println("Can not unmarshal JSON")
|
log.Println("Can not unmarshal JSON for version")
|
||||||
}
|
}
|
||||||
|
|
||||||
SendBackMessageserverVersion(&result, r)
|
SendBackMessageserverVersion(&result, r)
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func ServerInfo(c chan func() (*models.StructServerInfo, error)) {
|
func ServerInfo(c chan func() (*models.StructServerInfo, error)) {
|
||||||
|
@ -116,7 +95,6 @@ func ServerInfo(c chan func() (*models.StructServerInfo, error)) {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if err.Error() == "403" {
|
if err.Error() == "403" {
|
||||||
log.Println("Cookie changed, try to reconnect ...")
|
log.Println("Cookie changed, try to reconnect ...")
|
||||||
Auth()
|
|
||||||
} else {
|
} else {
|
||||||
if models.GetPromptError() == false {
|
if models.GetPromptError() == false {
|
||||||
log.Println("Error : ", err)
|
log.Println("Error : ", err)
|
||||||
|
@ -134,23 +112,22 @@ func ServerInfo(c chan func() (*models.StructServerInfo, error)) {
|
||||||
|
|
||||||
result := new(models.StructServerInfo)
|
result := new(models.StructServerInfo)
|
||||||
if err := json.Unmarshal(body, &result); err != nil { // Parse []byte to go struct pointer
|
if err := json.Unmarshal(body, &result); err != nil { // Parse []byte to go struct pointer
|
||||||
log.Println("Can not unmarshal JSON")
|
log.Println("Can not unmarshal JSON for server infos")
|
||||||
}
|
}
|
||||||
c <- (func() (*models.StructServerInfo, error) { return result, nil })
|
c <- (func() (*models.StructServerInfo, error) { return result, nil })
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func Apirequest(uri string, method string) (*http.Response, error) {
|
func Apirequest(uri string, method string) (*http.Response, error) {
|
||||||
|
|
||||||
req, err := http.NewRequest(method, models.GetURL()+uri, nil)
|
req, err := http.NewRequest(method, models.Getbaseurl()+uri, nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatalln("Error with url")
|
log.Fatalln("Error with url")
|
||||||
}
|
}
|
||||||
|
req.Header.Add("Accept", "application/json")
|
||||||
req.AddCookie(&http.Cookie{Name: "immich_access_token", Value: models.GetAccessToken()})
|
req.Header.Add("x-api-key", models.GetApiKey())
|
||||||
client := &http.Client{}
|
client := &http.Client{}
|
||||||
resp, err := client.Do(req)
|
resp, err := client.Do(req)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -164,23 +141,16 @@ func Apirequest(uri string, method string) (*http.Response, error) {
|
||||||
return resp, err
|
return resp, err
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
models.SetPromptError(false)
|
|
||||||
if resp.StatusCode == 200 {
|
if resp.StatusCode == 200 {
|
||||||
|
models.SetPromptError(false)
|
||||||
return resp, nil
|
return resp, nil
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
err := fmt.Errorf("%d", resp.StatusCode)
|
err := fmt.Errorf("%d", resp.StatusCode)
|
||||||
if models.GetPromptError() == false {
|
if models.GetPromptError() == false {
|
||||||
models.SetPromptError(true)
|
models.SetPromptError(true)
|
||||||
|
log.Println("Error code", err.Error(), " for ", models.Getbaseurl()+uri)
|
||||||
log.Println("Error code", err.Error())
|
|
||||||
|
|
||||||
}
|
}
|
||||||
return resp, err
|
return resp, err
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
package immich
|
package immich
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"immich-exporter/src/models"
|
"immich-exp/src/models"
|
||||||
"strconv"
|
"strconv"
|
||||||
|
|
||||||
"github.com/prometheus/client_golang/prometheus"
|
"github.com/prometheus/client_golang/prometheus"
|
||||||
|
@ -52,14 +52,14 @@ func SendBackMessagePreference(result *models.StructServerInfo, result2 *models.
|
||||||
r.MustRegister(user_photos)
|
r.MustRegister(user_photos)
|
||||||
total_photos.Add(float64((*result).Photos))
|
total_photos.Add(float64((*result).Photos))
|
||||||
total_videos.Add(float64((*result).Videos))
|
total_videos.Add(float64((*result).Videos))
|
||||||
total_usage.Add(float64((*result).UsageRaw))
|
total_usage.Add(float64((*result).Usage))
|
||||||
total_users.Add(float64(len((*result).UsageByUser)))
|
total_users.Add(float64(len((*result).UsageByUser)))
|
||||||
|
|
||||||
for i := 0; i < len((*result).UsageByUser); i++ {
|
for i := 0; i < len((*result).UsageByUser); i++ {
|
||||||
var myuser = GetName((*result).UsageByUser[i].UserID, result2)
|
var myuser = GetName((*result).UsageByUser[i].UserID, result2)
|
||||||
user_info.With(prometheus.Labels{"videos": strconv.Itoa((*result).UsageByUser[i].Videos), "photos": strconv.Itoa((*result).UsageByUser[i].Photos), "uid": (*result).UsageByUser[i].UserID, "usage": strconv.Itoa(int((*result).UsageByUser[i].UsageRaw)), "firstname": myuser.FirstName, "lastname": myuser.LastName}).Inc()
|
user_info.With(prometheus.Labels{"videos": strconv.Itoa((*result).UsageByUser[i].Videos), "photos": strconv.Itoa((*result).UsageByUser[i].Photos), "uid": (*result).UsageByUser[i].UserID, "usage": strconv.Itoa(int((*result).UsageByUser[i].Usage)), "firstname": myuser.FirstName, "lastname": myuser.LastName}).Inc()
|
||||||
user_photos.With(prometheus.Labels{"uid": (*result).UsageByUser[i].UserID, "firstname": myuser.FirstName, "lastname": myuser.LastName}).Set(float64((*result).UsageByUser[i].Photos))
|
user_photos.With(prometheus.Labels{"uid": (*result).UsageByUser[i].UserID, "firstname": myuser.FirstName, "lastname": myuser.LastName}).Set(float64((*result).UsageByUser[i].Photos))
|
||||||
user_usage.With(prometheus.Labels{"uid": (*result).UsageByUser[i].UserID, "firstname": myuser.FirstName, "lastname": myuser.LastName}).Set(float64((*result).UsageByUser[i].UsageRaw))
|
user_usage.With(prometheus.Labels{"uid": (*result).UsageByUser[i].UserID, "firstname": myuser.FirstName, "lastname": myuser.LastName}).Set(float64((*result).UsageByUser[i].Usage))
|
||||||
user_videos.With(prometheus.Labels{"uid": (*result).UsageByUser[i].UserID, "firstname": myuser.FirstName, "lastname": myuser.LastName}).Set(float64((*result).UsageByUser[i].Videos))
|
user_videos.With(prometheus.Labels{"uid": (*result).UsageByUser[i].UserID, "firstname": myuser.FirstName, "lastname": myuser.LastName}).Set(float64((*result).UsageByUser[i].Videos))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
158
src/init.go
158
src/init.go
|
@ -3,31 +3,39 @@ package main
|
||||||
import (
|
import (
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"flag"
|
"flag"
|
||||||
"immich-exporter/src/immich"
|
"fmt"
|
||||||
"immich-exporter/src/models"
|
"immich-exp/src/immich"
|
||||||
"io/ioutil"
|
"immich-exp/src/models"
|
||||||
"net/http"
|
|
||||||
|
"net/http"
|
||||||
|
"strconv"
|
||||||
|
"strings"
|
||||||
|
|
||||||
"log"
|
|
||||||
"os"
|
"os"
|
||||||
|
|
||||||
"github.com/joho/godotenv"
|
"github.com/joho/godotenv"
|
||||||
"github.com/prometheus/client_golang/prometheus"
|
"github.com/prometheus/client_golang/prometheus"
|
||||||
"github.com/prometheus/client_golang/prometheus/promhttp"
|
"github.com/prometheus/client_golang/prometheus/promhttp"
|
||||||
|
log "github.com/sirupsen/logrus"
|
||||||
)
|
)
|
||||||
|
|
||||||
func main() {
|
const DEFAULTPORT = 8090
|
||||||
startup()
|
|
||||||
log.Println("Immich URL :", models.GetURL())
|
|
||||||
log.Println("username :", models.GetUsername())
|
|
||||||
log.Println("password :", models.Getpasswordmasked())
|
|
||||||
log.Println("Started")
|
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
loadenv()
|
||||||
|
projectinfo()
|
||||||
|
log.Info("Immich URL: ", models.Getbaseurl())
|
||||||
|
log.Info("Started")
|
||||||
http.HandleFunc("/metrics", metrics)
|
http.HandleFunc("/metrics", metrics)
|
||||||
http.ListenAndServe(":8090", nil)
|
addr := ":" + strconv.Itoa(models.GetPort())
|
||||||
|
if models.GetPort() != DEFAULTPORT {
|
||||||
|
log.Info("Listening on port", models.GetPort())
|
||||||
|
}
|
||||||
|
http.ListenAndServe(addr, nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
func metrics(w http.ResponseWriter, r *http.Request) {
|
func metrics(w http.ResponseWriter, r *http.Request) {
|
||||||
|
log.Trace("New request")
|
||||||
registry := prometheus.NewRegistry()
|
registry := prometheus.NewRegistry()
|
||||||
immich.Allrequests(registry)
|
immich.Allrequests(registry)
|
||||||
h := promhttp.HandlerFor(registry, promhttp.HandlerOpts{})
|
h := promhttp.HandlerFor(registry, promhttp.HandlerOpts{})
|
||||||
|
@ -35,80 +43,86 @@ func metrics(w http.ResponseWriter, r *http.Request) {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func startup() {
|
|
||||||
projectinfo()
|
|
||||||
var envfile bool
|
|
||||||
|
|
||||||
flag.BoolVar(&envfile, "e", false, "Use .env file")
|
|
||||||
flag.Parse()
|
|
||||||
if envfile {
|
|
||||||
useenvfile()
|
|
||||||
} else {
|
|
||||||
initenv()
|
|
||||||
}
|
|
||||||
|
|
||||||
immich.Auth()
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
func projectinfo() {
|
func projectinfo() {
|
||||||
fileContent, err := os.Open("./package.json")
|
fileContent, err := os.ReadFile("./package.json")
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatal(err)
|
log.Fatal(err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
defer fileContent.Close()
|
|
||||||
|
|
||||||
byteResult, _ := ioutil.ReadAll(fileContent)
|
|
||||||
|
|
||||||
var res map[string]interface{}
|
var res map[string]interface{}
|
||||||
json.Unmarshal([]byte(byteResult), &res)
|
err = json.Unmarshal(fileContent, &res)
|
||||||
log.Println("Author :", res["author"])
|
if err != nil {
|
||||||
log.Println(res["name"], "version", res["version"])
|
log.Fatal(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
fmt.Print(res["name"], " (version ", res["version"], ")\n")
|
||||||
|
fmt.Print("Author: ", res["author"], "\n")
|
||||||
|
fmt.Print("Using log level: ", log.GetLevel(), "\n")
|
||||||
}
|
}
|
||||||
|
|
||||||
func useenvfile() {
|
func loadenv() {
|
||||||
myEnv, err := godotenv.Read()
|
var envfile bool
|
||||||
|
flag.BoolVar(&envfile, "e", false, "Use .env file")
|
||||||
|
flag.Parse()
|
||||||
|
_, err := os.Stat(".env")
|
||||||
|
if !os.IsNotExist(err) && !envfile {
|
||||||
|
err := godotenv.Load(".env")
|
||||||
|
if err != nil {
|
||||||
|
log.Panic("Error loading .env file:", err)
|
||||||
|
}
|
||||||
|
// fmt.Println("Using .env file")
|
||||||
|
}
|
||||||
|
|
||||||
username := myEnv["IMMICH_USERNAME"]
|
immichapikey := getEnv("IMMICH_API_KEY", "", false, "Immich API Key is not set", true)
|
||||||
password := myEnv["IMMICH_PASSWORD"]
|
immichURL := getEnv("IMMICH_BASE_URL", "http://localhost:8080", true, "Qbittorrent base_url is not set. Using default base_url", false)
|
||||||
immich_url := myEnv["IMMICH_BASE_URL"]
|
exporterPort := getEnv("EXPORTER_PORT", strconv.Itoa(DEFAULTPORT), false, "", false)
|
||||||
if myEnv["IMMICH_USERNAME"] == "" {
|
|
||||||
log.Panic("Immich username is not set.")
|
num, err := strconv.Atoi(exporterPort)
|
||||||
}
|
|
||||||
if myEnv["IMMICH_PASSWORD"] == "" {
|
|
||||||
log.Panic("Immich password is not set.")
|
|
||||||
}
|
|
||||||
if myEnv["IMMICH_BASE_URL"] == "" {
|
|
||||||
log.Panic("IMMICH base_url is not set.")
|
|
||||||
}
|
|
||||||
models.Setuser(username, password, immich_url)
|
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatal("Error loading .env file")
|
log.Panic("EXPORTER_PORT must be an integer")
|
||||||
}
|
}
|
||||||
log.Println("Using .env file")
|
if num < 0 || num > 65353 {
|
||||||
|
log.Panic("EXPORTER_PORT must be > 0 and < 65353")
|
||||||
|
}
|
||||||
|
|
||||||
|
setLogLevel(getEnv("LOG_LEVEL", "INFO", false, "", false))
|
||||||
|
models.SetApp(num, false)
|
||||||
|
models.Setuser(immichURL, immichapikey)
|
||||||
|
}
|
||||||
|
func setLogLevel(logLevel string) {
|
||||||
|
logLevels := map[string]log.Level{
|
||||||
|
"TRACE": log.TraceLevel,
|
||||||
|
"DEBUG": log.DebugLevel,
|
||||||
|
"INFO": log.InfoLevel,
|
||||||
|
"WARN": log.WarnLevel,
|
||||||
|
"ERROR": log.ErrorLevel,
|
||||||
|
}
|
||||||
|
|
||||||
|
level, found := logLevels[strings.ToUpper(logLevel)]
|
||||||
|
if !found {
|
||||||
|
level = log.InfoLevel
|
||||||
|
}
|
||||||
|
|
||||||
|
log.SetLevel(level)
|
||||||
|
log.SetFormatter(&log.TextFormatter{
|
||||||
|
DisableColors: false,
|
||||||
|
FullTimestamp: true,
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
func initenv() {
|
func getEnv(key string, fallback string, printLog bool, logPrinted string, needed bool) string {
|
||||||
|
value, ok := os.LookupEnv(key)
|
||||||
username := os.Getenv("IMMICH_USERNAME")
|
if !ok || value == "" {
|
||||||
password := os.Getenv("IMMICH_PASSWORD")
|
if needed {
|
||||||
immich_url := os.Getenv("IMMICH_BASE_URL")
|
log.Panicln("Please set a value for", key)
|
||||||
if os.Getenv("IMMICH_USERNAME") == "" {
|
}
|
||||||
log.Panic("Immich username is not set.")
|
if printLog {
|
||||||
|
log.Warn(logPrinted)
|
||||||
|
}
|
||||||
|
return fallback
|
||||||
}
|
}
|
||||||
if os.Getenv("IMMICH_PASSWORD") == "" {
|
return value
|
||||||
log.Panic("Immich password is not set.")
|
|
||||||
|
|
||||||
}
|
|
||||||
if os.Getenv("IMMICH_BASE_URL") == "" {
|
|
||||||
log.Panic("Immich base_url is not set.")
|
|
||||||
|
|
||||||
}
|
|
||||||
models.Setuser(username, password, immich_url)
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
64
src/models/api.go
Normal file
64
src/models/api.go
Normal file
|
@ -0,0 +1,64 @@
|
||||||
|
package models
|
||||||
|
|
||||||
|
import "time"
|
||||||
|
|
||||||
|
type StructLogin struct {
|
||||||
|
AccessToken string `json:"accessToken"`
|
||||||
|
UserID string `json:"userId"`
|
||||||
|
UserEmail string `json:"userEmail"`
|
||||||
|
FirstName string `json:"firstName"`
|
||||||
|
LastName string `json:"lastName"`
|
||||||
|
IsAdmin bool `json:"isAdmin"`
|
||||||
|
ShouldChangePassword bool `json:"shouldChangePassword"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type StructServerInfo struct {
|
||||||
|
Photos int `json:"photos"`
|
||||||
|
Videos int `json:"videos"`
|
||||||
|
Usage int64 `json:"usage"`
|
||||||
|
UsageByUser []struct {
|
||||||
|
UserID string `json:"userId"`
|
||||||
|
UserFirstName string `json:"userFirstName"`
|
||||||
|
UserLastName string `json:"userLastName"`
|
||||||
|
Photos int `json:"photos"`
|
||||||
|
Videos int `json:"videos"`
|
||||||
|
Usage int `json:"usage"`
|
||||||
|
} `json:"usageByUser"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type StructDiskInfo struct {
|
||||||
|
DiskAvailable string `json:"diskAvailable"`
|
||||||
|
DiskSize string `json:"diskSize"`
|
||||||
|
DiskUse string `json:"diskUse"`
|
||||||
|
DiskAvailableRaw int64 `json:"diskAvailableRaw"`
|
||||||
|
DiskSizeRaw int64 `json:"diskSizeRaw"`
|
||||||
|
DiskUseRaw int64 `json:"diskUseRaw"`
|
||||||
|
DiskUsagePercentage float64 `json:"diskUsagePercentage"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type StructServerVersion struct {
|
||||||
|
Major int `json:"major"`
|
||||||
|
Minor int `json:"minor"`
|
||||||
|
Patch int `json:"patch"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type StructAllUsers []struct {
|
||||||
|
ID string `json:"id"`
|
||||||
|
Email string `json:"email"`
|
||||||
|
FirstName string `json:"firstName"`
|
||||||
|
LastName string `json:"lastName"`
|
||||||
|
CreatedAt time.Time `json:"createdAt"`
|
||||||
|
ProfileImagePath string `json:"profileImagePath"`
|
||||||
|
ShouldChangePassword bool `json:"shouldChangePassword"`
|
||||||
|
IsAdmin bool `json:"isAdmin"`
|
||||||
|
DeletedAt time.Time `json:"deletedAt"`
|
||||||
|
OauthID string `json:"oauthId"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type StructCustomUser struct {
|
||||||
|
Email string
|
||||||
|
ID string
|
||||||
|
FirstName string
|
||||||
|
LastName string
|
||||||
|
IsAdmin bool
|
||||||
|
}
|
27
src/models/app.go
Normal file
27
src/models/app.go
Normal file
|
@ -0,0 +1,27 @@
|
||||||
|
package models
|
||||||
|
|
||||||
|
type TypeAppConfig struct {
|
||||||
|
Port int
|
||||||
|
Error bool
|
||||||
|
}
|
||||||
|
|
||||||
|
var AppConfig TypeAppConfig
|
||||||
|
|
||||||
|
func SetApp(setport int, seterror bool) {
|
||||||
|
AppConfig = TypeAppConfig{
|
||||||
|
Port: setport,
|
||||||
|
Error: seterror,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func GetPort() int {
|
||||||
|
return AppConfig.Port
|
||||||
|
}
|
||||||
|
|
||||||
|
func SetPromptError(prompt bool) {
|
||||||
|
AppConfig.Error = prompt
|
||||||
|
}
|
||||||
|
|
||||||
|
func GetPromptError() bool {
|
||||||
|
return AppConfig.Error
|
||||||
|
}
|
|
@ -1,11 +0,0 @@
|
||||||
package models
|
|
||||||
|
|
||||||
var myerr bool
|
|
||||||
|
|
||||||
func SetPromptError(prompt bool) {
|
|
||||||
myerr = prompt
|
|
||||||
}
|
|
||||||
|
|
||||||
func GetPromptError() bool {
|
|
||||||
return myerr
|
|
||||||
}
|
|
|
@ -1,64 +1,22 @@
|
||||||
package models
|
package models
|
||||||
|
|
||||||
import "time"
|
type StructImmich struct {
|
||||||
|
APIKey string
|
||||||
type StructLogin struct {
|
URL string
|
||||||
AccessToken string `json:"accessToken"`
|
|
||||||
UserID string `json:"userId"`
|
|
||||||
UserEmail string `json:"userEmail"`
|
|
||||||
FirstName string `json:"firstName"`
|
|
||||||
LastName string `json:"lastName"`
|
|
||||||
IsAdmin bool `json:"isAdmin"`
|
|
||||||
ShouldChangePassword bool `json:"shouldChangePassword"`
|
|
||||||
}
|
}
|
||||||
|
|
||||||
type StructServerInfo struct {
|
var myuser StructImmich
|
||||||
Photos int `json:"photos"`
|
|
||||||
Videos int `json:"videos"`
|
func Setuser(url string, apikey string) {
|
||||||
UsageByUser []struct {
|
myuser.URL = url
|
||||||
UserID string `json:"userId"`
|
myuser.APIKey = apikey
|
||||||
Videos int `json:"videos"`
|
|
||||||
Photos int `json:"photos"`
|
|
||||||
UsageRaw int64 `json:"usageRaw"`
|
|
||||||
Usage string `json:"usage"`
|
|
||||||
} `json:"usageByUser"`
|
|
||||||
UsageRaw int64 `json:"usageRaw"`
|
|
||||||
Usage string `json:"usage"`
|
|
||||||
}
|
}
|
||||||
|
|
||||||
type StructDiskInfo struct {
|
func Getbaseurl() string {
|
||||||
DiskAvailable string `json:"diskAvailable"`
|
return myuser.URL
|
||||||
DiskSize string `json:"diskSize"`
|
|
||||||
DiskUse string `json:"diskUse"`
|
|
||||||
DiskAvailableRaw int64 `json:"diskAvailableRaw"`
|
|
||||||
DiskSizeRaw int64 `json:"diskSizeRaw"`
|
|
||||||
DiskUseRaw int64 `json:"diskUseRaw"`
|
|
||||||
DiskUsagePercentage float64 `json:"diskUsagePercentage"`
|
|
||||||
}
|
}
|
||||||
|
|
||||||
type StructServerVersion struct {
|
func GetApiKey() string {
|
||||||
Major int `json:"major"`
|
return myuser.APIKey
|
||||||
Minor int `json:"minor"`
|
|
||||||
Patch int `json:"patch"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type StructAllUsers []struct {
|
|
||||||
ID string `json:"id"`
|
|
||||||
Email string `json:"email"`
|
|
||||||
FirstName string `json:"firstName"`
|
|
||||||
LastName string `json:"lastName"`
|
|
||||||
CreatedAt time.Time `json:"createdAt"`
|
|
||||||
ProfileImagePath string `json:"profileImagePath"`
|
|
||||||
ShouldChangePassword bool `json:"shouldChangePassword"`
|
|
||||||
IsAdmin bool `json:"isAdmin"`
|
|
||||||
DeletedAt time.Time `json:"deletedAt"`
|
|
||||||
OauthID string `json:"oauthId"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type StructCustomUser struct {
|
|
||||||
Email string
|
|
||||||
ID string
|
|
||||||
FirstName string
|
|
||||||
LastName string
|
|
||||||
IsAdmin bool
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,47 +0,0 @@
|
||||||
package models
|
|
||||||
|
|
||||||
type StructImmich struct {
|
|
||||||
Username string
|
|
||||||
Password string
|
|
||||||
URL string
|
|
||||||
AccessToken string
|
|
||||||
}
|
|
||||||
|
|
||||||
var myuser StructImmich
|
|
||||||
|
|
||||||
func Getuser() (string, string) {
|
|
||||||
return myuser.Username, myuser.Password
|
|
||||||
}
|
|
||||||
|
|
||||||
func Setuser(username string, password string, url string) {
|
|
||||||
myuser.Username = username
|
|
||||||
myuser.Password = password
|
|
||||||
myuser.URL = url
|
|
||||||
}
|
|
||||||
|
|
||||||
func GetUsername() string {
|
|
||||||
return myuser.Username
|
|
||||||
}
|
|
||||||
|
|
||||||
func Getpassword() string {
|
|
||||||
return myuser.Password
|
|
||||||
}
|
|
||||||
func Getpasswordmasked() string {
|
|
||||||
hide := ""
|
|
||||||
for i := 0; i < len(myuser.Password); i++ {
|
|
||||||
hide += "*"
|
|
||||||
}
|
|
||||||
return hide
|
|
||||||
}
|
|
||||||
|
|
||||||
func SetAccessToken(accessToken string) {
|
|
||||||
myuser.AccessToken = accessToken
|
|
||||||
}
|
|
||||||
|
|
||||||
func GetAccessToken() string {
|
|
||||||
return myuser.AccessToken
|
|
||||||
}
|
|
||||||
|
|
||||||
func GetURL() string {
|
|
||||||
return myuser.URL
|
|
||||||
}
|
|
Loading…
Reference in a new issue