assert a vod CUID when updated
ci / build (push) Has been cancelled Details

This commit is contained in:
CJ_Clippy 2024-07-06 00:49:51 -08:00
parent 3a89a076d9
commit a60d0f0821
40 changed files with 729 additions and 773 deletions

View File

@ -10,7 +10,7 @@ Tested on VKE v1.30.0+1 (PVCs on other versions may not be fulfilled)
direnv for loading .envrc
Temporal for work queue
Temporal for work queue, cron
Postgres for data storage

View File

@ -23,7 +23,7 @@ velero:
tilt:
kind get kubeconfig > ~/.kube/kind.yaml
KUBECONFIG=~/.kube/kind.yaml tilt up -f ./t.wip.tiltfile
KUBECONFIG=~/.kube/kind.yaml tilt up -f ./Tiltfile
exoscale:
kubectl apply -f https://raw.githubusercontent.com/exoscale/cert-manager-webhook-exoscale/master/deploy/exoscale-webhook-kustomize/deploy.yaml

View File

@ -4,6 +4,15 @@ Source Code for https://futureporn.net
See ./ARCHITECTURE.md for overview
## Metrics Notes
Keeping track of metrics we want to scrape using Prometheus
### Uppy
https://uppy.fp.sbtp.xyz/metrics
## Development Mantras
### Move fast and break things
@ -16,11 +25,14 @@ See ./ARCHITECTURE.md for overview
### If the way is long, the way is wrong
### Good, Fast, Cheap. Pick only two.
### Good, Fast, Cheap. Pick two but not all three.
### Organizations are fractals
### Focus on what moves the needle
### Alligator energy
### Alligator energy (move slow and preserve things)
### Code is run more than it is read
### The computer doesn't care

View File

@ -110,6 +110,7 @@ helm_remote(
# values=['./charts/nitter/values.yaml'],
# ))
k8s_yaml(helm(
'./charts/fp',
values=['./charts/fp/values-dev.yaml'],
@ -141,7 +142,6 @@ k8s_yaml(helm(
# )
# docker_build('fp/link2cid', './packages/link2cid')
docker_build(
'fp/strapi',
@ -153,6 +153,17 @@ docker_build(
]
)
# docker_build(
# 'fp/bot',
# '.',
# only=['./packages/bot'],
# dockerfile='./d.bot.dockerfile',
# live_update=[
# sync('./packages/bot', '/app')
# ]
# )
@ -201,7 +212,7 @@ cmd_button('temporal-web:namespace',
docker_build(
'fp/next',
'.',
only=['./pnpm-lock.yaml', './package.json', './packages/next'],
only=['./pnpm-lock.yaml', './package.json', './packages/next', './ca/letsencrypt-stg-root-x1.pem'],
dockerfile='d.next.dockerfile',
target='dev',
build_args={
@ -216,9 +227,9 @@ docker_build(
docker_build(
'fp/scout-manager',
'.',
only=['./pnpm-lock.yaml', './package.json', './packages/scout', './packages/next'],
dockerfile='d.scout.dockerfile',
target='manager',
only=['./pnpm-lock.yaml', './package.json', './packages/scout', './packages/next', './ca/letsencrypt-stg-root-x1.pem'],
dockerfile='d.packages.dockerfile',
target='scout-manager',
live_update=[
sync('./packages/scout', '/app'),
run('cd /app && pnpm i', trigger=['./packages/scout/package.json', './packages/scout/pnpm-lock.yaml']),
@ -230,10 +241,10 @@ docker_build(
docker_build(
'fp/scout-worker',
'.',
only=['./pnpm-lock.yaml', './package.json', './packages/scout', './packages/next'],
only=['./pnpm-lock.yaml', './package.json', './packages/scout', './packages/next', './ca/letsencrypt-stg-root-x1.pem'],
# ignore=['./packages/next'], # I wish I could use this ignore to ignore file changes in this dir, but that's not how it works
dockerfile='d.scout.dockerfile',
target='worker',
dockerfile='d.packages.dockerfile',
target='scout:worker',
live_update=[
# idk if this run() is effective
# run('cd /app && pnpm i', trigger=['./packages/scout/package.json', './packages/scout/pnpm-lock.yaml']),
@ -259,16 +270,24 @@ docker_build(
# workload='frp-operator-controller-manager',
# labels='tunnel'
# )
# k8s_resource(
# workload='echo',
# links=[
# link('https://echo.fp.sbtp.xyz'),
# link('http://echo.futureporn.svc.cluster.local:8001')
# ],
# labels='debug'
# )
k8s_resource(
workload='echo',
workload='uppy',
links=[
link('https://echo.fp.sbtp.xyz'),
link('http://echo.futureporn.svc.cluster.local:8001')
link('https://uppy.fp.sbtp.xyz'),
],
labels='frontend'
resource_deps=['redis-master'],
labels=['backend'],
)
k8s_resource(
workload='next',
port_forwards=['3000'],
@ -282,7 +301,7 @@ k8s_resource(
workload='strapi',
port_forwards=['1339'],
links=[
link('http://localhost:1339/admin'),
link('https://strapi.fp.sbtp.xyz/admin'),
link('https://strapi.fp.sbtp.xyz'),
],
resource_deps=['postgres'],
@ -307,13 +326,13 @@ k8s_resource(
k8s_resource(
workload='scout-worker',
resource_deps=['postgres', 'strapi', 'temporal-frontend', 'scout-manager'],
resource_deps=['postgres', 'strapi', 'temporal-frontend'],
labels=['backend'],
)
k8s_resource(
workload='scout-manager',
resource_deps=['postgres', 'strapi', 'temporal-frontend'],
resource_deps=['postgres', 'strapi', 'temporal-frontend', 'scout-worker'],
labels=['backend'],
)
@ -347,6 +366,20 @@ k8s_resource(
# ]
# )
helm_remote(
'redis',
repo_name='redis',
repo_url='https://charts.bitnami.com/bitnami',
namespace='futureporn',
version='19.6.1',
set=[
'auth.existingSecret=redis',
'auth.existingSecretPasswordKey=password',
'replica.persistence.enabled=false',
'architecture=standalone'
]
)
helm_remote(
'temporal',
repo_name='temporal',
@ -445,6 +478,18 @@ k8s_resource(
workload='cert-manager-webhook-exoscale',
labels=['networking'],
)
k8s_resource(
workload='redis-master',
labels=['backend']
)
# k8s_resource(
# workload='bot',
# labels=['backend']
# )
# k8s_resource(
# workload='cert-manager',
# labels='cert-manager'

View File

@ -0,0 +1,32 @@
-----BEGIN CERTIFICATE-----
MIIFmDCCA4CgAwIBAgIQU9C87nMpOIFKYpfvOHFHFDANBgkqhkiG9w0BAQsFADBm
MQswCQYDVQQGEwJVUzEzMDEGA1UEChMqKFNUQUdJTkcpIEludGVybmV0IFNlY3Vy
aXR5IFJlc2VhcmNoIEdyb3VwMSIwIAYDVQQDExkoU1RBR0lORykgUHJldGVuZCBQ
ZWFyIFgxMB4XDTE1MDYwNDExMDQzOFoXDTM1MDYwNDExMDQzOFowZjELMAkGA1UE
BhMCVVMxMzAxBgNVBAoTKihTVEFHSU5HKSBJbnRlcm5ldCBTZWN1cml0eSBSZXNl
YXJjaCBHcm91cDEiMCAGA1UEAxMZKFNUQUdJTkcpIFByZXRlbmQgUGVhciBYMTCC
AiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBALbagEdDTa1QgGBWSYkyMhsc
ZXENOBaVRTMX1hceJENgsL0Ma49D3MilI4KS38mtkmdF6cPWnL++fgehT0FbRHZg
jOEr8UAN4jH6omjrbTD++VZneTsMVaGamQmDdFl5g1gYaigkkmx8OiCO68a4QXg4
wSyn6iDipKP8utsE+x1E28SA75HOYqpdrk4HGxuULvlr03wZGTIf/oRt2/c+dYmD
oaJhge+GOrLAEQByO7+8+vzOwpNAPEx6LW+crEEZ7eBXih6VP19sTGy3yfqK5tPt
TdXXCOQMKAp+gCj/VByhmIr+0iNDC540gtvV303WpcbwnkkLYC0Ft2cYUyHtkstO
fRcRO+K2cZozoSwVPyB8/J9RpcRK3jgnX9lujfwA/pAbP0J2UPQFxmWFRQnFjaq6
rkqbNEBgLy+kFL1NEsRbvFbKrRi5bYy2lNms2NJPZvdNQbT/2dBZKmJqxHkxCuOQ
FjhJQNeO+Njm1Z1iATS/3rts2yZlqXKsxQUzN6vNbD8KnXRMEeOXUYvbV4lqfCf8
mS14WEbSiMy87GB5S9ucSV1XUrlTG5UGcMSZOBcEUpisRPEmQWUOTWIoDQ5FOia/
GI+Ki523r2ruEmbmG37EBSBXdxIdndqrjy+QVAmCebyDx9eVEGOIpn26bW5LKeru
mJxa/CFBaKi4bRvmdJRLAgMBAAGjQjBAMA4GA1UdDwEB/wQEAwIBBjAPBgNVHRMB
Af8EBTADAQH/MB0GA1UdDgQWBBS182Xy/rAKkh/7PH3zRKCsYyXDFDANBgkqhkiG
9w0BAQsFAAOCAgEAncDZNytDbrrVe68UT6py1lfF2h6Tm2p8ro42i87WWyP2LK8Y
nLHC0hvNfWeWmjZQYBQfGC5c7aQRezak+tHLdmrNKHkn5kn+9E9LCjCaEsyIIn2j
qdHlAkepu/C3KnNtVx5tW07e5bvIjJScwkCDbP3akWQixPpRFAsnP+ULx7k0aO1x
qAeaAhQ2rgo1F58hcflgqKTXnpPM02intVfiVVkX5GXpJjK5EoQtLceyGOrkxlM/
sTPq4UrnypmsqSagWV3HcUlYtDinc+nukFk6eR4XkzXBbwKajl0YjztfrCIHOn5Q
CJL6TERVDbM/aAPly8kJ1sWGLuvvWYzMYgLzDul//rUF10gEMWaXVZV51KpS9DY/
5CunuvCXmEQJHo7kGcViT7sETn6Jz9KOhvYcXkJ7po6d93A/jy4GKPIPnsKKNEmR
xUuXY4xRdh45tMJnLTUDdC9FIU0flTeO9/vNpVA8OPU1i14vCz+MU8KX1bV3GXm/
fxlB7VBBjX9v5oUep0o/j68R/iDlCOM4VVfRa8gX6T2FU7fNdatvGro7uQzIvWof
gN9WUwCbEMBy/YhBSrXycKA8crgGg3x1mIsopn88JKwmMBa68oS7EHM9w7C4y71M
7DiA+/9Qdp9RBWJpTS9i/mDnJg1xvo8Xz49mrrgfmcAXTCJqXi24NatI3Oc=
-----END CERTIFICATE-----

View File

@ -0,0 +1,15 @@
-----BEGIN CERTIFICATE-----
MIICTjCCAdSgAwIBAgIRAIPgc3k5LlLVLtUUvs4K/QcwCgYIKoZIzj0EAwMwaDEL
MAkGA1UEBhMCVVMxMzAxBgNVBAoTKihTVEFHSU5HKSBJbnRlcm5ldCBTZWN1cml0
eSBSZXNlYXJjaCBHcm91cDEkMCIGA1UEAxMbKFNUQUdJTkcpIEJvZ3VzIEJyb2Nj
b2xpIFgyMB4XDTIwMDkwNDAwMDAwMFoXDTQwMDkxNzE2MDAwMFowaDELMAkGA1UE
BhMCVVMxMzAxBgNVBAoTKihTVEFHSU5HKSBJbnRlcm5ldCBTZWN1cml0eSBSZXNl
YXJjaCBHcm91cDEkMCIGA1UEAxMbKFNUQUdJTkcpIEJvZ3VzIEJyb2Njb2xpIFgy
MHYwEAYHKoZIzj0CAQYFK4EEACIDYgAEOvS+w1kCzAxYOJbA06Aw0HFP2tLBLKPo
FQqR9AMskl1nC2975eQqycR+ACvYelA8rfwFXObMHYXJ23XLB+dAjPJVOJ2OcsjT
VqO4dcDWu+rQ2VILdnJRYypnV1MMThVxo0IwQDAOBgNVHQ8BAf8EBAMCAQYwDwYD
VR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQU3tGjWWQOwZo2o0busBB2766XlWYwCgYI
KoZIzj0EAwMDaAAwZQIwRcp4ZKBsq9XkUuN8wfX+GEbY1N5nmCRc8e80kUkuAefo
uc2j3cICeXo1cOybQ1iWAjEA3Ooawl8eQyR4wrjCofUE8h44p0j7Yl/kBlJZT8+9
vbtH7QiVzeKCOTQPINyRql6P
-----END CERTIFICATE-----

View File

@ -1,138 +0,0 @@
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: echo
namespace: futureporn
spec:
selector:
matchLabels:
app: echo
template:
metadata:
labels:
app: echo
spec:
containers:
- image: hashicorp/http-echo
name: echo
ports:
- containerPort: 5678
args:
- -text="Hello, choom!"
{{ if eq .Values.environment "development" }}
---
apiVersion: chisel-operator.io/v1
kind: ExitNode
metadata:
name: echo-exit-node
namespace: futureporn
spec:
host: "{{ .Values.chisel.exitNodeIp }}"
port: 9090
auth: chisel
{{ end }}
# ---
# apiVersion: traefik.io/v1alpha1
# kind: IngressRoute
# metadata:
# name: echo
# namespace: futureporn
# spec:
# entryPoints:
# - web
# routes:
# - match: Host(`echo.fp.sbtp.xyz`) || PathPrefix(`/extra/echo`)
# kind: Rule
# services:
# - name: echo
# port: 8001
# # tls:
# # secretName: echo-cert
---
apiVersion: v1
kind: Service
metadata:
name: echo
namespace: futureporn
annotations:
external-dns.alpha.kubernetes.io/hostname: "{{ .Values.echo.hostname }}"
{{ if eq .Values.environment "development" }}
chisel-operator.io/exit-node-name: "echo-exit-node"
{{ end }}
spec:
type: LoadBalancer
selector:
app: echo
ports:
- name: web
protocol: TCP
port: 5678
targetPort: 5678
- name: websecure
protocol: TCP
port: 4443
targetPort: 5678
---
apiVersion: cert-manager.io/v1
kind: Certificate
metadata:
name: echo
namespace: futureporn
spec:
secretName: echo-tls
issuerRef:
name: "{{ .Values.certManager.issuer }}"
kind: ClusterIssuer
dnsNames:
- "{{ .Values.echo.hostname }}"
---
apiVersion: traefik.io/v1alpha1
kind: IngressRoute
metadata:
name: echo-http
namespace: futureporn
spec:
entryPoints:
- web
routes:
- match: Host(`echo.fp.sbtp.xyz`)
kind: Rule
middlewares:
- name: redirect
namespace: futureporn
services:
- name: echo
namespace: futureporn
port: 5678
---
apiVersion: traefik.io/v1alpha1
kind: IngressRoute
metadata:
name: echo-https
namespace: futureporn
annotations:
cert-manager.io/cluster-issuer: "{{ .Values.certManager.issuer }}"
spec:
entryPoints:
- websecure
routes:
- match: Host(`echo.fp.sbtp.xyz`)
kind: Rule
services:
- name: echo
namespace: futureporn
port: 5678
tls:
secretName: echo-tls

View File

@ -13,6 +13,8 @@ spec:
env:
- name: HOSTNAME
value: 0.0.0.0
- name: NEXT_PUBLIC_UPPY_COMPANION_URL
value: "{{ .Values.uppy.hostname }}"
ports:
- name: web
containerPort: 3000

View File

@ -0,0 +1,219 @@
apiVersion: apps/v1
kind: Deployment
metadata:
name: uppy
namespace: futureporn
spec:
replicas: 2
minReadySeconds: 5
strategy:
type: RollingUpdate
rollingUpdate:
maxSurge: 2
maxUnavailable: 1
selector:
matchLabels:
app: uppy
template:
metadata:
labels:
app: uppy
spec:
containers:
- name: uppy
image: docker.io/transloadit/companion:latest
imagePullPolicy: IfNotPresent
resources:
limits:
memory: 150Mi
requests:
memory: 100Mi
env:
- name: COMPANION_STREAMING_UPLOAD
value: "true"
- name: COMPANION_CLIENT_ORIGINS
value: "{{ .Values.uppy.clientOrigins }}"
- name: COMPANION_DATADIR
value: /tmp/
- name: COMPANION_DOMAIN
value: "{{ .Values.uppy.domain }}"
- name: COMPANION_PROTOCOL
value: https
- name: COMPANION_REDIS_URL
valueFrom:
secretKeyRef:
name: uppy
key: redisUrl
- name: COMPANION_SECRET
valueFrom:
secretKeyRef:
name: uppy
key: secret
- name: COMPANION_PREAUTH_SECRET
valueFrom:
secretKeyRef:
name: uppy
key: preAuthSecret
- name: COMPANION_DROPBOX_KEY
valueFrom:
secretKeyRef:
name: uppy
key: dropboxKey
- name: COMPANION_DROPBOX_SECRET
valueFrom:
secretKeyRef:
name: uppy
key: dropboxSecret
- name: COMPANION_BOX_KEY
valueFrom:
secretKeyRef:
name: uppy
key: boxKey
- name: COMPANION_BOX_SECRET
valueFrom:
secretKeyRef:
name: uppy
key: boxSecret
- name: COMPANION_GOOGLE_KEY
valueFrom:
secretKeyRef:
name: uppy
key: googleKey
- name: COMPANION_GOOGLE_SECRET
valueFrom:
secretKeyRef:
name: uppy
key: googleSecret
- name: COMPANION_AWS_KEY
valueFrom:
secretKeyRef:
name: uppy
key: awsKey
- name: COMPANION_AWS_SECRET
valueFrom:
secretKeyRef:
name: uppy
key: awsSecret
- name: COMPANION_AWS_BUCKET
value: "{{ .Values.uppy.s3.bucket }}"
- name: COMPANION_AWS_REGION
value: "{{ .Values.uppy.s3.region }}"
- name: COMPANION_AWS_PREFIX
value: "{{ .Values.uppy.s3.prefix }}"
## COMPANION_OAUTH_DOMAIN is only necessary if using a different domain per each uppy pod.
## We don't need this because we are load balancing the pods so they all use the same domain name.
## @see https://github.com/transloadit/uppy/blob/f4dd3d534ff4378f3a2f73fe327358bcbde74059/docs/companion.md#server
- name: COMPANION_OAUTH_DOMAIN
value: ''
- name: COMPANION_PATH
value: ''
- name: COMPANION_IMPLICIT_PATH
value: ''
- name: COMPANION_DOMAINS
value: ''
## https://uppy.io/docs/companion/#uploadurls-companion_upload_urls
- name: COMPANION_UPLOAD_URLS
value: "{{ .Values.uppy.uploadUrls }}"
ports:
- containerPort: 3020
volumeMounts:
- name: uppy-data
mountPath: /mnt/uppy-data
volumes:
- name: uppy-data
emptyDir: {}
---
apiVersion: v1
kind: Service
metadata:
name: uppy
namespace: futureporn
annotations:
external-dns.alpha.kubernetes.io/hostname: "{{ .Values.uppy.hostname }}"
chisel-operator.io/exit-node-name: "uppy-exit-node"
spec:
type: LoadBalancer
ports:
- port: 3020
targetPort: 3020
protocol: TCP
selector:
app: uppy
{{ if eq .Values.environment "development" }}
---
apiVersion: chisel-operator.io/v1
kind: ExitNode
metadata:
name: uppy-exit-node
namespace: futureporn
spec:
host: "{{ .Values.chisel.exitNodeIp }}"
port: 9090
auth: chisel
{{ end }}
---
apiVersion: traefik.io/v1alpha1
kind: IngressRoute
metadata:
name: uppy-http
namespace: futureporn
spec:
entryPoints:
- web
routes:
- match: Host(`uppy.fp.sbtp.xyz`)
kind: Rule
middlewares:
- name: redirect
namespace: futureporn
services:
- name: uppy
namespace: futureporn
port: 3020
---
apiVersion: traefik.io/v1alpha1
kind: IngressRoute
metadata:
name: uppy-https
namespace: futureporn
annotations:
cert-manager.io/cluster-issuer: "{{ .Values.certManager.issuer }}"
spec:
entryPoints:
- websecure
routes:
- match: Host(`uppy.fp.sbtp.xyz`)
kind: Rule
services:
- name: uppy
namespace: futureporn
port: 3020
tls:
secretName: uppy-tls
# Welcome to Companion v4.15.1
# ===================================
# Congratulations on setting up Companion! Thanks for joining our cause, you have taken
# the first step towards the future of file uploading! We
# hope you are as excited about this as we are!
# While you did an awesome job on getting Companion running, this is just the welcome
# message, so let's talk about the places that really matter:
# - Be sure to add the following URLs as your Oauth redirect uris on their corresponding developer interfaces:
# https://uppy.fp.sbtp.xyz/drive/redirect, https://uppy.fp.sbtp.xyz/googlephotos/redirect, https://uppy.fp.sbtp.xyz/dropbox/redirect, https://uppy.fp.sbtp.xyz/box/redirect, https://uppy.fp.sbtp.xyz/instagram/redirect, https://uppy.fp.sbtp.xyz/facebook/redirect, https://uppy.fp.sbtp.xyz/onedrive/redirect, https://uppy.fp.sbtp.xyz/zoom/redirect, https://uppy.fp.sbtp.xyz/unsplash/redirect
# - The URL https://uppy.fp.sbtp.xyz/metrics is available for statistics to keep Companion running smoothly
# - https://github.com/transloadit/uppy/issues - report your bugs here
# So quit lollygagging, start uploading and experience the future!

View File

@ -34,5 +34,16 @@ chisel:
exitNodeIp: "155.138.254.201"
echo:
hostname: echo.fp.sbtp.xyz
uppy:
hostname: uppy.fp.sbtp.xyz
imageName: fp/uppy
s3:
endpoint: s3.us-west-000.backblazeb2.com
bucket: futureporn-usc
region: us-west-000
prefix: s3
clientOrigins: next.fp.sbtp.xyz
domain: uppy.fp.sbtp.xyz
uploadUrls: https://uppy.fp.sbtp.xyz/files
certManager:
issuer: letsencrypt-staging

View File

@ -5,22 +5,16 @@ RUN corepack enable
FROM base AS build
ENV NODE_ENV=production
COPY . /usr/src/app
COPY ./packages/bot /usr/src/app
WORKDIR /usr/src/app
RUN mkdir -p /prod/scout
RUN --mount=type=cache,id=pnpm,target=/pnpm/store pnpm install --frozen-lockfile
RUN pnpm deploy --filter=scout --prod /prod/scout
RUN pnpm deploy --filter=bot --prod /prod/scout
FROM base AS manager
COPY --from=build /prod/scout /app
FROM base AS bot
COPY --from=build /prod/bot /app
WORKDIR /app
ENTRYPOINT ["pnpm"]
CMD ["run", "start:manager"]
FROM base AS worker
COPY --from=build /prod/scout /app
WORKDIR /app
ENTRYPOINT ["pnpm"]
CMD ["run", "start:worker"]
CMD ["run", "start"]

42
d.packages.dockerfile Normal file
View File

@ -0,0 +1,42 @@
## This dockerfile creates multiple docker images.
## Because we are using monorepo with pnpm workspaces, we have many npm packages in this single git repo.
## Some of these packages in the monorepo depend on other packages in the monorepo.
## In order to build these individual packages which inter-depend on eachother,
## all of the dependent code must be present in the build.
##
## Below, COPY . /usr/src/app copies all the app code into the build context.
## Because we use Tilt, only specific path directories are visible to docker. This helps with build performance.
## When a new package becomes a dependency, we need to update our Tiltfile to include the package directory.
## Tiltfile example of docker_build() args which include `scout` and `next` packages.
## `only=['./pnpm-lock.yaml', './package.json', './packages/scout', './packages/next'],`
##
##
FROM node:20 AS base
ENV PNPM_HOME="/pnpm"
ENV PATH="$PNPM_HOME:$PATH"
RUN corepack enable
FROM base AS build
ENV NODE_ENV=production
COPY . /usr/src/app
WORKDIR /usr/src/app
RUN mkdir -p /prod/scout
RUN --mount=type=cache,id=pnpm,target=/pnpm/store pnpm install --frozen-lockfile
RUN pnpm deploy --filter=scout --prod /prod/scout
# RUN pnpm deploy --filter=bot --prod /prod/bot
FROM base AS scout-manager
COPY --from=build /prod/scout /app
WORKDIR /app
ENTRYPOINT ["pnpm"]
CMD ["run", "start:manager"]
FROM base AS scout-worker
COPY --from=build /prod/scout /app
COPY --from=build /usr/src/app/certs/letsencrypt-stg-root-x1.pem
ENV NODE_EXTRA_CA_CERTS "/app/certs/letsencrypt-stg-root-x1.pem"
WORKDIR /app
ENTRYPOINT ["pnpm"]
CMD ["run", "start:worker"]

View File

@ -5,9 +5,9 @@ WORKDIR /app
RUN corepack enable
FROM base as build
COPY ./packages/uppy/package.json ./
COPY ./packages/uppy/index.js ./
RUN --mount=type=cache,id=pnpm,target=/pnpm/store pnpm install
COPY ./packages/uppy/package.json ./packages/uppy/pnpm-lock.yaml /app
RUN --mount=type=cache,id=pnpm,target=/pnpm/store pnpm install --frozen-lockfile
COPY ./packages/uppy/ .
FROM build as run
ENTRYPOINT ["pnpm"]

View File

@ -1,5 +1,5 @@
# Futureporn node packages
Each folder here is an individual node package, each of which can reference each other.
Each folder here is an individual node package, each of which can reference each other. One reason we do this is to share utility functions between packages.
See https://pnpm.io/workspaces

View File

@ -1,3 +1,3 @@
# infra
This module contains scripts that help with miscellaneous infrastructure tasks.
This module contains scripts that help with miscellaneous infrastructure tasks like cleaning up unused resources on Vultr Kubernetes Engine.

View File

@ -1,5 +1,5 @@
{
"name": "scripts",
"name": "infra",
"type": "module",
"version": "1.0.0",
"description": "",

View File

@ -1,27 +1,2 @@
# futureporn-next
## Dev notes
When adding a new module via pnpm, docker compose needs to be restarted or something. I'm not sure the exact steps just yet, but I think it's something like the following.
```
pnpm add @uppy/react
docker compose build next
```
> fp-next | Module not found: Can't resolve '@uppy/react'
hmm... It looks like I'm missing something. Is the new package not getting into the container? Maybe it's something to do with the pnpm cache?
Must we build without cache?
docker compose build --no-cache next; docker compose up
YES. that solved the issue.
However, it's really slow to purge cache and download all packages once again. Is there a way we can speed this up?
* make it work
* make it right
* make it fast
# next

View File

@ -8,47 +8,19 @@ export default async function Page() {
return (
<>
<div className="content">
<div className="content">
<section className="hero">
<div className="hero-body">
<p className="title">About</p>
<p>Futureporn is a fanmade public archive of NSFW R18 vtuber livestreams.</p>
<p>It's the worst feeling when a VOD disappears from the internet. It means you missed out, it's gone, and you may never experience what your peers got to take part in.</p>
<p>Futureporn is created by fans, for fans. Missed a stream? We got you, bro.</p>
<p>Together we can end 404s and create an everlasting archive of lewdtuber livestreams.</p>
</div>
</section>
<div className="section">
<h1>Mission</h1>
<p>It&apos;s a lofty goal, but Futureporn aims to become <b>the Galaxy&apos;s best VTuber hentai site.</b></p>
</div>
<div className="section">
<h2>How do we get there?</h2>
<h3>1. Solve the viewer&apos;s common problems</h3>
<p>Viewers want to watch livestream VODs on their own time. Futureporn collects vods from public streams, and caches them for later viewing.</p>
<p>Viewers want to find content that interests them. Futureporn enables vod tagging for easy browsing.</p>
</div>
<div className="section">
<h3>2. Solve the streamer&apos;s common problems</h3>
<p>Platforms like PH are not rising to the needs of VTubers. Instead of offering support and resources, they restrict and ban top talent.</p>
<p>Futureporn is different, embracing the medium and leveraging emerging technologies to amplify VTuber success.</p>
</div>
<div className="section">
<h3>3. Scale beyond Earth</h3>
<p>Piggybacking on <Link href="/faq#ipfs">IPFS</Link>&apos; content-addressable capabilities and potential to end 404s, VODs preserved here can withstand the test of time, and eventually persist <Link href="/goals">off-world</Link>.</p>
</div>
<div className="section">

View File

@ -6,7 +6,7 @@ export default function NotFound() {
<h2 className='title is-2'>404 Not Found</h2>
<p>Could not find that stream archive.</p>
<Link href="/s">Return to archive list</Link>
<Link href="/archive">Return to archive list</Link>
</div>
)
}

View File

@ -63,7 +63,7 @@ export default function Navbar() {
</div>
{/* <div className="navbar-item">
<div className="navbar-item">
<Link className="button " href="/upload">
<span className="mr-1">Upload</span>
<FontAwesomeIcon
@ -71,7 +71,7 @@ export default function Navbar() {
className="fas fa-upload"
></FontAwesomeIcon>
</Link>
</div> */}
</div>
<div className="navbar-item fp-profile-button">
{/* show the login button if user is anon */}

View File

@ -10,8 +10,6 @@ interface PatronsListProps {
export default async function PatronsList({ displayStyle }: PatronsListProps) {
const patrons = await getPatrons()
console.log(`patrons are as follows`)
console.log(patrons)
if (!patrons) return (
<SkeletonTheme baseColor="#000" highlightColor="#000">

View File

@ -11,6 +11,7 @@ import { faTriangleExclamation, faCircleInfo, faThumbsUp, IconDefinition, faO, f
import { Hemisphere, Moon } from "lunarphase-js";
import { useEffect, useState } from "react";
import { faXTwitter } from "@fortawesome/free-brands-svg-icons";
import { notFound } from "next/navigation";
export interface IStreamProps {
stream: IStream;
@ -47,6 +48,7 @@ function determineStatus(stream: IStream): Status {
export default function StreamPage({ stream }: IStreamProps) {
console.log('StreamPage function has been invoked! stream as follows')
console.log(stream)
if (!stream) notFound()
const displayName = stream.attributes.vtuber.data.attributes.displayName;
const date = new Date(stream.attributes.date);
const [hemisphere, setHemisphere] = useState(Hemisphere.NORTHERN);
@ -169,8 +171,7 @@ export default function StreamPage({ stream }: IStreamProps) {
<span className="title is-1"><FontAwesomeIcon icon={icon}></FontAwesomeIcon></span>
<p className="mt-3">{desc1}</p>
<p className="mt-5">{desc2}<br />
{/* <Link href={`/upload?cuid=${stream.attributes.cuid}`}>Upload it here.</Link></p> */}
<Link style={{ cursor: 'not-allowed' }} href={`/upload?cuid=${stream.attributes.cuid}`}><i>Uploads coming soon.</i></Link></p>
<Link href={`/upload?cuid=${stream.attributes.cuid}`}>Upload it here.</Link></p>
</div>
</article>
</div>

View File

@ -16,7 +16,8 @@ import {
ColumnDef,
flexRender,
} from '@tanstack/react-table'
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'
import { faSpinner } from '@fortawesome/free-solid-svg-icons'
import { fetchStreamData, IStream } from '@/lib/streams'
@ -129,20 +130,20 @@ export default function StreamsTable() {
pageSize: 50,
})
const dataQuery = useQuery({
const { data, error, isPending } = useQuery({
queryKey: ['streams', pagination.pageIndex, pagination.pageSize],
queryFn: () => fetchStreamData(pagination),
placeholderData: keepPreviousData, // don't have 0 rows flash while changing pages/loading next page,
staleTime: 1000
staleTime: 1000,
}, queryClient)
const defaultData = React.useMemo(() => [], [])
const table = useReactTable({
data: dataQuery?.data?.rows ?? defaultData,
data: data?.rows ?? defaultData,
columns,
// pageCount: dataQuery.data?.pageCount ?? -1, //you can now pass in `rowCount` instead of pageCount and `pageCount` will be calculated internally (new in v8.13.0)
rowCount: dataQuery.data?.rowCount, // new in v8.13.0 - alternatively, just pass in `pageCount` directly
rowCount: data?.rowCount, // new in v8.13.0 - alternatively, just pass in `pageCount` directly
state: {
pagination,
},
@ -156,49 +157,53 @@ export default function StreamsTable() {
return (
<div className="p-2">
<div className="h-2" />
<table className='table is-hoverable is-fullwidth'>
<thead>
{table.getHeaderGroups().map(headerGroup => (
<tr key={headerGroup.id}>
{headerGroup.headers.map(header => {
return (
<th key={header.id} colSpan={header.colSpan}>
{header.isPlaceholder ? null : (
<div>
{flexRender(
header.column.columnDef.header,
header.getContext()
)}
</div>
)}
</th>
)
})}
</tr>
))}
</thead>
<tbody>
{table.getRowModel().rows.map(row => {
return (
<tr key={row.id}>
{row.getVisibleCells().map(cell => {
{isPending && <FontAwesomeIcon className="mt-5 fa-spin-pulse" icon={faSpinner} ></FontAwesomeIcon> }
{!isPending && <>
<table className='table is-hoverable is-fullwidth'>
<thead>
{table.getHeaderGroups().map(headerGroup => (
<tr key={headerGroup.id}>
{headerGroup.headers.map(header => {
return (
<td
className={getStatusClass(cell.getValue() as string)}
key={cell.id}
>
{flexRender(
cell.column.columnDef.cell,
cell.getContext()
<th key={header.id} colSpan={header.colSpan}>
{header.isPlaceholder ? null : (
<div>
{flexRender(
header.column.columnDef.header,
header.getContext()
)}
</div>
)}
</td>
</th>
)
})}
</tr>
)
})}
</tbody>
</table>
))}
</thead>
<tbody>
{table.getRowModel().rows.map(row => {
return (
<tr key={row.id}>
{row.getVisibleCells().map(cell => {
return (
<td
className={getStatusClass(cell.getValue() as string)}
key={cell.id}
>
{flexRender(
cell.column.columnDef.cell,
cell.getContext()
)}
</td>
)
})}
</tr>
)
})}
</tbody>
</table>
<div className="columns is-mobile is-vcentered">
<div className='column is-half'>
@ -273,6 +278,7 @@ export default function StreamsTable() {
</div>
</div>
</div>
</>}

View File

@ -159,235 +159,241 @@ export default function UploadForm({ vtubers }: IUploadFormProps) {
uppy.on('complete', async (result: any) => {
console.log('uppy complete! ')
console.log(result)
for (const s of result.successful) {
if (!s?.s3Multipart) {
setError('root.serverError', {
type: 'remote',
message: 'file was missing s3Multipart'
})
// throw new Error('file was missing s3Multipart')
}
}
let files = result.successful.map((f: any) => ({ key: f.s3Multipart.key, uploadId: f.s3Multipart.uploadId }));
setValue('files', files);
});
return (<div className="notification is-secondary">
<h1 className="title">VOD uploads</h1>
<p>
<i>coming soon!!</i>
</p>
<hr ></hr>
<p>Track progress on the <a href="/goals">Goals Page</a></p>
</div>)
// return (
// <>
return (
<>
// <div className='section'>
// <h2 className='title is-2'>Upload VOD</h2>
<div className='section'>
<h2 className='title is-2'>Upload VOD</h2>
// <p className="mb-5"><i>Together we can archive all lewdtuber livestreams!</i></p>
<p className="mb-5"><i>Together we can archive all lewdtuber livestreams!</i></p>
// {(!authData?.accessToken)
// ?
// <>
// <aside className='notification is-danger'><p>Please log in to upload VODs</p></aside>
// <LoginButton />
// </>
// : (
{(!authData?.accessToken)
?
<>
<aside className='notification is-danger'><p>Please log in to upload VODs</p></aside>
<LoginButton />
</>
: (
// <div className='columns is-multiline'>
// <form id="vod-details" onSubmit={handleSubmit(createUSC)}>
<div className='columns is-multiline'>
<form id="vod-details" onSubmit={handleSubmit(createUSC)}>
// {(!isSubmitSuccessful) && <div className='column is-full'>
// <section className="hero is-info mb-3">
// <div className="hero-body">
// <p className="title">
// Step 1
// </p>
// <p className="subtitle">
// Upload the file
// </p>
// </div>
// </section>
// <section className="section mb-5">
// <Dashboard
// uppy={uppy}
// theme='dark'
// proudlyDisplayPoweredByUppy={false}
// />
{(!isSubmitSuccessful) && <div className='column is-full'>
<section className="hero is-info mb-3">
<div className="hero-body">
<p className="title">
Step 1
</p>
<p className="subtitle">
Upload the file
</p>
</div>
</section>
<section className="section mb-5">
<Dashboard
uppy={uppy}
theme='dark'
proudlyDisplayPoweredByUppy={true}
showProgressDetails={true}
/>
// <input
// required
// hidden={true}
// style={{ display: 'none' }}
// className="input" type="text"
// {...register('files')}
// ></input>
{/* This form is hidden. Why? */}
<input
required
hidden={false}
style={{ display: 'block' }}
className="input" type="text"
{...register('files')}
></input>
// {errors.files && <p className="help is-danger">{errors.files.message?.toString()}</p>}
{errors.files && <p className="help is-danger">{errors.files.message?.toString()}</p>}
// </section>
// </div>}
</section>
</div>}
// {(!isSubmitSuccessful) && <div className='column is-full '>
// {/* {(!cuid) && <aside className='notification is-info'>Hint: Some of these fields are filled out automatically when uploading from a <Link href="/streams">stream</Link> page.</aside>} */}
{(!isSubmitSuccessful) && <div className='column is-full '>
{/* {(!cuid) && <aside className='notification is-info'>Hint: Some of these fields are filled out automatically when uploading from a <Link href="/streams">stream</Link> page.</aside>} */}
// <section className="hero is-info mb-3">
// <div className="hero-body">
// <p className="title">
// Step 2
// </p>
// <p className="subtitle">
// Tell us about the VOD
// </p>
// </div>
// </section>
<section className="hero is-info mb-3">
<div className="hero-body">
<p className="title">
Step 2
</p>
<p className="subtitle">
Tell us about the VOD
</p>
</div>
</section>
// <section className="section">
<section className="section">
// {/* <input
// required
// // hidden={false}
// // style={{ display: 'none' }}
// className="input" type="text"
// {...register('streamCuid')}
// ></input> */}
{/* <input
required
// hidden={false}
// style={{ display: 'none' }}
className="input" type="text"
{...register('streamCuid')}
></input> */}
// <div className="field">
// <label className="label">VTuber</label>
// <div className="select">
// <select
// required
// // value={vtuber}
// // onChange={(evt) => setVtuber(parseInt(evt.target.value))}
// {...register('vtuber')}
// >
// {vtubers.map((vtuber: IVtuber) => (
// <option key={vtuber.id} value={vtuber.id}>{vtuber.attributes.displayName}</option>
// ))}
// </select>
// </div>
// <p className="help is-info">Choose the VTuber this VOD belongs to. (More VTubers will be added when storage/bandwidth funding is secured.)</p>
// {errors.vtuber && <p className="help is-danger">vtuber error</p>}
<div className="field">
<label className="label">VTuber</label>
<div className="select">
<select
required
// value={vtuber}
// onChange={(evt) => setVtuber(parseInt(evt.target.value))}
{...register('vtuber')}
>
{vtubers.map((vtuber: IVtuber) => (
<option key={vtuber.id} value={vtuber.id}>{vtuber.attributes.displayName}</option>
))}
</select>
</div>
<p className="help is-info">Choose the VTuber this VOD belongs to. (More VTubers will be added when storage/bandwidth funding is secured.)</p>
{errors.vtuber && <p className="help is-danger">vtuber error</p>}
// </div>
</div>
// <div className="field">
// <label className="label">Stream Date</label>
// <input
// required
// className="input" type="date"
// {...register('date')}
// // onChange={(evt) => setDate(evt.target.value)}
// ></input>
// <p className="help is-info">The date when the VOD was originally streamed.</p>
// {errors.date && <p className="help is-danger">{errors.date.message?.toString()}</p>}
<div className="field">
<label className="label">Stream Date</label>
<input
required
className="input" type="date"
{...register('date')}
// onChange={(evt) => setDate(evt.target.value)}
></input>
<p className="help is-info">The date when the VOD was originally streamed.</p>
{errors.date && <p className="help is-danger">{errors.date.message?.toString()}</p>}
// </div>
</div>
// <div className="field">
// <label className="label">Notes</label>
// <textarea
// className="textarea"
// placeholder="e.g. Missing first 10 minutes of stream"
// // onChange={(evt) => setNote(evt.target.value)}
// {...register('notes')}
// ></textarea>
// <p className="help is-info">If there are any issues with the VOD, put a note here. If there are no VOD issues, leave this field blank.</p>
// </div>
<div className="field">
<label className="label">Notes</label>
<textarea
className="textarea"
placeholder="e.g. Missing first 10 minutes of stream"
// onChange={(evt) => setNote(evt.target.value)}
{...register('notes')}
></textarea>
<p className="help is-info">If there are any issues with the VOD, put a note here. If there are no VOD issues, leave this field blank.</p>
</div>
// <div className="field">
// <label className="label">Attribution</label>
// <label className="checkbox">
// <input
// type="checkbox"
// // onChange={(evt) => setAttribution(evt.target.checked)}
// {...register('attribution')}
// />
// <span className={`ml-2 ${styles.noselect}`}>Credit {authData.user?.username} for the upload.</span>
// <p className="help is-info">Check this box if you want your username displayed on the website. Thank you for uploading!</p>
// </label>
// </div>
<div className="field">
<label className="label">Attribution</label>
<label className="checkbox">
<input
type="checkbox"
// onChange={(evt) => setAttribution(evt.target.checked)}
{...register('attribution')}
/>
<span className={`ml-2 ${styles.noselect}`}>Credit {authData.user?.username} for the upload.</span>
<p className="help is-info">Check this box if you want your username displayed on the website. Thank you for uploading!</p>
</label>
</div>
// </section>
</section>
// </div>}
</div>}
// <div className="column is-full">
// <section className="hero is-info">
// <div className="hero-body">
// <p className="title">
// Step 3
// </p>
// <p className="subtitle">
// Send the form
// </p>
// </div>
// </section>
// <section className="section">
<div className="column is-full">
<section className="hero is-info">
<div className="hero-body">
<p className="title">
Step 3
</p>
<p className="subtitle">
Send the form
</p>
</div>
</section>
<section className="section">
// {errors.root?.serverError && (
// <div className="notification">
// <button className="delete" onClick={() => clearErrors()}></button>
// <ErrorMessage name="root" errors={errors} ></ErrorMessage>
// </div>
// )}
{errors.root?.serverError && (
<div className="notification">
<button className="delete" onClick={() => clearErrors()}></button>
<ErrorMessage name="root" errors={errors} ></ErrorMessage>
</div>
)}
// {!isSubmitSuccessful && (
// <button className="button is-primary is-large mt-5">
// <span className="icon is-small">
// <FontAwesomeIcon icon={faPaperPlane}></FontAwesomeIcon>
// </span>
// <span>Send</span>
// </button>
// )}
{!isSubmitSuccessful && (
<button className="button is-primary is-large mt-5">
<span className="icon is-small">
<FontAwesomeIcon icon={faPaperPlane}></FontAwesomeIcon>
</span>
<span>Send</span>
</button>
)}
// {isSubmitting && (
// <p>
// <FontAwesomeIcon className="mt-5 fa-spin-pulse" icon={faSpinner} ></FontAwesomeIcon>
// </p>
// )}
// {isSubmitSuccessful && (
// <>
// <aside className="notification mt-5 is-success">Thank you for uploading! </aside>
// <button onClick={() => {
// reset(); // reset form
// const files = uppy.getFiles()
// for (const file of files) {
// uppy.removeFile(file.id); // reset uppy
// }
// }} className="button is-primary">
// <span className="icon is-small">
// <FontAwesomeIcon icon={faEraser}></FontAwesomeIcon>
// </span>
// <span>Reset form</span>
// </button>
// </>
// )}
{isSubmitting && (
<p>
<FontAwesomeIcon className="mt-5 fa-spin-pulse" icon={faSpinner} ></FontAwesomeIcon>
</p>
)}
{isSubmitSuccessful && (
<>
<aside className="notification mt-5 is-success">Thank you for uploading! </aside>
<button onClick={() => {
reset(); // reset form
const files = uppy.getFiles()
for (const file of files) {
uppy.removeFile(file.id); // reset uppy
}
}} className="button is-primary">
<span className="icon is-small">
<FontAwesomeIcon icon={faEraser}></FontAwesomeIcon>
</span>
<span>Reset form</span>
</button>
</>
)}
// </section>
// </div>
</section>
</div>
// </form>
// </div>
</form>
</div>
// )
// }
)
}
// </div>
</div>
// </>
// )
</>
)
}

View File

@ -340,14 +340,14 @@ export async function fetchStreamData({ pageIndex, pageSize }: { pageIndex: numb
})
const response = await fetch(
`${strapiUrl}/api/streams?${query}`
);
const json = await response.json();
console.log(json)
const d = {
rows: json.data,
pageCount: Math.ceil(json.meta.pagination.total / pageSize),
rowCount: json.meta.pagination.total,
}
);
const json = await response.json();
console.log(json)
const d = {
rows: json.data,
pageCount: Math.ceil(json.meta.pagination.total / pageSize),
rowCount: json.meta.pagination.total,
}
// console.log(`fetchStreamData with pageIndex=${pageIndex}, pageSize=${pageSize}\n\n${JSON.stringify(d, null, 2)}`)
return d;
}

View File

@ -8,6 +8,10 @@ import { useAuth } from './components/auth';
import { companionUrl } from '@/lib/constants';
// Uppy is a challenging react integration. Following are some references
// @see https://github.com/transloadit/uppy/issues/4727#issuecomment-1761118428
export const UppyContext = createContext(new Uppy());
export default function UppyProvider({
@ -18,12 +22,17 @@ export default function UppyProvider({
const { authData } = useAuth();
const [uppy] = useState(() => new Uppy(
{
autoProceed: true
autoProceed: false,
debug: true
}
)
.use(RemoteSources, {
companionUrl,
sources: ['GoogleDrive']
sources: [
'GoogleDrive',
'Dropbox',
'Url'
]
})
.use(AwsS3, {
companionUrl,

View File

@ -1,4 +1,4 @@
{
"extension": ["js"],
"spec": "src/**/*.spec.js"
"extension": ["ts"],
"spec": "src/**/*.spec.ts"
}

View File

@ -1,8 +1,3 @@
// export function blah(name) {
// return `Today is a blah kind of a day. amirite, ${name}?`;
// }
import fetch from "node-fetch"
import { NotificationData, processEmail } from "./workflows.js"
import qs from 'qs'

View File

@ -19,7 +19,7 @@
"declarationMap": true,
"sourceMap": true,
"rootDir": "./src",
"outDir": "./lib"
"outDir": "./dist"
},
"include": ["**/*.ts"],
"ts-node": {

View File

@ -1,6 +1,7 @@
module.exports = ({ env }) => ({
host: env('HOST', '0.0.0.0'),
port: env.int('PORT', 1337),
proxy: true,
app: {
keys: env.array('APP_KEYS'),
},

View File

@ -1,6 +1,7 @@
{
"compilerOptions": {
"moduleResolution": "nodenext",
"module": "NodeNext",
"moduleResolution": "NodeNext",
"target": "ES2021",
"checkJs": true,
"allowJs": true

View File

@ -11,10 +11,10 @@ function generateCuid(event) {
module.exports = {
async beforeUpdate(event) {
console.log(`>> beforeUpdate! We are generating a CUID`);
generateCuid(event);
},
async beforeCreate(event) {
console.log(`>> beforeCreate! We are generating a CUID`);
console.log(`>> beforeCreate! We are generating a CUID`);
generateCuid(event);
},
@ -22,4 +22,6 @@ module.exports = {
console.log(`>> afterCreate! We are generating a CUID`);
generateCuid(event);
}
}
}

View File

@ -1,30 +0,0 @@
SESSION_SECRET=a9834jjajfajfiojaoejfbitco####$#iniswhigjlbutoonlyifyour8asl
PORT=5000
FILEPATH=/tmp
HOST=http://localhost:5000
UPLOAD_URLS=http://localhost:5000
SECRET=afjafifjfjSHHHHHHdontdtouchtiafImS+____cared
SERVER_BASE_URL=http://localhost:5000
B2_ENDPOINT=s3.us-west-000.backblazeb2.com
B2_BUCKET=fp-usc-dev
B2_SECRET=K0004kP+ZfsINYsvWMGYdX66Gr5ZvIo
B2_KEY=000d37f13a933b80000000034
DRIVE_KEY=886031456924-jiuukhfte5n0cfkktevgojpum54dn6r3.apps.googleusercontent.com
DRIVE_SECRET=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
DROPBOX_KEY=zvaxniaf1gunns9
DROPBOX_SECRET=cclglkkjkoqqo3v
JWT_SECRET=GRYMjvirjfI6GxzkbNQMhg==
STRAPI_API_KEY=9ad1b224cb399219cae910569875aa76ff2bd408db7e799653d4317198e326f04694abbecb31efc2d5b845c39e348940bb548b07ecf1d3fff07535d92df001700ce8dfea96dd3fd8a720c49f366761537f0042a74b4e35100b783f54be28e13086c96a1d437ff31c80568618ef94ef7de7ba3f8396651f2797ff2eb6091e1a7f
STRAPI_URL=http://localhost:1337
#B2_ENDPOINT=s3.us-west-000.backblazeb2.com
#B2_BUCKET=futureporn-uppy
#B2_SECRET=K000NRFAHCIWBYOhXa1QlabBzi5Puvk
#B2_KEY=000d37f13a933b80000000025
#B2_BUCKET=0d53c79f31b3ead983030b18
#B2_KEY_ID=000d37f13a933b80000000025
#B2_KEY_NAME=futureporn-uppy-2023-05-05
#B2_APPLICATION_KEY=K000NRFAHCIWBYOhXa1QlabBzi5Puvk

View File

@ -1,17 +0,0 @@
SESSION_SECRET=a9834jjajfajfiojaoejfbitco####$#iniswhigjlbutoonlyifyour8asl
PORT=5000
FILEPATH=/tmp
HOST=https://uppy.futureporn.net
UPLOAD_URLS=https://uppy.futureporn.net
SECRET=afjafifjfjSHHHHHHdontdtouchtiafImS+____cared
SERVER_BASE_URL=http://uppy.futureporn.net
B2_ENDPOINT=s3.us-west-000.backblazeb2.com
B2_BUCKET=futureporn
B2_SECRET=K000euvnkS7IiMiCUQA3iCy/qxwwvLw
B2_KEY=000d37f13a933b8000000002a
DRIVE_KEY=886031456924-jiuukhfte5n0cfkktevgojpum54dn6r3.apps.googleusercontent.com
DRIVE_SECRET=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
DROPBOX_KEY=zvaxniaf1gunns9
DROPBOX_SECRET=cclglkkjkoqqo3v
JWT_SECRET=GRYMjvirjfI6GxzkbNQMhg==

View File

@ -1,6 +1,6 @@
# uppy
This is the server component which handles user uploads.
This is the server-side component which handles user uploads. It is especially useful for allowing users to upload directly from their Dropbox, GoogleDrive, etc.
## B2 Bucket CORS configuration

View File

@ -1,7 +1,6 @@
#!/usr/bin/env node
import dotenv from 'dotenv'
dotenv.config()
import 'dotenv/config'
import express from 'express'
import bodyParser from 'body-parser'
import session from 'express-session'
@ -12,6 +11,7 @@ import jwt from 'jsonwebtoken'
const appEnv = new Array(
'HOST',
'SESSION_SECRET',
'PORT',
'FILEPATH',

View File

@ -1,19 +1,15 @@
{
"type": "module",
"name": "fp-uppy",
"version": "1.0.0",
"name": "uppy",
"version": "1.0.5",
"description": "",
"main": "index.js",
"scripts": {
"start": "node index",
"dev": "nodemon --watch **/*.js --watch .env --watch package.json index"
"start": "node index"
},
"keywords": [],
"author": "",
"license": "Unlicense",
"devDependencies": {
"nodemon": "^3.1.0"
},
"dependencies": {
"@uppy/aws-s3-multipart": "^2.4.3",
"@uppy/companion": "4.12.0",

View File

@ -41,10 +41,6 @@ importers:
yup:
specifier: link:@hookform/resolvers/yup
version: link:@hookform/resolvers/yup
devDependencies:
nodemon:
specifier: ^3.1.0
version: 3.1.0
packages:
@ -501,9 +497,6 @@ packages:
'@uppy/utils@4.1.3':
resolution: {integrity: sha512-nTuMvwWYobnJcytDO3t+D6IkVq/Qs4Xv3vyoEZ+Iaf8gegZP+rEyoaFT2CK5XLRMienPyqRqNbIfRuFaOWSIFw==}
abbrev@1.1.1:
resolution: {integrity: sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==}
accepts@1.3.8:
resolution: {integrity: sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==}
engines: {node: '>= 0.6'}
@ -512,10 +505,6 @@ packages:
resolution: {integrity: sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==}
engines: {node: '>=8'}
anymatch@3.1.3:
resolution: {integrity: sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==}
engines: {node: '>= 8'}
array-flatten@1.1.1:
resolution: {integrity: sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==}
@ -530,9 +519,6 @@ packages:
engines: {node: '>= 4.5.0'}
hasBin: true
balanced-match@1.0.2:
resolution: {integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==}
base64-js@1.5.1:
resolution: {integrity: sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==}
@ -540,10 +526,6 @@ packages:
resolution: {integrity: sha512-NF+epuEdnUYVlGuhaxbbq+dvJttwLnGY+YixlXlME5KpQ5W3CnXA5cVTneY3SPbPDRkcjMbifrwmFYcClgOZeg==}
engines: {node: '>= 0.8'}
binary-extensions@2.3.0:
resolution: {integrity: sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==}
engines: {node: '>=8'}
bintrees@1.0.2:
resolution: {integrity: sha512-VOMgTMwjAaUG580SXn3LacVgjurrbMme7ZZNYGSSV7mmtY6QQRh0Eg3pwIcntQ77DErK1L0NxkbetjcoXzVwKw==}
@ -561,13 +543,6 @@ packages:
bowser@2.11.0:
resolution: {integrity: sha512-AlcaJBi/pqqJBIQ8U9Mcpc9i8Aqxn88Skv5d+xBX006BY5u8N3mGLHa5Lgppa7L/HfwgwLgZ6NYs+Ag6uUmJRA==}
brace-expansion@1.1.11:
resolution: {integrity: sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==}
braces@3.0.2:
resolution: {integrity: sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==}
engines: {node: '>=8'}
brorand@1.1.0:
resolution: {integrity: sha512-cKV8tMCEpQs4hK/ik71d6LrPOnpkpGBR0wzxqr68g2m/LB2GxVYQroAjMJZRVM1Y4BCjCKc3vAamxSzOY2RP+w==}
@ -600,10 +575,6 @@ packages:
resolution: {integrity: sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==}
engines: {node: '>=10'}
chokidar@3.6.0:
resolution: {integrity: sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==}
engines: {node: '>= 8.10.0'}
clone-response@1.0.3:
resolution: {integrity: sha512-ROoL94jJH2dUVML2Y/5PEDNaSHgeOdSDicUyS7izcF63G6sTc/FTjLub4b8Il9S8S0beOfYt0TaA5qvFK+w0wA==}
@ -629,9 +600,6 @@ packages:
resolution: {integrity: sha512-gk/Z852D2Wtb//0I+kRFNKKE9dIIVirjoqPoA1wJU+XePVXZfGeBpk45+A1rKO4Q43prqWBNY/MiIeRLbPWUaA==}
engines: {node: '>=4.0.0'}
concat-map@0.0.1:
resolution: {integrity: sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==}
connect-redis@7.1.0:
resolution: {integrity: sha512-UaqO1EirWjON2ENsyau7N5lbkrdYBpS6mYlXSeff/OYXsd6EGZ+SXSmNPoljL2PSua8fgjAEaldSA73PMZQ9Eg==}
engines: {node: '>=16'}
@ -811,10 +779,6 @@ packages:
resolution: {integrity: sha512-B9/wizE4WngqQftFPmdaMYlXoJlJOYxGQOanC77fq9k8+Z0v5dDSVh+3glErdIROP//s/jgb7ZuxKfB8nVyo0g==}
hasBin: true
fill-range@7.0.1:
resolution: {integrity: sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==}
engines: {node: '>=8'}
finalhandler@1.2.0:
resolution: {integrity: sha512-5uXcUVftlQMFnWC9qu/svkWv3GTd2PfUhK/3PLkYNAe7FbqJMt3515HaxE6eRL74GdsriiwujiawdaB1BpEISg==}
engines: {node: '>= 0.8'}
@ -831,11 +795,6 @@ packages:
resolution: {integrity: sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==}
engines: {node: '>= 0.6'}
fsevents@2.3.3:
resolution: {integrity: sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==}
engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0}
os: [darwin]
function-bind@1.1.2:
resolution: {integrity: sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==}
@ -851,10 +810,6 @@ packages:
resolution: {integrity: sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA==}
engines: {node: '>=8'}
glob-parent@5.1.2:
resolution: {integrity: sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==}
engines: {node: '>= 6'}
gopd@1.0.1:
resolution: {integrity: sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==}
@ -869,10 +824,6 @@ packages:
resolution: {integrity: sha512-QaoZudI9Gmh2W415gd71Iul6gpVH9sG1SkjfnGHtqYZopQDQ5PUVxRol5zFCrwGi9S0EbExbelHlZScgdChg2w==}
engines: {node: '>=12.0.0'}
has-flag@3.0.0:
resolution: {integrity: sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==}
engines: {node: '>=4'}
has-flag@4.0.0:
resolution: {integrity: sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==}
engines: {node: '>=8'}
@ -920,9 +871,6 @@ packages:
ieee754@1.2.1:
resolution: {integrity: sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==}
ignore-by-default@1.0.1:
resolution: {integrity: sha512-Ius2VYcGNk7T90CppJqcIkS5ooHUZyIQK+ClZfMfMNFEF9VSE73Fq+906u/CWu92x4gzZMWOwfFYckPObzdEbA==}
inherits@2.0.4:
resolution: {integrity: sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==}
@ -934,26 +882,10 @@ packages:
resolution: {integrity: sha512-LlbxQ7xKzfBusov6UMi4MFpEg0m+mAm9xyNGEduwXMEDuf4WfzB/RZwMVYEd7IKGvh4IUkEXYxtAVu9T3OelJQ==}
engines: {node: '>= 10'}
is-binary-path@2.1.0:
resolution: {integrity: sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==}
engines: {node: '>=8'}
is-extglob@2.1.1:
resolution: {integrity: sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==}
engines: {node: '>=0.10.0'}
is-glob@4.0.3:
resolution: {integrity: sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==}
engines: {node: '>=0.10.0'}
is-nan@1.3.2:
resolution: {integrity: sha512-E+zBKpQ2t6MEo1VsonYmluk9NxGrbzpeeLC2xIViuO2EjU2xsXsBPwTr3Ykv9l08UYEVEdWeRZNouaZqF6RN0w==}
engines: {node: '>= 0.4'}
is-number@7.0.0:
resolution: {integrity: sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==}
engines: {node: '>=0.12.0'}
is-stream@2.0.1:
resolution: {integrity: sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==}
engines: {node: '>=8'}
@ -1107,9 +1039,6 @@ packages:
minimalistic-crypto-utils@1.0.1:
resolution: {integrity: sha512-JIYlbt6g8i5jKfJ3xz7rF0LXmv2TkDxBLUkiBeZ7bAx4GnnNMr8xFpGnOxn6GhTEHx3SjRrZEoU+j04prX1ktg==}
minimatch@3.1.2:
resolution: {integrity: sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==}
moment-timezone@0.5.45:
resolution: {integrity: sha512-HIWmqA86KcmCAhnMAN0wuDOARV/525R2+lOLotuGFzn4HO+FH+/645z2wx0Dt3iDv6/p61SIvKnDstISainhLQ==}
@ -1145,19 +1074,6 @@ packages:
resolution: {integrity: sha512-nl4JTiZ7ZQDc97MmpTq9BQjYhq7gOtoh7SiPH069gBFBj0PzD8HI7zyFs6rzqL8Y5tTiEEYLxgtbx034YPrbyQ==}
engines: {node: '>=6'}
nodemon@3.1.0:
resolution: {integrity: sha512-xqlktYlDMCepBJd43ZQhjWwMw2obW/JRvkrLxq5RCNcuDDX1DbcPT+qT1IlIIdf+DhnWs90JpTMe+Y5KxOchvA==}
engines: {node: '>=10'}
hasBin: true
nopt@1.0.10:
resolution: {integrity: sha512-NWmpvLSqUrgrAC9HCuxEvb+PSloHpqVu+FqcO4eeF2h5qYRhA7ev6KvelyQAKtegUbC6RypJnlEOhd8vloNKYg==}
hasBin: true
normalize-path@3.0.0:
resolution: {integrity: sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==}
engines: {node: '>=0.10.0'}
normalize-url@6.1.0:
resolution: {integrity: sha512-DlL+XwOy3NxAQ8xuC0okPgK46iuVNAK01YN7RueYBqqFeGsBjV9XmCAzAdgt+667bCl5kPh9EqKKDwnaPG1I7A==}
engines: {node: '>=10'}
@ -1202,10 +1118,6 @@ packages:
path-to-regexp@0.1.7:
resolution: {integrity: sha512-5DFkuoqlv1uYQKxy8omFBeJPQcdoE07Kv2sferDCrAq1ohOU+MSDswDIbnx3YAM60qIOnYa53wBhXW0EbMonrQ==}
picomatch@2.3.1:
resolution: {integrity: sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==}
engines: {node: '>=8.6'}
preact@10.20.2:
resolution: {integrity: sha512-S1d1ernz3KQ+Y2awUxKakpfOg2CEmJmwOP+6igPx6dgr6pgDvenqYviyokWso2rhHvGtTlWWnJDa7RaPbQerTg==}
@ -1223,9 +1135,6 @@ packages:
pseudomap@1.0.2:
resolution: {integrity: sha512-b/YwNhb8lk1Zz2+bXXpS/LK9OisiZZ1SNsSLxN1x2OXVEhW2Ckr/7mWE5vrC1ZTiJlD9g19jWszTmJsB+oEpFQ==}
pstree.remy@1.1.8:
resolution: {integrity: sha512-77DZwxQmxKnu3aR542U+X8FypNzbfJ+C5XQDk3uWjWxn6151aIMGthWYRXTqT1E5oJvg+ljaa2OJi+VfvCOQ8w==}
pump@3.0.0:
resolution: {integrity: sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==}
@ -1281,10 +1190,6 @@ packages:
resolution: {integrity: sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==}
engines: {node: '>= 6'}
readdirp@3.6.0:
resolution: {integrity: sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==}
engines: {node: '>=8.10.0'}
redis@4.2.0:
resolution: {integrity: sha512-bCR0gKVhIXFg8zCQjXEANzgI01DDixtPZgIUZHBCmwqixnu+MK3Tb2yqGjh+HCLASQVVgApiwhNkv+FoedZOGQ==}
@ -1352,10 +1257,6 @@ packages:
signal-exit@3.0.7:
resolution: {integrity: sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==}
simple-update-notifier@2.0.0:
resolution: {integrity: sha512-a2B9Y0KlNXl9u/vsW6sTIu9vGEpfKu2wRV6l1H3XEas/0gUIzGzBoP/IouTcUQbm9JWZLH3COxyn03TYlFax6w==}
engines: {node: '>=10'}
sorted-array-functions@1.3.0:
resolution: {integrity: sha512-2sqgzeFlid6N4Z2fUQ1cvFmTOLRi/sEDzSQ0OKYchqgoPmQBVyM3959qYx3fpS6Esef80KjmpgPeEr028dP3OA==}
@ -1372,10 +1273,6 @@ packages:
strnum@1.0.5:
resolution: {integrity: sha512-J8bbNyKKXl5qYcR36TIO8W3mVGVHrmmxsd5PAItGkmyzwJvybiw2IVq5nqd0i4LSNSkB/sx9VHllbfFdr9k1JA==}
supports-color@5.5.0:
resolution: {integrity: sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==}
engines: {node: '>=4'}
supports-color@7.2.0:
resolution: {integrity: sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==}
engines: {node: '>=8'}
@ -1383,18 +1280,10 @@ packages:
tdigest@0.1.2:
resolution: {integrity: sha512-+G0LLgjjo9BZX2MfdvPfH+MKLCrxlXSYec5DaPYP1fe6Iyhf0/fSmJ0bFiZ1F8BT6cGXl2LpltQptzjXKWEkKA==}
to-regex-range@5.0.1:
resolution: {integrity: sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==}
engines: {node: '>=8.0'}
toidentifier@1.0.1:
resolution: {integrity: sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==}
engines: {node: '>=0.6'}
touch@3.1.0:
resolution: {integrity: sha512-WBx8Uy5TLtOSRtIq+M03/sKDrXCLHxwDcquSP2c43Le03/9serjQBIztjRz6FkJez9D/hleyAXTBGLwwZUw9lA==}
hasBin: true
tslib@1.14.1:
resolution: {integrity: sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==}
@ -1412,9 +1301,6 @@ packages:
resolution: {integrity: sha512-KPHm4VL5dDXKz01UuEd88Df+KzynaohSL9fBh096KWAxSKZQDI2uBrVqtvRM4rwrIrRRKsdLNML/lnaaVSRioA==}
engines: {node: '>= 0.8'}
undefsafe@2.0.5:
resolution: {integrity: sha512-WxONCrssBM8TSPRqN5EmsjVrsv4A8X12J4ArBiiayv3DyyG3ZlIg6yysuuSYdZsVz3TKcTg2fd//Ujd4CHV1iA==}
undici-types@5.26.5:
resolution: {integrity: sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==}
@ -2477,8 +2363,6 @@ snapshots:
dependencies:
lodash.throttle: 4.1.1
abbrev@1.1.1: {}
accepts@1.3.8:
dependencies:
mime-types: 2.1.35
@ -2488,11 +2372,6 @@ snapshots:
dependencies:
color-convert: 2.0.1
anymatch@3.1.3:
dependencies:
normalize-path: 3.0.0
picomatch: 2.3.1
array-flatten@1.1.1: {}
asn1.js@5.4.1:
@ -2507,16 +2386,12 @@ snapshots:
atob@2.1.2: {}
balanced-match@1.0.2: {}
base64-js@1.5.1: {}
basic-auth@2.0.1:
dependencies:
safe-buffer: 5.1.2
binary-extensions@2.3.0: {}
bintrees@1.0.2: {}
bn.js@4.12.0:
@ -2558,15 +2433,6 @@ snapshots:
bowser@2.11.0: {}
brace-expansion@1.1.11:
dependencies:
balanced-match: 1.0.2
concat-map: 0.0.1
braces@3.0.2:
dependencies:
fill-range: 7.0.1
brorand@1.1.0:
optional: true
@ -2606,18 +2472,6 @@ snapshots:
ansi-styles: 4.3.0
supports-color: 7.2.0
chokidar@3.6.0:
dependencies:
anymatch: 3.1.3
braces: 3.0.2
glob-parent: 5.1.2
is-binary-path: 2.1.0
is-glob: 4.0.3
normalize-path: 3.0.0
readdirp: 3.6.0
optionalDependencies:
fsevents: 2.3.3
clone-response@1.0.3:
dependencies:
mimic-response: 1.0.1
@ -2641,8 +2495,6 @@ snapshots:
common-tags@1.8.2: {}
concat-map@0.0.1: {}
connect-redis@7.1.0(express-session@1.17.3):
dependencies:
express-session: 1.17.3
@ -2689,10 +2541,9 @@ snapshots:
dependencies:
ms: 2.0.0
debug@4.3.4(supports-color@5.5.0):
debug@4.3.4:
dependencies:
ms: 2.1.2
supports-color: 5.5.0
decompress-response@6.0.0:
dependencies:
@ -2877,10 +2728,6 @@ snapshots:
dependencies:
strnum: 1.0.5
fill-range@7.0.1:
dependencies:
to-regex-range: 5.0.1
finalhandler@1.2.0:
dependencies:
debug: 2.6.9
@ -2903,9 +2750,6 @@ snapshots:
fresh@0.5.2: {}
fsevents@2.3.3:
optional: true
function-bind@1.1.2: {}
generic-pool@3.8.2: {}
@ -2922,10 +2766,6 @@ snapshots:
dependencies:
pump: 3.0.0
glob-parent@5.1.2:
dependencies:
is-glob: 4.0.3
gopd@1.0.1:
dependencies:
get-intrinsic: 1.2.4
@ -2957,8 +2797,6 @@ snapshots:
jwk-to-pem: 2.0.5
jws: 4.0.0
has-flag@3.0.0: {}
has-flag@4.0.0: {}
has-property-descriptors@1.0.2:
@ -3009,31 +2847,17 @@ snapshots:
ieee754@1.2.1: {}
ignore-by-default@1.0.1: {}
inherits@2.0.4: {}
ipaddr.js@1.9.1: {}
ipaddr.js@2.1.0: {}
is-binary-path@2.1.0:
dependencies:
binary-extensions: 2.3.0
is-extglob@2.1.1: {}
is-glob@4.0.3:
dependencies:
is-extglob: 2.1.1
is-nan@1.3.2:
dependencies:
call-bind: 1.0.7
define-properties: 1.2.1
is-number@7.0.0: {}
is-stream@2.0.1: {}
js-base64@3.7.7: {}
@ -3162,7 +2986,7 @@ snapshots:
memorystore@1.6.7:
dependencies:
debug: 4.3.4(supports-color@5.5.0)
debug: 4.3.4
lru-cache: 4.1.5
transitivePeerDependencies:
- supports-color
@ -3193,10 +3017,6 @@ snapshots:
minimalistic-crypto-utils@1.0.1:
optional: true
minimatch@3.1.2:
dependencies:
brace-expansion: 1.1.11
moment-timezone@0.5.45:
dependencies:
moment: 2.30.1
@ -3231,25 +3051,6 @@ snapshots:
long-timeout: 0.1.1
sorted-array-functions: 1.3.0
nodemon@3.1.0:
dependencies:
chokidar: 3.6.0
debug: 4.3.4(supports-color@5.5.0)
ignore-by-default: 1.0.1
minimatch: 3.1.2
pstree.remy: 1.1.8
semver: 7.6.0
simple-update-notifier: 2.0.0
supports-color: 5.5.0
touch: 3.1.0
undefsafe: 2.0.5
nopt@1.0.10:
dependencies:
abbrev: 1.1.1
normalize-path@3.0.0: {}
normalize-url@6.1.0: {}
oauth-sign@0.9.0: {}
@ -3280,8 +3081,6 @@ snapshots:
path-to-regexp@0.1.7: {}
picomatch@2.3.1: {}
preact@10.20.2: {}
prom-client@14.0.1:
@ -3301,8 +3100,6 @@ snapshots:
pseudomap@1.0.2: {}
pstree.remy@1.1.8: {}
pump@3.0.0:
dependencies:
end-of-stream: 1.4.4
@ -3360,10 +3157,6 @@ snapshots:
string_decoder: 1.3.0
util-deprecate: 1.0.2
readdirp@3.6.0:
dependencies:
picomatch: 2.3.1
redis@4.2.0:
dependencies:
'@redis/bloom': 1.0.2(@redis/client@1.2.0)
@ -3454,10 +3247,6 @@ snapshots:
signal-exit@3.0.7: {}
simple-update-notifier@2.0.0:
dependencies:
semver: 7.6.0
sorted-array-functions@1.3.0: {}
statuses@2.0.1: {}
@ -3473,10 +3262,6 @@ snapshots:
strnum@1.0.5: {}
supports-color@5.5.0:
dependencies:
has-flag: 3.0.0
supports-color@7.2.0:
dependencies:
has-flag: 4.0.0
@ -3485,16 +3270,8 @@ snapshots:
dependencies:
bintrees: 1.0.2
to-regex-range@5.0.1:
dependencies:
is-number: 7.0.0
toidentifier@1.0.1: {}
touch@3.1.0:
dependencies:
nopt: 1.0.10
tslib@1.14.1: {}
tslib@2.6.2: {}
@ -3518,8 +3295,6 @@ snapshots:
dependencies:
random-bytes: 1.0.0
undefsafe@2.0.5: {}
undici-types@5.26.5: {}
unpipe@1.0.0: {}

View File

@ -25,13 +25,45 @@ EOF
# --from-literal=username=${TRAEFIK_USERNAME} \
# --from-literal=password=${TRAEFIK_PASSWORD}
# kubectl --namespace futureporn delete secret uppy --ignore-not-found
# kubectl --namespace futureporn create secret generic uppy \
# --from-literal=driveKey=${UPPY_DRIVE_KEY} \
# --from-literal=driveSecret=${UPPY_DRIVE_SECRET} \
# --from-literal=dropboxKey=${UPPY_DROPBOX_KEY} \
# --from-literal=dropboxSecret=${UPPY_DROPBOX_SECRET} \
# --from-literal=jwtSecret=${UPPY_JWT_SECRET} \
# --from-literal=secret=${UPPY_SECRET} \
# --from-literal=sessionSecret=${UPPY_SESSION_SECRET} \
# --from-literal=b2Key=${UPPY_B2_KEY} \
# --from-literal=b2Secret=${UPPY_B2_SECRET}\
kubectl --namespace futureporn delete secret redis --ignore-not-found
kubectl --namespace futureporn create secret generic redis \
--from-literal=password=${REDIS_PASSWORD}
kubectl --namespace futureporn delete secret uppy --ignore-not-found
kubectl --namespace futureporn create secret generic uppy \
--from-literal=redisUrl=${COMPANION_REDIS_URL} \
--from-literal=secret=${COMPANION_SECRET} \
--from-literal=preAuthSecret=${COMPANION_PREAUTH_SECRET} \
--from-literal=dropboxKey=${COMPANION_DROPBOX_KEY} \
--from-literal=dropboxSecret=${COMPANION_DROPBOX_SECRET} \
--from-literal=boxKey=${COMPANION_BOX_KEY} \
--from-literal=boxSecret=${COMPANION_BOX_SECRET} \
--from-literal=googleKey=${COMPANION_GOOGLE_KEY} \
--from-literal=googleSecret=${COMPANION_GOOGLE_SECRET} \
--from-literal=awsKey=${COMPANION_AWS_KEY} \
--from-literal=awsSecret=${COMPANION_AWS_SECRET} \
--from-literal=awsBucket=${COMPANION_AWS_BUCKET} \
--from-literal=oauthDomain=${COMPANION_OAUTH_DOMAIN} \
--from-literal=uploadUrls=${COMPANION_UPLOAD_URLS}
## @todo we need exoscale in two separate namespaces.
## Is it worth using secrets reflector?
kubectl --namespace cert-manager delete secret exoscale --ignore-not-found
kubectl --namespace cert-manager create secret generic exoscale \
--from-literal=apiKey=${EXOSCALE_API_KEY} \
--from-literal=apiSecret=${EXOSCALE_API_SECRET}
## @todo we need exoscale in two separate namespaces.
## Is it worth using secrets reflector?
kubectl --namespace futureporn delete secret exoscale --ignore-not-found
kubectl --namespace futureporn create secret generic exoscale \
--from-literal=apiKey=${EXOSCALE_API_KEY} \

View File

@ -1,6 +1,6 @@
#!/bin/bash
dbname=2024-06-19_22-24-03-futureporn-db.psql
dbname=20240704T204659Z_development.psql
## drop futureporn_db
kubectl -n futureporn exec postgres -- psql -U postgres --command "DROP DATABASE futureporn_db;"