add /account settings
This commit is contained in:
parent
a05bf6de74
commit
fe1f318424
3
.vscode/extensions.json
vendored
3
.vscode/extensions.json
vendored
@ -3,6 +3,7 @@
|
||||
"redhat.vscode-yaml",
|
||||
"jetify.devbox",
|
||||
"redhat.ansible",
|
||||
"dotjoshjohnson.xml"
|
||||
"dotjoshjohnson.xml",
|
||||
"j69.ejs-beautify"
|
||||
]
|
||||
}
|
||||
@ -59,4 +59,7 @@ In other words, pick something for a name and roll with the punches.
|
||||
|
||||
### Do what you can, with what you have, where you are at
|
||||
|
||||
### Use it up, wear it out, make it do, or do without
|
||||
### Use it up, wear it out, make it do, or do without
|
||||
|
||||
### [Just Culture](https://pilotswhoaskwhy.com/2023/05/15/the-power-of-just-culture-killing-the-blame-game/)
|
||||
|
||||
|
||||
@ -80,6 +80,9 @@ model Vod {
|
||||
sourceAudioCodec String?
|
||||
sourceVideoFps Float?
|
||||
|
||||
muxAssetId String?
|
||||
muxPlaybackId String?
|
||||
|
||||
// audio analysis
|
||||
audioIntegratedLufs Float? // Integrated loudness (LUFS-I)
|
||||
audioLoudnessRange Float? // Loudness Range (LRA)
|
||||
|
||||
5
services/pocketbase/.gitignore
vendored
Normal file
5
services/pocketbase/.gitignore
vendored
Normal file
@ -0,0 +1,5 @@
|
||||
.ftp-deploy-sync-state.json
|
||||
node_modules
|
||||
pb_data
|
||||
.DS_Store
|
||||
.secrets
|
||||
1
services/pocketbase/CHANGELOG.md
Normal file
1
services/pocketbase/CHANGELOG.md
Normal file
@ -0,0 +1 @@
|
||||
# pocketpages-starter-datastar
|
||||
94
services/pocketbase/README.md
Normal file
94
services/pocketbase/README.md
Normal file
@ -0,0 +1,94 @@
|
||||
# Datastar Starter Kit
|
||||
|
||||
This starter kit demonstrates how to build realtime web applications using [Datastar](https://github.com/starfederation/datastar) with PocketPages. It includes a live chat demo and counter example.
|
||||
|
||||
## Features
|
||||
|
||||
- Realtime chat with emoji avatars
|
||||
- Live counter with instant updates
|
||||
- Datastar signal management
|
||||
- Server-sent events (SSE) integration
|
||||
- Modern UI with Tailwind CSS
|
||||
|
||||
## Installation
|
||||
|
||||
```bash
|
||||
npx tiged benallfree/pocketpages/packages/starters/datastar .
|
||||
cd datastar
|
||||
npm i
|
||||
pocketbase serve --dir=pb_data --dev
|
||||
```
|
||||
|
||||
## Setup
|
||||
|
||||
The starter kit is pre-configured with the required Datastar setup:
|
||||
|
||||
1. **Plugin Configuration** (`+config.js`): Includes the datastar plugin
|
||||
2. **Script Injection** (`+layout.ejs`): Includes `<%- datastar.scripts() %>` in the `<head>` section
|
||||
3. **Realtime Integration**: Configured for realtime updates
|
||||
|
||||
## Usage
|
||||
|
||||
1. Start the server and visit `http://127.0.0.1:8090`
|
||||
2. Open multiple browser tabs to see realtime updates
|
||||
3. Send messages in the chat to see them appear instantly across all tabs
|
||||
4. Click the counter button to see live updates
|
||||
|
||||
## Key Components
|
||||
|
||||
- **Chat System**: Real-time messaging with random emoji avatars
|
||||
- **Counter**: Simple state management with live updates
|
||||
- **Datastar Integration**: Server-side signal reading and client-side binding
|
||||
- **Realtime Broadcasting**: Updates sent to all connected clients
|
||||
|
||||
## Datastar Features Demonstrated
|
||||
|
||||
- `datastar.patchElements()` - DOM updates
|
||||
- `datastar.patchSignals()` - Signal management
|
||||
- `datastar.readSignals()` - Form data reading
|
||||
- `datastar.realtime.*` - Broadcasting to all clients
|
||||
- Client-side data binding with `data-bind-*` attributes
|
||||
- Event handling with `data-on-click` attributes
|
||||
|
||||
|
||||
|
||||
## dev notes
|
||||
|
||||
### S3 has some jenk
|
||||
|
||||
cache s3 requests at the proxy level
|
||||
https://github.com/pocketbase/pocketbase/issues/28#issuecomment-1492516269
|
||||
https://github.com/pocketbase/pocketbase/discussions/4332#discussioncomment-8450890
|
||||
|
||||
|
||||
### search
|
||||
|
||||
https://www.meilisearch.com/
|
||||
|
||||
|
||||
### horizontal scaling
|
||||
|
||||
https://github.com/fondoger/pocketbase (pg fork)
|
||||
https://github.com/litesql/pocketbase-ha
|
||||
|
||||
|
||||
### Data migrations
|
||||
|
||||
https://github.com/pocketbase/pocketbase/discussions/2836#discussioncomment-6340103
|
||||
|
||||
|
||||
### FTS
|
||||
|
||||
https://github.com/pocketbuilds/fts?tab=readme-ov-file#readme
|
||||
|
||||
|
||||
### plugins
|
||||
|
||||
https://pocketbuilds.com/
|
||||
|
||||
|
||||
## Deployments
|
||||
|
||||
how the pros do it
|
||||
|
||||
https://github.com/benallfree/pocketpages/blob/5bc48d4f8df75b2f78ca61fa18c792d814b926e8/packages/starters/deploy-pockethost-manual/deploy-pockethost.ts#L5
|
||||
2868
services/pocketbase/package-lock.json
generated
Normal file
2868
services/pocketbase/package-lock.json
generated
Normal file
File diff suppressed because it is too large
Load Diff
25
services/pocketbase/package.json
Normal file
25
services/pocketbase/package.json
Normal file
@ -0,0 +1,25 @@
|
||||
{
|
||||
"name": "futureporn",
|
||||
"version": "3.0.3",
|
||||
"private": true,
|
||||
"description": "Dedication to the preservation of lewdtuber history",
|
||||
"license": "Unlicense",
|
||||
"scripts": {
|
||||
"deploy": "phio deploy"
|
||||
},
|
||||
"dependencies": {
|
||||
"jsonwebtoken": "^9.0.2",
|
||||
"pg": "^8.16.3",
|
||||
"pocketpages": ">=0.22.3",
|
||||
"pocketpages-plugin-auth": "^0.2.2",
|
||||
"pocketpages-plugin-datastar": ">=0.2.0",
|
||||
"pocketpages-plugin-micro-dash": "^0.1.0"
|
||||
},
|
||||
"files": [
|
||||
"pb_hooks",
|
||||
"*.md"
|
||||
],
|
||||
"devDependencies": {
|
||||
"phio": "^0.3.5"
|
||||
}
|
||||
}
|
||||
37
services/pocketbase/pb_hooks/import.pb.js
Normal file
37
services/pocketbase/pb_hooks/import.pb.js
Normal file
@ -0,0 +1,37 @@
|
||||
/// <reference path="../pb_data/types.d.ts" />
|
||||
|
||||
// @see https://github.com/pocketbase/pocketbase/discussions/6287
|
||||
|
||||
// NOTE: this script must be run from the project root
|
||||
// ./pocketbase import /path/to/your/data.json YOUR_COLLECTION
|
||||
$app.rootCmd.addCommand(new Command({
|
||||
use: "import",
|
||||
run: (cmd, args) => {
|
||||
const data = require(args[0])
|
||||
|
||||
const collection = $app.findCollectionByNameOrId(args[1]);
|
||||
// console.log(`data`, data, 'collection', collection);
|
||||
|
||||
$app.runInTransaction((txApp) => {
|
||||
let record;
|
||||
for (let item of data) {
|
||||
// check https://pocketbase.io/docs/js-records/
|
||||
record = new Record(collection)
|
||||
|
||||
// bulk set the item field values
|
||||
//
|
||||
// note: if you want to set predefined values for "autodate" type fields
|
||||
// you'll need to manually load them with record.setRaw("created", val)
|
||||
record.load(item)
|
||||
|
||||
// call txApp.saveNoValidate for better performance
|
||||
// but be aware that the fields validators will be skipped and could result in data integrity issues
|
||||
// if you haven't checked and verified the imported data beforehand
|
||||
txApp.save(record)
|
||||
}
|
||||
})
|
||||
},
|
||||
}))
|
||||
|
||||
|
||||
|
||||
80
services/pocketbase/pb_hooks/pages/(site)/+layout.ejs
Normal file
80
services/pocketbase/pb_hooks/pages/(site)/+layout.ejs
Normal file
@ -0,0 +1,80 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en" class="h-full">
|
||||
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||
<title>
|
||||
<%=meta('title') || '~~~~~' %>
|
||||
</title>
|
||||
<meta name="description" content="<%=meta('description') || 'aaaaa'%>" />
|
||||
<meta property="og:title" content="<%=meta('title') || 'Futureporn.net'%>" />
|
||||
<meta property="og:description" content="<%=meta('description') %>" />
|
||||
<meta property="og:image" content="<%=meta('image') || '/android-chrome-512x512.png'%>" />
|
||||
<meta property="og:url" content="<%=meta('path') ? `${meta('path')}` : meta('url') || `${request.url}`%>" />
|
||||
<meta name="RATING" content="RTA-5042-1996-1400-1577-RTA" />
|
||||
|
||||
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bulma@1.0.4/css/bulma.min.css">
|
||||
<link rel="alternate" type="application/rss+xml" title="Futureporn VODs (RSS)" href="/vods/feed.xml">
|
||||
<link rel="alternate" type="application/rss+xml" title="Futureporn VODs (Atom)" href="/vods/rss.xml">
|
||||
<link rel="alternate" type="application/json" title="Futureporn VODs" href="/vods/feed.json">
|
||||
|
||||
|
||||
<%- slots.head %> <%- datastar.scripts({realtime: true}) %>
|
||||
</head>
|
||||
|
||||
<body class="h-full bg-gradient-to-br from-slate-50 via-blue-50 to-indigo-100 font-sans antialiased">
|
||||
<div class="min-h-full flex flex-col">
|
||||
<main class="flex-1 container mx-auto px-4 py-8 sm:px-6 lg:px-8">
|
||||
<div class="max-w-4xl mx-auto">
|
||||
<div class="space-y-8">
|
||||
<!-- Header Section -->
|
||||
<nav class="level">
|
||||
<!-- Left side -->
|
||||
<div class="level-left">
|
||||
<div class="level-item">
|
||||
<p class="subtitle is-5"><a href="/"><strong>Futureporn.net</strong></a></p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="level-right">
|
||||
<% if (auth) { %>
|
||||
<div class="level-item">
|
||||
<a href="/account">Account</a>
|
||||
</div>
|
||||
<div class="level-item">
|
||||
<a href="/auth/logout">Logout</a>
|
||||
</div>
|
||||
<% } else { %>
|
||||
<div class="level-item">
|
||||
<a href="/auth/login">Login</a>
|
||||
</div>
|
||||
<% } %>
|
||||
</div>
|
||||
|
||||
</nav>
|
||||
|
||||
<div class="notification is-info" data-signals='{"showNotif": false}' data-show="$showNotif">
|
||||
<button class="delete" data-on-click="$showNotif = false"></button>
|
||||
<span data-text="$message"></span>
|
||||
</div>
|
||||
|
||||
|
||||
<%- slots.body || slot%>
|
||||
</div>
|
||||
</div>
|
||||
</main>
|
||||
|
||||
|
||||
|
||||
<footer class="footer mt-5">
|
||||
<div class="content has-text-centered">
|
||||
<p>
|
||||
<strong>Futureporn <%= data.version %></strong> made with love by <a href="https://t.co/I8p0oH0AAB">@CJ_Clippy</a>.
|
||||
</p>
|
||||
</div>
|
||||
</footer>
|
||||
|
||||
</div>
|
||||
</body>
|
||||
|
||||
</html>
|
||||
31
services/pocketbase/pb_hooks/pages/(site)/+middleware.js
Normal file
31
services/pocketbase/pb_hooks/pages/(site)/+middleware.js
Normal file
@ -0,0 +1,31 @@
|
||||
/** @type {import('pocketpages').PageDataLoaderFunc} */
|
||||
module.exports = function ({ meta, redirect, request, auth }) {
|
||||
meta('title', 'Futureporn.net')
|
||||
meta('description', 'Dedication to the preservation of Lewdtuber history')
|
||||
meta('image', 'https://example.com/about-preview.jpg')
|
||||
|
||||
const cookies = request.cookies()
|
||||
// console.log('cookies as follows')
|
||||
// console.log(JSON.stringify(cookies))
|
||||
// console.log('auth as follows')
|
||||
// console.log(auth)
|
||||
|
||||
let user;
|
||||
|
||||
if (auth) {
|
||||
console.log('request.auth is present id:', auth.get('id'))
|
||||
user = $app.findFirstRecordByData('users', 'id', auth.id);
|
||||
}
|
||||
|
||||
return { user, version: require(`../../../package.json`).version }
|
||||
}
|
||||
|
||||
// module.exports = (api, next) => {
|
||||
// const { auth, redirect } = api
|
||||
// if (!auth) {
|
||||
// return redirect('/auth/login', {
|
||||
// message: 'You must be logged in to access this page',
|
||||
// })
|
||||
// }
|
||||
// next()
|
||||
// }
|
||||
@ -0,0 +1,9 @@
|
||||
module.exports = (api, next) => {
|
||||
const { auth, redirect } = api
|
||||
if (!auth) {
|
||||
return redirect('/auth/login', {
|
||||
message: 'You must be logged in to access this page',
|
||||
})
|
||||
}
|
||||
next()
|
||||
}
|
||||
36
services/pocketbase/pb_hooks/pages/(site)/account/index.ejs
Normal file
36
services/pocketbase/pb_hooks/pages/(site)/account/index.ejs
Normal file
@ -0,0 +1,36 @@
|
||||
<h2 class="title is-2">Account Overview</h2>
|
||||
<p>Welcome back, <strong><%= auth.get('name') %></strong>.</p>
|
||||
|
||||
<h3 class="title is-3 mt-5">Patreon Information</h3>
|
||||
|
||||
<div class="notification is-info is-light">
|
||||
Please note: Patron status updates may take up to one minute to synchronize.
|
||||
</div>
|
||||
|
||||
<p>
|
||||
<strong>Role:</strong>
|
||||
<% if (auth.get('patron')) { %>
|
||||
Patron
|
||||
<% } else { %>
|
||||
Not a Patron
|
||||
<a class="ml-3" target="_blank" href="https://patreon.com/cj_clippy">Become a Patron</a>
|
||||
<% } %>
|
||||
</p>
|
||||
|
||||
<p><strong>Patreon ID:</strong> <%= auth.get('patreonId') %></p>
|
||||
|
||||
|
||||
<div class="mt-5">
|
||||
<h3 class="title is-3">Account Settings</h3>
|
||||
|
||||
<label class="checkbox">
|
||||
<input class="checkbox" type="checkbox" name="publicUsername" data-bind="publicUsername" data-on-input__debounce.300ms.leading="@patch('/api/user/settings')">
|
||||
Show <%= auth.get('name') %> on the <a href="/patrons">patrons page</a>
|
||||
</label>
|
||||
|
||||
<div id="results" class="mt-5"></div>
|
||||
|
||||
<!-- <br />
|
||||
<input class="button" type="submit" value="Save" /> -->
|
||||
|
||||
</div>
|
||||
@ -0,0 +1,30 @@
|
||||
<script server>
|
||||
let error = null
|
||||
const methods = pb().collection('users').listAuthMethods();
|
||||
dbg({
|
||||
methods
|
||||
})
|
||||
|
||||
const {
|
||||
providers
|
||||
} = methods.oauth2
|
||||
</script>
|
||||
|
||||
|
||||
<% if (error) { %>
|
||||
<mark><%= error %></mark>
|
||||
<% } %>
|
||||
|
||||
<% if (!methods.oauth2.enabled) { %>
|
||||
<mark>OAuth2 login is disabled. See README.md for details.</mark>
|
||||
<% } else {%>
|
||||
<% providers.forEach(provider => { %>
|
||||
<form method="POST" action="/auth/oauth/login">
|
||||
<input type="hidden" name="provider" value="<%=provider.name%>">
|
||||
<button class="button" type="submit">Log in with <%=provider.displayName%></button>
|
||||
</form>
|
||||
<% }) %>
|
||||
<% if (providers.length === 0) { %>
|
||||
<mark>No OAuth2 providers enabled. See README.md for details.</mark>
|
||||
<% } %>
|
||||
<% } %>
|
||||
@ -0,0 +1,8 @@
|
||||
<h2 class="title is-2">Login</h2>
|
||||
|
||||
<p>Log in to Futureporn using a Patreon account.</p>
|
||||
<p>Logging in provides access to your patron perks.</p>
|
||||
<p>To become a patron, visit <a href="https://patreon.com/cj_clippy">CJ_Clippy on Patreon</a>.</p>
|
||||
|
||||
<hr />
|
||||
<%- include('oauth2.ejs') %>
|
||||
@ -0,0 +1,4 @@
|
||||
<script server>
|
||||
signOut()
|
||||
redirect(`/`)
|
||||
</script>
|
||||
@ -0,0 +1,67 @@
|
||||
<script server>
|
||||
const {
|
||||
state,
|
||||
code
|
||||
} = params
|
||||
|
||||
let error = null
|
||||
let authData = null
|
||||
try {
|
||||
authData = signInWithOAuth2(state, code)
|
||||
|
||||
|
||||
dbg("the shit user id is " + authData.record.id)
|
||||
if (!authData.record.id) {
|
||||
throw new Error('invalid authData. authData must contain a record.id');
|
||||
}
|
||||
|
||||
if (!authData.record.created) {
|
||||
throw new Error('invalid authData. missing record.created')
|
||||
}
|
||||
|
||||
|
||||
|
||||
let user = $app.findRecordById('users', authData.record.id)
|
||||
|
||||
|
||||
// if user is new, give them a free trial
|
||||
const userCreatedAt = new Date(authData.record.created).valueOf();
|
||||
const anHourAgo = Date.now() - 60 * 60 * 1000; // 1 hour in ms
|
||||
dbg(`comparing ${userCreatedAt} > ${anHourAgo}`);
|
||||
if (userCreatedAt > anHourAgo) {
|
||||
dbg("THE USER IS NEW");
|
||||
user.set('patron', true);
|
||||
} else {
|
||||
dbg("the user is NOT new");
|
||||
}
|
||||
|
||||
console.log(JSON.stringify(authData, null, 2))
|
||||
dbg("authData:", stringify(authData))
|
||||
|
||||
|
||||
user.set('patreonAccessToken', authData.meta.accessToken);
|
||||
// user.set('patreonId', authData.meta.id); // we do this via the admin UI
|
||||
$app.save(user);
|
||||
|
||||
|
||||
|
||||
// patreon id can be found in _externalAuths system table
|
||||
|
||||
|
||||
|
||||
// Here we set the patreonId.
|
||||
// If we're seeing this user for the first time,
|
||||
// unconditionally grant them patron status.
|
||||
// The backend later removes the status if they aren't subscribed
|
||||
// let user = $app.findRecordById('user', )
|
||||
|
||||
response.redirect('/')
|
||||
} catch (e) {
|
||||
error = e.message
|
||||
}
|
||||
</script>
|
||||
<% if (error) { %>
|
||||
<mark>
|
||||
<%=error%>
|
||||
</mark>
|
||||
<% } %>
|
||||
@ -0,0 +1,23 @@
|
||||
<script server>
|
||||
let error = null
|
||||
|
||||
if (request.method === 'POST') {
|
||||
let provider
|
||||
try {
|
||||
provider = body().provider
|
||||
const url = requestOAuth2Login(provider)
|
||||
console.log('url is as follows')
|
||||
console.log(url)
|
||||
response.redirect(url)
|
||||
} catch (error) {
|
||||
console.log("FAILURE! We failed to get the OAuth2Login from provider", provider)
|
||||
error = error.message
|
||||
}
|
||||
}
|
||||
</script>
|
||||
<% if (error) { %>
|
||||
<p>we got an err</p>
|
||||
<mark>
|
||||
<%=error%>
|
||||
</mark>
|
||||
<% } %>
|
||||
10
services/pocketbase/pb_hooks/pages/(site)/humans.txt
Normal file
10
services/pocketbase/pb_hooks/pages/(site)/humans.txt
Normal file
@ -0,0 +1,10 @@
|
||||
Hello humans
|
||||
|
||||
futureporn.net
|
||||
future.porn
|
||||
|
||||
R18. For adults only.
|
||||
|
||||
Dedication to the preservation of VTuber history
|
||||
|
||||
made with love by CJ_Clippy cj@futureporn.net
|
||||
23
services/pocketbase/pb_hooks/pages/(site)/index.ejs
Normal file
23
services/pocketbase/pb_hooks/pages/(site)/index.ejs
Normal file
@ -0,0 +1,23 @@
|
||||
<% if (!data?.user?.get('patron')) { %>
|
||||
<div class="notification is-info">
|
||||
Thank you for your support on <a href="https://patreon.com/cj_clippy">Patreon!</a>
|
||||
</div>
|
||||
<% } %>
|
||||
|
||||
<ul class="mt-5">
|
||||
<li class="mb-2">
|
||||
<a class="button" href="/vt">
|
||||
<h2 class="title is-2">VTubers</h2>
|
||||
</a>
|
||||
</li>
|
||||
<li class="mb-2">
|
||||
<a class="button" href="/vods">
|
||||
<h2 class="title is-2">Vods</h2>
|
||||
</a>
|
||||
</li>
|
||||
<li class="mb-2">
|
||||
<a class="button" href="/patrons">
|
||||
<h2 class="title is-2">Patrons</h2>
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
64
services/pocketbase/pb_hooks/pages/(site)/patrons/index.ejs
Normal file
64
services/pocketbase/pb_hooks/pages/(site)/patrons/index.ejs
Normal file
@ -0,0 +1,64 @@
|
||||
<p></p>
|
||||
|
||||
<div class="menu">
|
||||
<p class="subtitle">Thank you to our wonderful patrons who keep this site running</p>
|
||||
<ul class="menu-list">
|
||||
<li>Tyrs</li>
|
||||
<li>StubbstheZombie</li>
|
||||
<li>Delques1843</li>
|
||||
<li>Cray Shay</li>
|
||||
<li>Jay black</li>
|
||||
<li>E T 4321</li>
|
||||
<li>ProfessionalUwU</li>
|
||||
<li>LzyAsn</li>
|
||||
<li>RettichDerGeile</li>
|
||||
<li>Vladislav Šlechta</li>
|
||||
<li>FluffyPenguins527</li>
|
||||
<li>Enderwolf</li>
|
||||
<li>Kieren</li>
|
||||
<li>Captain Highlighter</li>
|
||||
<li>Jonas andreas Gulbrandsen-Efteland</li>
|
||||
<li>Drefsab</li>
|
||||
<li>Randernizer</li>
|
||||
<li>sheldmaster</li>
|
||||
<li>Joe Thelizard</li>
|
||||
<li>IshikawaTXC</li>
|
||||
<li>Alex</li>
|
||||
<li>BioAct1ve</li>
|
||||
<li>AverageYuriEnjoyer</li>
|
||||
<li>Virted</li>
|
||||
<li>MechiPlat</li>
|
||||
<li>JustSleep</li>
|
||||
<li>Cjyoubusta</li>
|
||||
<li>Bravo The Chonk</li>
|
||||
<li>LaoPao</li>
|
||||
<li>Toffse</li>
|
||||
<li>Rubén Ruiz</li>
|
||||
<li>Brewhλwk</li>
|
||||
<li>BusterMachine7</li>
|
||||
<li>Lucas</li>
|
||||
<li>Jogabbagabba</li>
|
||||
<li>Tony</li>
|
||||
<li>Mydus</li>
|
||||
<li>Wubb wubb</li>
|
||||
<li>François d'Aruna</li>
|
||||
<li>Cheese And Crackers</li>
|
||||
<li>Shift</li>
|
||||
<li>Addable Gravy61</li>
|
||||
<li>Heiko7761</li>
|
||||
<li>DustyGreenTea</li>
|
||||
<li>Lolithia</li>
|
||||
<li>Aicome 2000</li>
|
||||
<li>The Gameinator</li>
|
||||
<li>Dice Loynes</li>
|
||||
<li>MilkMoblin</li>
|
||||
<li>Turnip Toss</li>
|
||||
<li>C4425</li>
|
||||
<li>TheSlimiestKing</li>
|
||||
<li>R4z0rSh4rP</li>
|
||||
<li>Lumbar247</li>
|
||||
<li>Vilkki</li>
|
||||
<li>Chiko</li>
|
||||
<li>Djinn</li>
|
||||
</ul>
|
||||
</div>
|
||||
10
services/pocketbase/pb_hooks/pages/(site)/robots.txt
Normal file
10
services/pocketbase/pb_hooks/pages/(site)/robots.txt
Normal file
@ -0,0 +1,10 @@
|
||||
# robots.txt for futureporn.net
|
||||
|
||||
# Block all web crawlers from accessing admin and private areas
|
||||
User-agent: *
|
||||
Disallow: /_/
|
||||
Disallow: /auth/
|
||||
Disallow: /api/
|
||||
|
||||
# Allow crawlers to access public content
|
||||
Allow: /
|
||||
48
services/pocketbase/pb_hooks/pages/(site)/vods/+load.js
Normal file
48
services/pocketbase/pb_hooks/pages/(site)/vods/+load.js
Normal file
@ -0,0 +1,48 @@
|
||||
// +load.js
|
||||
|
||||
/** @type {import('pocketpages').PageDataLoaderFunc} */
|
||||
module.exports = function (api) {
|
||||
const { request, response } = api;
|
||||
|
||||
try {
|
||||
// Read query params with PocketPages
|
||||
const query = request.url.query || {};
|
||||
const page = parseInt(query.page) || 1;
|
||||
const limit = parseInt(query.limit) || 200;
|
||||
const offset = (page - 1) * limit;
|
||||
|
||||
// Fetch all VODs, sorted by -streamDate
|
||||
const allVods = $app.findRecordsByFilter('vods', null, '-streamDate');
|
||||
|
||||
// Slice according to pagination
|
||||
const vods = allVods.slice(offset, offset + limit);
|
||||
|
||||
// Expand related vtubers
|
||||
$app.expandRecords(vods, ['vtubers'], null);
|
||||
|
||||
// Pagination metadata
|
||||
const total = allVods.length;
|
||||
const totalPages = Math.ceil(total / limit);
|
||||
|
||||
return {
|
||||
vods,
|
||||
pagination: {
|
||||
page,
|
||||
limit,
|
||||
total,
|
||||
totalPages,
|
||||
hasNext: page < totalPages,
|
||||
hasPrev: page > 1,
|
||||
},
|
||||
};
|
||||
|
||||
} catch (e) {
|
||||
console.error('Error fetching VODs:', e.message);
|
||||
|
||||
if (e.message.match(/no rows/)) {
|
||||
return response.html(404, 'VODs not found');
|
||||
} else {
|
||||
return response.html(500, 'Unknown internal error while fetching VODs');
|
||||
}
|
||||
}
|
||||
};
|
||||
26
services/pocketbase/pb_hooks/pages/(site)/vods/[id]/+load.js
Normal file
26
services/pocketbase/pb_hooks/pages/(site)/vods/[id]/+load.js
Normal file
@ -0,0 +1,26 @@
|
||||
// +load.js
|
||||
|
||||
/** @type {import('pocketpages').PageDataLoaderFunc} */
|
||||
module.exports = function (api) {
|
||||
const { params, response } = api;
|
||||
try {
|
||||
const vod = $app.findFirstRecordByData('vods', 'id', params.id);
|
||||
$app.expandRecord(vod, ["vtubers"], null);
|
||||
|
||||
|
||||
return { vod };
|
||||
} catch (e) {
|
||||
console.error('error!', e.message);
|
||||
|
||||
if (e.message.match(/no rows/)) {
|
||||
console.log('we are sending 404')
|
||||
return response.html(404, 'VOD not found')
|
||||
|
||||
} else {
|
||||
console.log('we are sending error 500')
|
||||
return response.html(500, 'Unknown internal error while fetching vod')
|
||||
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
@ -0,0 +1,72 @@
|
||||
<div class="players" <% if (data?.user?.get('patron')) { %> data-signals="{'selected':'cdn1'}" <% } else { %> data-signals="{'selected':'cdn2'}" <% } %>>
|
||||
|
||||
<!-- CDN2 Player (B2) -->
|
||||
<div class="b2-player" data-show="$selected == 'cdn2'">
|
||||
<video controls <% if (!data?.user?.get('patron')) { %> preload="none" <% } %>>
|
||||
<% if (data.vod?.get('videoSrcB2')) { %>
|
||||
<source src="<%= data.vod?.get('videoSrcB2') %>" type="video/mp4">
|
||||
<% } else { %>
|
||||
Your browser does not support the video tag.
|
||||
<% } %>
|
||||
</video>
|
||||
</div>
|
||||
|
||||
<!-- CDN1 Player (Mux, patrons only) -->
|
||||
<% if (data?.user?.get('patron')) { %>
|
||||
<div class="mux-player" data-show="$selected == 'cdn1'">
|
||||
<script src="https://cdn.jsdelivr.net/npm/@mux/mux-player" defer></script>
|
||||
<mux-player playback-id="<%= data.vod?.get('muxPlaybackId') %>" playback-token="<%= data.vod?.get('muxPlaybackToken') %>"></mux-player>
|
||||
</div>
|
||||
<% } %>
|
||||
|
||||
</div>
|
||||
|
||||
<!-- Player toggle buttons -->
|
||||
<nav class="level mt-5">
|
||||
<div class="level-left">
|
||||
<% if (data?.user?.get('patron')) { %>
|
||||
<button class="button is-success" data-on-click="$selected = 'cdn1'">CDN1 player</button>
|
||||
<% } else { %>
|
||||
<button disabled class="button is-danger">CDN1 player (patrons only)</button>
|
||||
<% } %>
|
||||
<button class="button is-success" data-on-click="$selected = 'cdn2'">CDN2 player</button>
|
||||
</div>
|
||||
</nav>
|
||||
|
||||
<!-- VOD Details -->
|
||||
<div class="vod-details box mt-5">
|
||||
<p><b>VOD ID:</b> <%= data.vod?.id ?? 'N/A' %></p>
|
||||
|
||||
<p>
|
||||
<b>VTubers:</b>
|
||||
<% const vtubers = data.vod?.get('expand')?.vtubers ?? []; %>
|
||||
<% vtubers.forEach((vtuber, index) => { %>
|
||||
<% if (vtuber) { %>
|
||||
<a href="/vt/<%= vtuber.get('slug') ?? '#' %>">
|
||||
<%= vtuber.get('displayName') ?? 'Unknown VTuber' %>
|
||||
</a><%= index < vtubers.length - 1 ? ', ' : '' %>
|
||||
<% } %>
|
||||
<% }) %>
|
||||
<% if (vtubers.length === 0) { %>None<% } %>
|
||||
</p>
|
||||
|
||||
<p><b>Stream Date:</b> <%= data.vod?.get('streamDate') ?? 'Unknown date' %></p>
|
||||
|
||||
<% if (data.vod?.get('announceUrl')) { %>
|
||||
<p>
|
||||
<b>Announce URL:</b>
|
||||
<a href="<%= data.vod?.get('announceUrl') %>"><%= data.vod?.get('announceUrl') %></a>
|
||||
</p>
|
||||
<% } %>
|
||||
|
||||
<% if (data.vod?.get('ipfsCid')) { %>
|
||||
<p><b>IPFS CID:</b> <%= data.vod?.get('ipfsCid') %></p>
|
||||
<% } %>
|
||||
|
||||
<% if (data.vod?.get('notes')) { %>
|
||||
<p><b>Notes:</b></p>
|
||||
<pre class="p-2"><%= data.vod?.get('notes') %></pre>
|
||||
<% } %>
|
||||
</div>
|
||||
|
||||
<div class="mb-5"></div>
|
||||
@ -0,0 +1,26 @@
|
||||
// +load.js
|
||||
|
||||
/** @type {import('pocketpages').PageDataLoaderFunc} */
|
||||
module.exports = function (api) {
|
||||
const { params, response } = api;
|
||||
try {
|
||||
const vods = $app.findRecordsByFilter('vods', null, '-streamDate');
|
||||
$app.expandRecords(vods, ["vtubers"], null);
|
||||
// vods.expandedAll("vtubers");
|
||||
return { vods };
|
||||
|
||||
} catch (e) {
|
||||
console.error('error!', e.message);
|
||||
|
||||
if (e.message.match(/no rows/)) {
|
||||
console.log('we are sending 404')
|
||||
return response.html(404, 'VODs not found')
|
||||
|
||||
} else {
|
||||
console.log('we are sending error 500')
|
||||
return response.html(500, 'Unknown internal error while fetching vods')
|
||||
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
@ -0,0 +1,50 @@
|
||||
<%#
|
||||
index.ejs — Atom Feed Generator (Atom 1.0)
|
||||
Expects: data.vods = [{ id, title, summary, streamDate }]
|
||||
%>
|
||||
|
||||
<%
|
||||
const siteBase = "https://futureporn.net";
|
||||
const feedSelf = `${siteBase}/vods/feed.xml`;
|
||||
const updated = new Date().toISOString();
|
||||
response.header('Content-Type', 'application/atom+xml')
|
||||
%>
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<feed xmlns="http://www.w3.org/2005/Atom">
|
||||
<id><%= siteBase %></id>
|
||||
<title>Futureporn.net</title>
|
||||
<updated><%= updated %></updated>
|
||||
<generator> </generator>
|
||||
|
||||
<author>
|
||||
<name>CJ_Clippy</name>
|
||||
<email>cj@futureporn.net</email>
|
||||
<uri><%= siteBase %></uri>
|
||||
</author>
|
||||
|
||||
<link rel="alternate" href="<%= siteBase %>" />
|
||||
<link rel="self" href="<%= feedSelf %>" />
|
||||
|
||||
<subtitle><%= meta('description') %></subtitle>
|
||||
<logo><%= siteBase %>/images/futureporn-icon.png</logo>
|
||||
<icon><%= siteBase %>/favicon.ico</icon>
|
||||
|
||||
<% for (const vod of data.vods) { %>
|
||||
<%
|
||||
const url = `${siteBase}/vods/${vod.id}`;
|
||||
%>
|
||||
<entry>
|
||||
<title type="html">
|
||||
<![CDATA[ <%= vod.title %> ]]>
|
||||
</title>
|
||||
<id><%= url %></id>
|
||||
<link href="<%= url %>" />
|
||||
<updated><%= new Date(vod.updated) %></updated>
|
||||
<% if (vod.notes) { %>
|
||||
<summary type="html">
|
||||
<![CDATA[ <%= vod.notes %> ]]>
|
||||
</summary>
|
||||
<% } %>
|
||||
</entry>
|
||||
<% } %>
|
||||
</feed>
|
||||
72
services/pocketbase/pb_hooks/pages/(site)/vods/index.ejs
Normal file
72
services/pocketbase/pb_hooks/pages/(site)/vods/index.ejs
Normal file
@ -0,0 +1,72 @@
|
||||
<h2 class="title is-2">VODs</h2>
|
||||
|
||||
<% if (Array.isArray(data.vods) && data.vods.length > 0) { %>
|
||||
<div class="table-container">
|
||||
<table class="table is-striped is-hoverable is-fullwidth">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Stream Date</th>
|
||||
<th>VTubers</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<% for (const vod of data.vods) { %>
|
||||
<tr>
|
||||
<td>
|
||||
<a href="/vods/<%= vod?.id %>" class="is-small is-link">
|
||||
<%= vod?.get ? vod.get('streamDate') : vod?.streamDate ?? 'Unknown date' %>
|
||||
</a>
|
||||
</td>
|
||||
<td>
|
||||
<% const vtubers = vod?.get ? vod.get('expand')?.vtubers ?? [] : vod?.vtubers ?? []; %>
|
||||
<% if (vtubers.length > 0) { %>
|
||||
<% for (let i = 0; i < vtubers.length; i++) { %>
|
||||
<%= vtubers[i]?.get ? vtubers[i].get('displayName') : vtubers[i]?.displayName ?? 'Unknown' %>
|
||||
<%= i < vtubers.length - 1 ? ', ' : '' %>
|
||||
<% } %>
|
||||
<% } else { %>
|
||||
None
|
||||
<% } %>
|
||||
</td>
|
||||
</tr>
|
||||
<% } %>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
<!-- Pagination Controls -->
|
||||
<% if (data.pagination && data.pagination.totalPages > 1) { %>
|
||||
<nav class="pagination is-centered" role="navigation" aria-label="pagination">
|
||||
<% const currentPage = data.pagination.page; %>
|
||||
<% const totalPages = data.pagination.totalPages; %>
|
||||
|
||||
<!-- Previous Page -->
|
||||
<% if (data.pagination.hasPrev) { %>
|
||||
<a class="pagination-previous" href="?page=<%= currentPage - 1 %>&limit=<%= data.pagination.limit %>">Previous</a>
|
||||
<% } else { %>
|
||||
<a class="pagination-previous" disabled>Previous</a>
|
||||
<% } %>
|
||||
|
||||
<!-- Next Page -->
|
||||
<% if (data.pagination.hasNext) { %>
|
||||
<a class="pagination-next" href="?page=<%= currentPage + 1 %>&limit=<%= data.pagination.limit %>">Next</a>
|
||||
<% } else { %>
|
||||
<a class="pagination-next" disabled>Next</a>
|
||||
<% } %>
|
||||
|
||||
<!-- Page Numbers -->
|
||||
<ul class="pagination-list">
|
||||
<% for (let i = 1; i <= totalPages; i++) { %>
|
||||
<li>
|
||||
<a class="pagination-link <%= i === currentPage ? 'is-current' : '' %>" href="?page=<%= i %>&limit=<%= data.pagination.limit %>">
|
||||
<%= i %>
|
||||
</a>
|
||||
</li>
|
||||
<% } %>
|
||||
</ul>
|
||||
</nav>
|
||||
<% } %>
|
||||
|
||||
<% } else { %>
|
||||
<p>No VODs available.</p>
|
||||
<% } %>
|
||||
25
services/pocketbase/pb_hooks/pages/(site)/vt/[slug]/+load.js
Normal file
25
services/pocketbase/pb_hooks/pages/(site)/vt/[slug]/+load.js
Normal file
@ -0,0 +1,25 @@
|
||||
// +load.js
|
||||
|
||||
/** @type {import('pocketpages').PageDataLoaderFunc} */
|
||||
module.exports = function (api) {
|
||||
const { params, response } = api;
|
||||
try {
|
||||
const vtuber = $app.findFirstRecordByData('vtubers', 'slug', params.slug);
|
||||
$app.expandRecord(vtuber, ["vods"], null);
|
||||
// console.log(JSON.stringify(vtuber))
|
||||
return { vtuber };
|
||||
} catch (e) {
|
||||
console.error('error!', e.message);
|
||||
|
||||
if (e.message.match(/no rows/)) {
|
||||
console.log('we are sending 404')
|
||||
return response.html(404, 'VTuber not found')
|
||||
|
||||
} else {
|
||||
console.log('we are sending error 500')
|
||||
return response.html(500, 'Unknown internal error while fetching vtuber')
|
||||
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
@ -0,0 +1,3 @@
|
||||
<% if (data.vtuber) { %>
|
||||
<%- include('vtuber.ejs', { vtuber: data.vtuber }) %>
|
||||
<% } %>
|
||||
8
services/pocketbase/pb_hooks/pages/(site)/vt/index.ejs
Normal file
8
services/pocketbase/pb_hooks/pages/(site)/vt/index.ejs
Normal file
@ -0,0 +1,8 @@
|
||||
<script server>
|
||||
const
|
||||
vtubers = $app.findRecordsByFilter('vtubers')
|
||||
</script>
|
||||
|
||||
|
||||
<h3>Vtubers</h3>
|
||||
<%- include('vtuber-list.ejs', { vtubers }) %>
|
||||
14
services/pocketbase/pb_hooks/pages/+config.js
Normal file
14
services/pocketbase/pb_hooks/pages/+config.js
Normal file
@ -0,0 +1,14 @@
|
||||
|
||||
|
||||
module.exports = {
|
||||
debug: false,
|
||||
plugins: [
|
||||
'pocketpages-plugin-ejs',
|
||||
'pocketpages-plugin-datastar',
|
||||
'pocketpages-plugin-realtime',
|
||||
'pocketpages-plugin-auth',
|
||||
'pocketpages-plugin-js-sdk',
|
||||
'pocketpages-plugin-micro-dash',
|
||||
'../../../src/plugins/patreon'
|
||||
],
|
||||
}
|
||||
11
services/pocketbase/pb_hooks/pages/_private/vtuber-list.ejs
Normal file
11
services/pocketbase/pb_hooks/pages/_private/vtuber-list.ejs
Normal file
@ -0,0 +1,11 @@
|
||||
<div id="vtuber-list">
|
||||
<% for (const vtuber of vtubers) { %>
|
||||
<div class="">
|
||||
<span class="">
|
||||
<a href="/vt/<%= vtuber.get('slug') %>">
|
||||
<%= vtuber.get('displayName') %>
|
||||
</a>
|
||||
</span>
|
||||
</div>
|
||||
<% } %>
|
||||
</div>
|
||||
62
services/pocketbase/pb_hooks/pages/_private/vtuber.ejs
Normal file
62
services/pocketbase/pb_hooks/pages/_private/vtuber.ejs
Normal file
@ -0,0 +1,62 @@
|
||||
<div id="vtuber" class="">
|
||||
<div class="flex items-center justify-between">
|
||||
|
||||
<!-- VTuber Image -->
|
||||
<figure class="image is-128x128">
|
||||
<img src="/api/files/vtubers/<%= data.vtuber?.id %>/<%= data.vtuber?.image %>?thumb=128x128" alt="<%= data.vtuber?.get?.('displayName') || 'VTuber' %>" />
|
||||
</figure>
|
||||
|
||||
<!-- VTuber Name -->
|
||||
<span class="title is-6">
|
||||
<%= data.vtuber?.displayName || data.vtuber?.get?.('displayName') || 'Unknown VTuber' %>
|
||||
</span>
|
||||
|
||||
|
||||
|
||||
|
||||
<section class="section">
|
||||
<h3 class="title is-4 mb-4">VODs</h3>
|
||||
|
||||
<%
|
||||
const vods = data.vtuber.get('expand')?.vods || [];
|
||||
if (vods.length > 0) {
|
||||
%>
|
||||
<div class="columns is-multiline">
|
||||
<% for (const vod of vods) { %>
|
||||
<div class="column is-one-quarter-desktop is-half-tablet is-full-mobile">
|
||||
<a href="/vods/<%= vod.get('id') %>" class="box has-text-centered">
|
||||
|
||||
<!-- Thumbnail -->
|
||||
<% if (vod.get('thumbnail')) { %>
|
||||
<figure class="image is-16by9 mb-2">
|
||||
<img src="/api/files/vods/<%= vod.get('id') %>/<%= vod.get('thumbnail') %>?thumb=400x225" alt="VOD thumbnail for <%= vod.get('id') %>" />
|
||||
</figure>
|
||||
<% } else { %>
|
||||
<div class="has-background-grey-lighter py-6 mb-2">
|
||||
<span class="has-text-grey">No thumbnail</span>
|
||||
</div>
|
||||
<% } %>
|
||||
|
||||
<!-- Title / ID -->
|
||||
<p class="is-size-6 has-text-weight-semibold">
|
||||
<%= vod.get('title') || vod.get('id') %>
|
||||
</p>
|
||||
|
||||
<!-- Date -->
|
||||
<% if (vod.get('streamDate')) { %>
|
||||
<p class="is-size-7 has-text-grey">
|
||||
<%= new Date(vod.get('streamDate')).toLocaleDateString() %>
|
||||
</p>
|
||||
<% } %>
|
||||
</a>
|
||||
</div>
|
||||
<% } %>
|
||||
</div>
|
||||
<% } else { %>
|
||||
<p>No VODs available for this VTuber.</p>
|
||||
<% } %>
|
||||
</section>
|
||||
|
||||
|
||||
</div>
|
||||
</div>
|
||||
@ -0,0 +1,6 @@
|
||||
<%
|
||||
response.header("Content-Type",
|
||||
"application/json");
|
||||
response.html(410,
|
||||
"");
|
||||
%>
|
||||
@ -0,0 +1,41 @@
|
||||
<script server>
|
||||
// const {
|
||||
// request,
|
||||
// response
|
||||
// } = api;
|
||||
|
||||
|
||||
const cookies = request.cookies()
|
||||
|
||||
let user;
|
||||
|
||||
if (auth) {
|
||||
console.log('request.auth is present id:', auth.get('id'))
|
||||
user = $app.findFirstRecordByData('users', 'id', auth.id);
|
||||
}
|
||||
|
||||
|
||||
if (!user) {
|
||||
datastar.patchSignals(stringify({
|
||||
showNotif: true
|
||||
}))
|
||||
return response.html(401, "Auth required")
|
||||
}
|
||||
|
||||
console.log('signals as follows')
|
||||
const signals = datastar.readSignals(request, {})
|
||||
|
||||
user.set('publicUsername', signals.publicUsername);
|
||||
|
||||
// Determine the publicUsername status
|
||||
const publicStatus = user.get('publicUsername') ?
|
||||
'Your username is now <b>public</b>.' :
|
||||
'Your username is now <b>private</b>.';
|
||||
|
||||
// Update the page with a verbose message
|
||||
datastar.patchElements(`
|
||||
<div id="results" class="notification is-success mt-5">
|
||||
Saved! ${publicStatus}
|
||||
</div>
|
||||
`);
|
||||
</script>
|
||||
6
services/pocketbase/pb_hooks/pages/api/v1.json/index.ejs
Normal file
6
services/pocketbase/pb_hooks/pages/api/v1.json/index.ejs
Normal file
@ -0,0 +1,6 @@
|
||||
<%
|
||||
response.header("Content-Type",
|
||||
"application/json");
|
||||
response.html(410,
|
||||
"");
|
||||
%>
|
||||
@ -0,0 +1 @@
|
||||
<% response.redirect('/vods/feed.json', 301) %>
|
||||
@ -0,0 +1 @@
|
||||
<% response.redirect('/vods/feed.xml', 301) %>
|
||||
@ -0,0 +1 @@
|
||||
<% response.redirect('/vods/rss.xml', 301) %>
|
||||
26
services/pocketbase/pb_hooks/pages/vods/feed.json/+load.js
Normal file
26
services/pocketbase/pb_hooks/pages/vods/feed.json/+load.js
Normal file
@ -0,0 +1,26 @@
|
||||
// +load.js
|
||||
|
||||
/** @type {import('pocketpages').PageDataLoaderFunc} */
|
||||
module.exports = function (api) {
|
||||
const { params, response } = api;
|
||||
try {
|
||||
const vods = $app.findRecordsByFilter('vods', null, '-streamDate');
|
||||
$app.expandRecords(vods, ["vtubers"], null);
|
||||
// vods.expandedAll("vtubers");
|
||||
return { vods };
|
||||
|
||||
} catch (e) {
|
||||
console.error('error!', e.message);
|
||||
|
||||
if (e.message.match(/no rows/)) {
|
||||
console.log('we are sending 404')
|
||||
return response.html(404, 'VODs not found')
|
||||
|
||||
} else {
|
||||
console.log('we are sending error 500')
|
||||
return response.html(500, 'Unknown internal error while fetching vods')
|
||||
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
29
services/pocketbase/pb_hooks/pages/vods/feed.json/index.ejs
Normal file
29
services/pocketbase/pb_hooks/pages/vods/feed.json/index.ejs
Normal file
@ -0,0 +1,29 @@
|
||||
<%#
|
||||
/**
|
||||
* index.ejs - Generates a JSON feed
|
||||
* Expects: data.vods = [{ id, title, url, description, publishedAt, ... }]
|
||||
*/
|
||||
%>
|
||||
|
||||
<%
|
||||
const feed = {
|
||||
version: "https://jsonfeed.org/version/1",
|
||||
title: `${meta('title')} VODs`,
|
||||
home_page_url: "https://futureporn.net",
|
||||
feed_url: "https://futureporn.net/vods/feed.json",
|
||||
description: meta('description'),
|
||||
icon: "https://futureporn.net/images/futureporn-icon.png",
|
||||
author: {
|
||||
name: "CJ_Clippy",
|
||||
url: "https://futureporn.net"
|
||||
},
|
||||
items: data.vods.map(vod => ({
|
||||
content_html: "",
|
||||
url: `https://futureporn.net/vods/${vod.id}`,
|
||||
title: vod.title,
|
||||
summary: vod.notes || vod.title,
|
||||
image: vod.thumbnail,
|
||||
date_modified: vod.updated
|
||||
}))
|
||||
};
|
||||
%><%- JSON.stringify(feed, null, 2) %>
|
||||
28
services/pocketbase/pb_hooks/pages/vods/feed.xml/+load.js
Normal file
28
services/pocketbase/pb_hooks/pages/vods/feed.xml/+load.js
Normal file
@ -0,0 +1,28 @@
|
||||
// +load.js
|
||||
|
||||
/** @type {import('pocketpages').PageDataLoaderFunc} */
|
||||
module.exports = function (api) {
|
||||
const { params, response } = api;
|
||||
try {
|
||||
const vods = $app.findRecordsByFilter('vods', null, '-streamDate', 99);
|
||||
$app.expandRecords(vods, ["vtubers"], null);
|
||||
|
||||
|
||||
console.log(JSON.stringify(vods, null, 2))
|
||||
return { vods };
|
||||
|
||||
} catch (e) {
|
||||
console.error('error!', e.message);
|
||||
|
||||
if (e.message.match(/no rows/)) {
|
||||
console.log('we are sending 404')
|
||||
return response.html(404, 'VODs not found')
|
||||
|
||||
} else {
|
||||
console.log('we are sending error 500')
|
||||
return response.html(500, 'Unknown internal error while fetching vods')
|
||||
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
58
services/pocketbase/pb_hooks/pages/vods/feed.xml/index.ejs
Normal file
58
services/pocketbase/pb_hooks/pages/vods/feed.xml/index.ejs
Normal file
@ -0,0 +1,58 @@
|
||||
<%#
|
||||
index.ejs — ATOM Feed Generator
|
||||
Expects: data.vods = [{ id, title, notes, thumbnail, streamDate }]
|
||||
%>
|
||||
|
||||
<%=
|
||||
response.header("Content-Type", "application/atom+xml");
|
||||
|
||||
// Build Atom XML as a string
|
||||
let atom = `<?xml version="1.0" encoding="utf-8"?>
|
||||
<feed xmlns="http://www.w3.org/2005/Atom">
|
||||
<title>Futureporn.net</title>
|
||||
<link href="<%= env('ORIGIN') %>"/>
|
||||
<updated>${new Date().toISOString()}</updated>
|
||||
<id><%= env('ORIGIN') %></id>
|
||||
<author>
|
||||
<name>CJ_Clippy</name>
|
||||
<email>cj@futureporn.net</email>
|
||||
</author>`;
|
||||
|
||||
for (const vod of data.vods) {
|
||||
const url = `${env('ORIGIN')}/vods/${vod.id}`;
|
||||
const entryTitle = ((vod?.get('expand')?.vtubers?.map(vt => vt.get('displayName')) || [])
|
||||
.join(', ') || vod.get('streamDate'));
|
||||
|
||||
atom += `
|
||||
<entry>
|
||||
<title>
|
||||
<![CDATA[${entryTitle}]]>
|
||||
</title>
|
||||
<link href="${url}" />
|
||||
<id>${url}</id>
|
||||
<updated>${vod.get('streamDate')}</updated>`;
|
||||
|
||||
if (vod.get('notes')) {
|
||||
atom += `
|
||||
<summary type="html">
|
||||
<![CDATA[${vod.get('notes')}]]>
|
||||
</summary>`;
|
||||
}
|
||||
|
||||
if (vod.get('thumbnail')) {
|
||||
atom += `
|
||||
<content type="image">
|
||||
<![CDATA[<img src="${vod.get('thumbnail')}" />]]>
|
||||
</content>`;
|
||||
}
|
||||
|
||||
atom += `
|
||||
</entry>`;
|
||||
}
|
||||
|
||||
atom += `
|
||||
</feed>`;
|
||||
|
||||
// Send the Atom feed
|
||||
response.html(200, '<p>HELLO</p>');
|
||||
%>
|
||||
28
services/pocketbase/pb_hooks/pages/vods/rss.xml/+load.js
Normal file
28
services/pocketbase/pb_hooks/pages/vods/rss.xml/+load.js
Normal file
@ -0,0 +1,28 @@
|
||||
// +load.js
|
||||
|
||||
/** @type {import('pocketpages').PageDataLoaderFunc} */
|
||||
module.exports = function (api) {
|
||||
const { params, response } = api;
|
||||
try {
|
||||
const vods = $app.findRecordsByFilter('vods', null, '-streamDate', 99);
|
||||
$app.expandRecords(vods, ["vtubers"], null);
|
||||
|
||||
|
||||
console.log(JSON.stringify(vods, null, 2))
|
||||
return { vods };
|
||||
|
||||
} catch (e) {
|
||||
console.error('error!', e.message);
|
||||
|
||||
if (e.message.match(/no rows/)) {
|
||||
console.log('we are sending 404')
|
||||
return response.html(404, 'VODs not found')
|
||||
|
||||
} else {
|
||||
console.log('we are sending error 500')
|
||||
return response.html(500, 'Unknown internal error while fetching vods')
|
||||
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
56
services/pocketbase/pb_hooks/pages/vods/rss.xml/index.ejs
Normal file
56
services/pocketbase/pb_hooks/pages/vods/rss.xml/index.ejs
Normal file
@ -0,0 +1,56 @@
|
||||
<%#
|
||||
index.ejs — RSS Feed Generator (RSS 2.0)
|
||||
Expects: data.vods = [{ id, title, notes, thumbnail, streamDate }]
|
||||
%>
|
||||
|
||||
<%
|
||||
response.header("Content-Type", "application/rss+xml")
|
||||
|
||||
// Build RSS XML as a string
|
||||
let rss = `<?xml version="1.0" encoding="utf-8"?>
|
||||
<rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/">
|
||||
<channel>
|
||||
<title>Futureporn.net</title>
|
||||
<link>https://futureporn.net</link>
|
||||
<description>Dedication to the preservaton of lewdtuber history</description>
|
||||
<lastBuildDate>${new Date().toUTCString()}</lastBuildDate>
|
||||
<docs>https://validator.w3.org/feed/docs/rss2.html</docs>
|
||||
<generator> </generator>
|
||||
<language>en</language>
|
||||
<image>
|
||||
<title>Futureporn.net</title>
|
||||
<url>https://futureporn.net/images/futureporn-icon.png</url>
|
||||
<link>https://futureporn.net</link>
|
||||
</image>`;
|
||||
|
||||
for (const vod of data.vods) {
|
||||
const url = `${env('ORIGIN')}/vods/${vod.id}`;
|
||||
rss += `
|
||||
<item>
|
||||
|
||||
<title><![CDATA[${
|
||||
((vod?.get('expand')?.vtubers?.map(vt => vt.get('displayName')) || []).join(', ')
|
||||
|| vod.get('streamDate'))
|
||||
}]]></title>
|
||||
<link>${url}</link>
|
||||
<guid>${url}</guid>
|
||||
<pubDate>${vod.get('streamDate')}</pubDate>`;
|
||||
if (vod.notes) {
|
||||
rss += `
|
||||
<description><![CDATA[${vod.notes}]]></description>`;
|
||||
}
|
||||
if (vod.thumbnail) {
|
||||
rss += `
|
||||
<enclosure url="${vod.thumbnail}" length="0" type="image/png" />`;
|
||||
}
|
||||
rss += `
|
||||
</item>`;
|
||||
}
|
||||
|
||||
rss += `
|
||||
</channel>
|
||||
</rss>`;
|
||||
|
||||
// Send the RSS
|
||||
response.html(200, rss);
|
||||
%>
|
||||
1
services/pocketbase/pb_hooks/pocketpages.pb.js
Normal file
1
services/pocketbase/pb_hooks/pocketpages.pb.js
Normal file
@ -0,0 +1 @@
|
||||
require('pocketpages')
|
||||
79
services/pocketbase/pb_migrations/1761803155_created_vod.js
Normal file
79
services/pocketbase/pb_migrations/1761803155_created_vod.js
Normal file
@ -0,0 +1,79 @@
|
||||
/// <reference path="../pb_data/types.d.ts" />
|
||||
migrate((app) => {
|
||||
const collection = new Collection({
|
||||
"createRule": null,
|
||||
"deleteRule": null,
|
||||
"fields": [
|
||||
{
|
||||
"autogeneratePattern": "[a-z0-9]{15}",
|
||||
"hidden": false,
|
||||
"id": "text3208210256",
|
||||
"max": 15,
|
||||
"min": 15,
|
||||
"name": "id",
|
||||
"pattern": "^[a-z0-9]+$",
|
||||
"presentable": false,
|
||||
"primaryKey": true,
|
||||
"required": true,
|
||||
"system": true,
|
||||
"type": "text"
|
||||
},
|
||||
{
|
||||
"hidden": false,
|
||||
"id": "date3986823616",
|
||||
"max": "",
|
||||
"min": "",
|
||||
"name": "streamDate",
|
||||
"presentable": false,
|
||||
"required": false,
|
||||
"system": false,
|
||||
"type": "date"
|
||||
},
|
||||
{
|
||||
"exceptDomains": null,
|
||||
"hidden": false,
|
||||
"id": "url3307693472",
|
||||
"name": "announceUrl",
|
||||
"onlyDomains": null,
|
||||
"presentable": false,
|
||||
"required": false,
|
||||
"system": false,
|
||||
"type": "url"
|
||||
},
|
||||
{
|
||||
"hidden": false,
|
||||
"id": "autodate2990389176",
|
||||
"name": "created",
|
||||
"onCreate": true,
|
||||
"onUpdate": false,
|
||||
"presentable": false,
|
||||
"system": false,
|
||||
"type": "autodate"
|
||||
},
|
||||
{
|
||||
"hidden": false,
|
||||
"id": "autodate3332085495",
|
||||
"name": "updated",
|
||||
"onCreate": true,
|
||||
"onUpdate": true,
|
||||
"presentable": false,
|
||||
"system": false,
|
||||
"type": "autodate"
|
||||
}
|
||||
],
|
||||
"id": "pbc_144770472",
|
||||
"indexes": [],
|
||||
"listRule": null,
|
||||
"name": "vod",
|
||||
"system": false,
|
||||
"type": "base",
|
||||
"updateRule": null,
|
||||
"viewRule": null
|
||||
});
|
||||
|
||||
return app.save(collection);
|
||||
}, (app) => {
|
||||
const collection = app.findCollectionByNameOrId("pbc_144770472");
|
||||
|
||||
return app.delete(collection);
|
||||
})
|
||||
@ -0,0 +1,57 @@
|
||||
/// <reference path="../pb_data/types.d.ts" />
|
||||
migrate((app) => {
|
||||
const collection = new Collection({
|
||||
"createRule": null,
|
||||
"deleteRule": null,
|
||||
"fields": [
|
||||
{
|
||||
"autogeneratePattern": "[a-z0-9]{15}",
|
||||
"hidden": false,
|
||||
"id": "text3208210256",
|
||||
"max": 15,
|
||||
"min": 15,
|
||||
"name": "id",
|
||||
"pattern": "^[a-z0-9]+$",
|
||||
"presentable": false,
|
||||
"primaryKey": true,
|
||||
"required": true,
|
||||
"system": true,
|
||||
"type": "text"
|
||||
},
|
||||
{
|
||||
"hidden": false,
|
||||
"id": "autodate2990389176",
|
||||
"name": "created",
|
||||
"onCreate": true,
|
||||
"onUpdate": false,
|
||||
"presentable": false,
|
||||
"system": false,
|
||||
"type": "autodate"
|
||||
},
|
||||
{
|
||||
"hidden": false,
|
||||
"id": "autodate3332085495",
|
||||
"name": "updated",
|
||||
"onCreate": true,
|
||||
"onUpdate": true,
|
||||
"presentable": false,
|
||||
"system": false,
|
||||
"type": "autodate"
|
||||
}
|
||||
],
|
||||
"id": "pbc_3872109612",
|
||||
"indexes": [],
|
||||
"listRule": null,
|
||||
"name": "vtuber",
|
||||
"system": false,
|
||||
"type": "base",
|
||||
"updateRule": null,
|
||||
"viewRule": null
|
||||
});
|
||||
|
||||
return app.save(collection);
|
||||
}, (app) => {
|
||||
const collection = app.findCollectionByNameOrId("pbc_3872109612");
|
||||
|
||||
return app.delete(collection);
|
||||
})
|
||||
@ -0,0 +1,48 @@
|
||||
/// <reference path="../pb_data/types.d.ts" />
|
||||
migrate((app) => {
|
||||
const collection = app.findCollectionByNameOrId("pbc_3872109612")
|
||||
|
||||
// add field
|
||||
collection.fields.addAt(1, new Field({
|
||||
"autogeneratePattern": "",
|
||||
"hidden": false,
|
||||
"id": "text1731158936",
|
||||
"max": 0,
|
||||
"min": 0,
|
||||
"name": "displayName",
|
||||
"pattern": "",
|
||||
"presentable": false,
|
||||
"primaryKey": false,
|
||||
"required": false,
|
||||
"system": false,
|
||||
"type": "text"
|
||||
}))
|
||||
|
||||
// add field
|
||||
collection.fields.addAt(2, new Field({
|
||||
"autogeneratePattern": "",
|
||||
"hidden": false,
|
||||
"id": "text2560465762",
|
||||
"max": 0,
|
||||
"min": 0,
|
||||
"name": "slug",
|
||||
"pattern": "",
|
||||
"presentable": false,
|
||||
"primaryKey": false,
|
||||
"required": false,
|
||||
"system": false,
|
||||
"type": "text"
|
||||
}))
|
||||
|
||||
return app.save(collection)
|
||||
}, (app) => {
|
||||
const collection = app.findCollectionByNameOrId("pbc_3872109612")
|
||||
|
||||
// remove field
|
||||
collection.fields.removeById("text1731158936")
|
||||
|
||||
// remove field
|
||||
collection.fields.removeById("text2560465762")
|
||||
|
||||
return app.save(collection)
|
||||
})
|
||||
352
services/pocketbase/pb_migrations/1761818023_updated_vtuber.js
Normal file
352
services/pocketbase/pb_migrations/1761818023_updated_vtuber.js
Normal file
@ -0,0 +1,352 @@
|
||||
/// <reference path="../pb_data/types.d.ts" />
|
||||
migrate((app) => {
|
||||
const collection = app.findCollectionByNameOrId("pbc_3872109612")
|
||||
|
||||
// add field
|
||||
collection.fields.addAt(3, new Field({
|
||||
"cascadeDelete": false,
|
||||
"collectionId": "pbc_144770472",
|
||||
"hidden": false,
|
||||
"id": "relation3825607268",
|
||||
"maxSelect": 999,
|
||||
"minSelect": 0,
|
||||
"name": "vods",
|
||||
"presentable": false,
|
||||
"required": false,
|
||||
"system": false,
|
||||
"type": "relation"
|
||||
}))
|
||||
|
||||
// add field
|
||||
collection.fields.addAt(4, new Field({
|
||||
"hidden": false,
|
||||
"id": "file3309110367",
|
||||
"maxSelect": 1,
|
||||
"maxSize": 0,
|
||||
"mimeTypes": [],
|
||||
"name": "image",
|
||||
"presentable": false,
|
||||
"protected": false,
|
||||
"required": false,
|
||||
"system": false,
|
||||
"thumbs": [],
|
||||
"type": "file"
|
||||
}))
|
||||
|
||||
// add field
|
||||
collection.fields.addAt(5, new Field({
|
||||
"exceptDomains": null,
|
||||
"hidden": false,
|
||||
"id": "url1288386755",
|
||||
"name": "chaturbate",
|
||||
"onlyDomains": null,
|
||||
"presentable": false,
|
||||
"required": false,
|
||||
"system": false,
|
||||
"type": "url"
|
||||
}))
|
||||
|
||||
// add field
|
||||
collection.fields.addAt(6, new Field({
|
||||
"exceptDomains": null,
|
||||
"hidden": false,
|
||||
"id": "url376077238",
|
||||
"name": "twitter",
|
||||
"onlyDomains": null,
|
||||
"presentable": false,
|
||||
"required": false,
|
||||
"system": false,
|
||||
"type": "url"
|
||||
}))
|
||||
|
||||
// add field
|
||||
collection.fields.addAt(7, new Field({
|
||||
"exceptDomains": null,
|
||||
"hidden": false,
|
||||
"id": "url2042351438",
|
||||
"name": "patreon",
|
||||
"onlyDomains": null,
|
||||
"presentable": false,
|
||||
"required": false,
|
||||
"system": false,
|
||||
"type": "url"
|
||||
}))
|
||||
|
||||
// add field
|
||||
collection.fields.addAt(8, new Field({
|
||||
"exceptDomains": null,
|
||||
"hidden": false,
|
||||
"id": "url1928100768",
|
||||
"name": "twitch",
|
||||
"onlyDomains": null,
|
||||
"presentable": false,
|
||||
"required": false,
|
||||
"system": false,
|
||||
"type": "url"
|
||||
}))
|
||||
|
||||
// add field
|
||||
collection.fields.addAt(9, new Field({
|
||||
"exceptDomains": null,
|
||||
"hidden": false,
|
||||
"id": "url847873150",
|
||||
"name": "tiktok",
|
||||
"onlyDomains": null,
|
||||
"presentable": false,
|
||||
"required": false,
|
||||
"system": false,
|
||||
"type": "url"
|
||||
}))
|
||||
|
||||
// add field
|
||||
collection.fields.addAt(10, new Field({
|
||||
"exceptDomains": null,
|
||||
"hidden": false,
|
||||
"id": "url1505654846",
|
||||
"name": "onlyfans",
|
||||
"onlyDomains": null,
|
||||
"presentable": false,
|
||||
"required": false,
|
||||
"system": false,
|
||||
"type": "url"
|
||||
}))
|
||||
|
||||
// add field
|
||||
collection.fields.addAt(11, new Field({
|
||||
"exceptDomains": null,
|
||||
"hidden": false,
|
||||
"id": "url4034435380",
|
||||
"name": "youtube",
|
||||
"onlyDomains": null,
|
||||
"presentable": false,
|
||||
"required": false,
|
||||
"system": false,
|
||||
"type": "url"
|
||||
}))
|
||||
|
||||
// add field
|
||||
collection.fields.addAt(12, new Field({
|
||||
"exceptDomains": null,
|
||||
"hidden": false,
|
||||
"id": "url3056519709",
|
||||
"name": "linktree",
|
||||
"onlyDomains": null,
|
||||
"presentable": false,
|
||||
"required": false,
|
||||
"system": false,
|
||||
"type": "url"
|
||||
}))
|
||||
|
||||
// add field
|
||||
collection.fields.addAt(13, new Field({
|
||||
"exceptDomains": null,
|
||||
"hidden": false,
|
||||
"id": "url2609473773",
|
||||
"name": "carrd",
|
||||
"onlyDomains": null,
|
||||
"presentable": false,
|
||||
"required": false,
|
||||
"system": false,
|
||||
"type": "url"
|
||||
}))
|
||||
|
||||
// add field
|
||||
collection.fields.addAt(14, new Field({
|
||||
"exceptDomains": null,
|
||||
"hidden": false,
|
||||
"id": "url2799872019",
|
||||
"name": "fansly",
|
||||
"onlyDomains": null,
|
||||
"presentable": false,
|
||||
"required": false,
|
||||
"system": false,
|
||||
"type": "url"
|
||||
}))
|
||||
|
||||
// add field
|
||||
collection.fields.addAt(15, new Field({
|
||||
"exceptDomains": null,
|
||||
"hidden": false,
|
||||
"id": "url1736283674",
|
||||
"name": "pornhub",
|
||||
"onlyDomains": null,
|
||||
"presentable": false,
|
||||
"required": false,
|
||||
"system": false,
|
||||
"type": "url"
|
||||
}))
|
||||
|
||||
// add field
|
||||
collection.fields.addAt(16, new Field({
|
||||
"exceptDomains": null,
|
||||
"hidden": false,
|
||||
"id": "url1322392000",
|
||||
"name": "discord",
|
||||
"onlyDomains": null,
|
||||
"presentable": false,
|
||||
"required": false,
|
||||
"system": false,
|
||||
"type": "url"
|
||||
}))
|
||||
|
||||
// add field
|
||||
collection.fields.addAt(17, new Field({
|
||||
"exceptDomains": null,
|
||||
"hidden": false,
|
||||
"id": "url3191313207",
|
||||
"name": "reddit",
|
||||
"onlyDomains": null,
|
||||
"presentable": false,
|
||||
"required": false,
|
||||
"system": false,
|
||||
"type": "url"
|
||||
}))
|
||||
|
||||
// add field
|
||||
collection.fields.addAt(18, new Field({
|
||||
"exceptDomains": null,
|
||||
"hidden": false,
|
||||
"id": "url3425232140",
|
||||
"name": "throne",
|
||||
"onlyDomains": null,
|
||||
"presentable": false,
|
||||
"required": false,
|
||||
"system": false,
|
||||
"type": "url"
|
||||
}))
|
||||
|
||||
// add field
|
||||
collection.fields.addAt(19, new Field({
|
||||
"exceptDomains": null,
|
||||
"hidden": false,
|
||||
"id": "url2225635011",
|
||||
"name": "instagram",
|
||||
"onlyDomains": null,
|
||||
"presentable": false,
|
||||
"required": false,
|
||||
"system": false,
|
||||
"type": "url"
|
||||
}))
|
||||
|
||||
// add field
|
||||
collection.fields.addAt(20, new Field({
|
||||
"exceptDomains": null,
|
||||
"hidden": false,
|
||||
"id": "url1802815712",
|
||||
"name": "facebook",
|
||||
"onlyDomains": null,
|
||||
"presentable": false,
|
||||
"required": false,
|
||||
"system": false,
|
||||
"type": "url"
|
||||
}))
|
||||
|
||||
// add field
|
||||
collection.fields.addAt(21, new Field({
|
||||
"exceptDomains": null,
|
||||
"hidden": false,
|
||||
"id": "url4055117536",
|
||||
"name": "merch",
|
||||
"onlyDomains": null,
|
||||
"presentable": false,
|
||||
"required": false,
|
||||
"system": false,
|
||||
"type": "url"
|
||||
}))
|
||||
|
||||
// add field
|
||||
collection.fields.addAt(22, new Field({
|
||||
"convertURLs": false,
|
||||
"hidden": false,
|
||||
"id": "editor1843675174",
|
||||
"maxSize": 0,
|
||||
"name": "description",
|
||||
"presentable": false,
|
||||
"required": false,
|
||||
"system": false,
|
||||
"type": "editor"
|
||||
}))
|
||||
|
||||
// add field
|
||||
collection.fields.addAt(23, new Field({
|
||||
"hidden": false,
|
||||
"id": "number2960516043",
|
||||
"max": null,
|
||||
"min": null,
|
||||
"name": "themeColor",
|
||||
"onlyInt": false,
|
||||
"presentable": false,
|
||||
"required": false,
|
||||
"system": false,
|
||||
"type": "number"
|
||||
}))
|
||||
|
||||
return app.save(collection)
|
||||
}, (app) => {
|
||||
const collection = app.findCollectionByNameOrId("pbc_3872109612")
|
||||
|
||||
// remove field
|
||||
collection.fields.removeById("relation3825607268")
|
||||
|
||||
// remove field
|
||||
collection.fields.removeById("file3309110367")
|
||||
|
||||
// remove field
|
||||
collection.fields.removeById("url1288386755")
|
||||
|
||||
// remove field
|
||||
collection.fields.removeById("url376077238")
|
||||
|
||||
// remove field
|
||||
collection.fields.removeById("url2042351438")
|
||||
|
||||
// remove field
|
||||
collection.fields.removeById("url1928100768")
|
||||
|
||||
// remove field
|
||||
collection.fields.removeById("url847873150")
|
||||
|
||||
// remove field
|
||||
collection.fields.removeById("url1505654846")
|
||||
|
||||
// remove field
|
||||
collection.fields.removeById("url4034435380")
|
||||
|
||||
// remove field
|
||||
collection.fields.removeById("url3056519709")
|
||||
|
||||
// remove field
|
||||
collection.fields.removeById("url2609473773")
|
||||
|
||||
// remove field
|
||||
collection.fields.removeById("url2799872019")
|
||||
|
||||
// remove field
|
||||
collection.fields.removeById("url1736283674")
|
||||
|
||||
// remove field
|
||||
collection.fields.removeById("url1322392000")
|
||||
|
||||
// remove field
|
||||
collection.fields.removeById("url3191313207")
|
||||
|
||||
// remove field
|
||||
collection.fields.removeById("url3425232140")
|
||||
|
||||
// remove field
|
||||
collection.fields.removeById("url2225635011")
|
||||
|
||||
// remove field
|
||||
collection.fields.removeById("url1802815712")
|
||||
|
||||
// remove field
|
||||
collection.fields.removeById("url4055117536")
|
||||
|
||||
// remove field
|
||||
collection.fields.removeById("editor1843675174")
|
||||
|
||||
// remove field
|
||||
collection.fields.removeById("number2960516043")
|
||||
|
||||
return app.save(collection)
|
||||
})
|
||||
20
services/pocketbase/pb_migrations/1761818044_updated_vod.js
Normal file
20
services/pocketbase/pb_migrations/1761818044_updated_vod.js
Normal file
@ -0,0 +1,20 @@
|
||||
/// <reference path="../pb_data/types.d.ts" />
|
||||
migrate((app) => {
|
||||
const collection = app.findCollectionByNameOrId("pbc_144770472")
|
||||
|
||||
// update collection data
|
||||
unmarshal({
|
||||
"name": "vods"
|
||||
}, collection)
|
||||
|
||||
return app.save(collection)
|
||||
}, (app) => {
|
||||
const collection = app.findCollectionByNameOrId("pbc_144770472")
|
||||
|
||||
// update collection data
|
||||
unmarshal({
|
||||
"name": "vod"
|
||||
}, collection)
|
||||
|
||||
return app.save(collection)
|
||||
})
|
||||
@ -0,0 +1,20 @@
|
||||
/// <reference path="../pb_data/types.d.ts" />
|
||||
migrate((app) => {
|
||||
const collection = app.findCollectionByNameOrId("pbc_3872109612")
|
||||
|
||||
// update collection data
|
||||
unmarshal({
|
||||
"name": "vtubers"
|
||||
}, collection)
|
||||
|
||||
return app.save(collection)
|
||||
}, (app) => {
|
||||
const collection = app.findCollectionByNameOrId("pbc_3872109612")
|
||||
|
||||
// update collection data
|
||||
unmarshal({
|
||||
"name": "vtuber"
|
||||
}, collection)
|
||||
|
||||
return app.save(collection)
|
||||
})
|
||||
139
services/pocketbase/pb_migrations/1761818487_updated_vods.js
Normal file
139
services/pocketbase/pb_migrations/1761818487_updated_vods.js
Normal file
@ -0,0 +1,139 @@
|
||||
/// <reference path="../pb_data/types.d.ts" />
|
||||
migrate((app) => {
|
||||
const collection = app.findCollectionByNameOrId("pbc_144770472")
|
||||
|
||||
// add field
|
||||
collection.fields.addAt(3, new Field({
|
||||
"cascadeDelete": false,
|
||||
"collectionId": "_pb_users_auth_",
|
||||
"hidden": false,
|
||||
"id": "relation1668006755",
|
||||
"maxSelect": 1,
|
||||
"minSelect": 0,
|
||||
"name": "uploader",
|
||||
"presentable": false,
|
||||
"required": false,
|
||||
"system": false,
|
||||
"type": "relation"
|
||||
}))
|
||||
|
||||
// add field
|
||||
collection.fields.addAt(4, new Field({
|
||||
"convertURLs": false,
|
||||
"hidden": false,
|
||||
"id": "editor18589324",
|
||||
"maxSize": 0,
|
||||
"name": "notes",
|
||||
"presentable": false,
|
||||
"required": false,
|
||||
"system": false,
|
||||
"type": "editor"
|
||||
}))
|
||||
|
||||
// add field
|
||||
collection.fields.addAt(5, new Field({
|
||||
"hidden": false,
|
||||
"id": "json2596236420",
|
||||
"maxSize": 0,
|
||||
"name": "segmentKeys",
|
||||
"presentable": false,
|
||||
"required": false,
|
||||
"system": false,
|
||||
"type": "json"
|
||||
}))
|
||||
|
||||
// add field
|
||||
collection.fields.addAt(6, new Field({
|
||||
"hidden": false,
|
||||
"id": "file3785949232",
|
||||
"maxSelect": 1,
|
||||
"maxSize": 0,
|
||||
"mimeTypes": [],
|
||||
"name": "sourceVideo",
|
||||
"presentable": false,
|
||||
"protected": false,
|
||||
"required": false,
|
||||
"system": false,
|
||||
"thumbs": [],
|
||||
"type": "file"
|
||||
}))
|
||||
|
||||
// add field
|
||||
collection.fields.addAt(7, new Field({
|
||||
"hidden": false,
|
||||
"id": "file651090729",
|
||||
"maxSelect": 99,
|
||||
"maxSize": 0,
|
||||
"mimeTypes": [],
|
||||
"name": "segments",
|
||||
"presentable": false,
|
||||
"protected": false,
|
||||
"required": false,
|
||||
"system": false,
|
||||
"thumbs": [],
|
||||
"type": "file"
|
||||
}))
|
||||
|
||||
// add field
|
||||
collection.fields.addAt(8, new Field({
|
||||
"hidden": false,
|
||||
"id": "file3277268710",
|
||||
"maxSelect": 1,
|
||||
"maxSize": 0,
|
||||
"mimeTypes": [],
|
||||
"name": "thumbnail",
|
||||
"presentable": false,
|
||||
"protected": false,
|
||||
"required": false,
|
||||
"system": false,
|
||||
"thumbs": [],
|
||||
"type": "file"
|
||||
}))
|
||||
|
||||
// add field
|
||||
collection.fields.addAt(9, new Field({
|
||||
"hidden": false,
|
||||
"id": "select2063623452",
|
||||
"maxSelect": 1,
|
||||
"name": "status",
|
||||
"presentable": false,
|
||||
"required": false,
|
||||
"system": false,
|
||||
"type": "select",
|
||||
"values": [
|
||||
"ordering",
|
||||
"pending",
|
||||
"approved",
|
||||
"rejected",
|
||||
"processing",
|
||||
"processed"
|
||||
]
|
||||
}))
|
||||
|
||||
return app.save(collection)
|
||||
}, (app) => {
|
||||
const collection = app.findCollectionByNameOrId("pbc_144770472")
|
||||
|
||||
// remove field
|
||||
collection.fields.removeById("relation1668006755")
|
||||
|
||||
// remove field
|
||||
collection.fields.removeById("editor18589324")
|
||||
|
||||
// remove field
|
||||
collection.fields.removeById("json2596236420")
|
||||
|
||||
// remove field
|
||||
collection.fields.removeById("file3785949232")
|
||||
|
||||
// remove field
|
||||
collection.fields.removeById("file651090729")
|
||||
|
||||
// remove field
|
||||
collection.fields.removeById("file3277268710")
|
||||
|
||||
// remove field
|
||||
collection.fields.removeById("select2063623452")
|
||||
|
||||
return app.save(collection)
|
||||
})
|
||||
28
services/pocketbase/pb_migrations/1761818515_updated_vods.js
Normal file
28
services/pocketbase/pb_migrations/1761818515_updated_vods.js
Normal file
@ -0,0 +1,28 @@
|
||||
/// <reference path="../pb_data/types.d.ts" />
|
||||
migrate((app) => {
|
||||
const collection = app.findCollectionByNameOrId("pbc_144770472")
|
||||
|
||||
// add field
|
||||
collection.fields.addAt(10, new Field({
|
||||
"cascadeDelete": false,
|
||||
"collectionId": "pbc_3872109612",
|
||||
"hidden": false,
|
||||
"id": "relation3093501878",
|
||||
"maxSelect": 999,
|
||||
"minSelect": 0,
|
||||
"name": "vtubers",
|
||||
"presentable": false,
|
||||
"required": false,
|
||||
"system": false,
|
||||
"type": "relation"
|
||||
}))
|
||||
|
||||
return app.save(collection)
|
||||
}, (app) => {
|
||||
const collection = app.findCollectionByNameOrId("pbc_144770472")
|
||||
|
||||
// remove field
|
||||
collection.fields.removeById("relation3093501878")
|
||||
|
||||
return app.save(collection)
|
||||
})
|
||||
@ -0,0 +1,46 @@
|
||||
/// <reference path="../pb_data/types.d.ts" />
|
||||
migrate((app) => {
|
||||
const collection = app.findCollectionByNameOrId("pbc_3872109612")
|
||||
|
||||
// remove field
|
||||
collection.fields.removeById("number2960516043")
|
||||
|
||||
// add field
|
||||
collection.fields.addAt(23, new Field({
|
||||
"autogeneratePattern": "",
|
||||
"hidden": false,
|
||||
"id": "text2960516043",
|
||||
"max": 0,
|
||||
"min": 0,
|
||||
"name": "themeColor",
|
||||
"pattern": "",
|
||||
"presentable": false,
|
||||
"primaryKey": false,
|
||||
"required": false,
|
||||
"system": false,
|
||||
"type": "text"
|
||||
}))
|
||||
|
||||
return app.save(collection)
|
||||
}, (app) => {
|
||||
const collection = app.findCollectionByNameOrId("pbc_3872109612")
|
||||
|
||||
// add field
|
||||
collection.fields.addAt(23, new Field({
|
||||
"hidden": false,
|
||||
"id": "number2960516043",
|
||||
"max": null,
|
||||
"min": null,
|
||||
"name": "themeColor",
|
||||
"onlyInt": false,
|
||||
"presentable": false,
|
||||
"required": false,
|
||||
"system": false,
|
||||
"type": "number"
|
||||
}))
|
||||
|
||||
// remove field
|
||||
collection.fields.removeById("text2960516043")
|
||||
|
||||
return app.save(collection)
|
||||
})
|
||||
124
services/pocketbase/pb_migrations/1761915053_updated_vods.js
Normal file
124
services/pocketbase/pb_migrations/1761915053_updated_vods.js
Normal file
@ -0,0 +1,124 @@
|
||||
/// <reference path="../pb_data/types.d.ts" />
|
||||
migrate((app) => {
|
||||
const collection = app.findCollectionByNameOrId("pbc_144770472")
|
||||
|
||||
// remove field
|
||||
collection.fields.removeById("file3785949232")
|
||||
|
||||
// remove field
|
||||
collection.fields.removeById("file651090729")
|
||||
|
||||
// remove field
|
||||
collection.fields.removeById("file3277268710")
|
||||
|
||||
// add field
|
||||
collection.fields.addAt(8, new Field({
|
||||
"autogeneratePattern": "",
|
||||
"hidden": false,
|
||||
"id": "text3785949232",
|
||||
"max": 0,
|
||||
"min": 0,
|
||||
"name": "sourceVideo",
|
||||
"pattern": "",
|
||||
"presentable": false,
|
||||
"primaryKey": false,
|
||||
"required": false,
|
||||
"system": false,
|
||||
"type": "text"
|
||||
}))
|
||||
|
||||
// add field
|
||||
collection.fields.addAt(9, new Field({
|
||||
"autogeneratePattern": "",
|
||||
"hidden": false,
|
||||
"id": "text651090729",
|
||||
"max": 0,
|
||||
"min": 0,
|
||||
"name": "segments",
|
||||
"pattern": "",
|
||||
"presentable": false,
|
||||
"primaryKey": false,
|
||||
"required": false,
|
||||
"system": false,
|
||||
"type": "text"
|
||||
}))
|
||||
|
||||
// add field
|
||||
collection.fields.addAt(10, new Field({
|
||||
"autogeneratePattern": "",
|
||||
"hidden": false,
|
||||
"id": "text3277268710",
|
||||
"max": 0,
|
||||
"min": 0,
|
||||
"name": "thumbnail",
|
||||
"pattern": "",
|
||||
"presentable": false,
|
||||
"primaryKey": false,
|
||||
"required": false,
|
||||
"system": false,
|
||||
"type": "text"
|
||||
}))
|
||||
|
||||
return app.save(collection)
|
||||
}, (app) => {
|
||||
const collection = app.findCollectionByNameOrId("pbc_144770472")
|
||||
|
||||
// add field
|
||||
collection.fields.addAt(6, new Field({
|
||||
"hidden": false,
|
||||
"id": "file3785949232",
|
||||
"maxSelect": 1,
|
||||
"maxSize": 0,
|
||||
"mimeTypes": [],
|
||||
"name": "sourceVideo",
|
||||
"presentable": false,
|
||||
"protected": false,
|
||||
"required": false,
|
||||
"system": false,
|
||||
"thumbs": [],
|
||||
"type": "file"
|
||||
}))
|
||||
|
||||
// add field
|
||||
collection.fields.addAt(7, new Field({
|
||||
"hidden": false,
|
||||
"id": "file651090729",
|
||||
"maxSelect": 99,
|
||||
"maxSize": 0,
|
||||
"mimeTypes": [],
|
||||
"name": "segments",
|
||||
"presentable": false,
|
||||
"protected": false,
|
||||
"required": false,
|
||||
"system": false,
|
||||
"thumbs": [],
|
||||
"type": "file"
|
||||
}))
|
||||
|
||||
// add field
|
||||
collection.fields.addAt(8, new Field({
|
||||
"hidden": false,
|
||||
"id": "file3277268710",
|
||||
"maxSelect": 1,
|
||||
"maxSize": 0,
|
||||
"mimeTypes": [],
|
||||
"name": "thumbnail",
|
||||
"presentable": false,
|
||||
"protected": false,
|
||||
"required": false,
|
||||
"system": false,
|
||||
"thumbs": [],
|
||||
"type": "file"
|
||||
}))
|
||||
|
||||
// remove field
|
||||
collection.fields.removeById("text3785949232")
|
||||
|
||||
// remove field
|
||||
collection.fields.removeById("text651090729")
|
||||
|
||||
// remove field
|
||||
collection.fields.removeById("text3277268710")
|
||||
|
||||
return app.save(collection)
|
||||
})
|
||||
67
services/pocketbase/pb_migrations/1761915570_updated_vods.js
Normal file
67
services/pocketbase/pb_migrations/1761915570_updated_vods.js
Normal file
@ -0,0 +1,67 @@
|
||||
/// <reference path="../pb_data/types.d.ts" />
|
||||
migrate((app) => {
|
||||
const collection = app.findCollectionByNameOrId("pbc_144770472")
|
||||
|
||||
// add field
|
||||
collection.fields.addAt(11, new Field({
|
||||
"autogeneratePattern": "",
|
||||
"hidden": false,
|
||||
"id": "text3889096196",
|
||||
"max": 0,
|
||||
"min": 0,
|
||||
"name": "muxAssetId",
|
||||
"pattern": "",
|
||||
"presentable": false,
|
||||
"primaryKey": false,
|
||||
"required": false,
|
||||
"system": false,
|
||||
"type": "text"
|
||||
}))
|
||||
|
||||
// add field
|
||||
collection.fields.addAt(12, new Field({
|
||||
"autogeneratePattern": "",
|
||||
"hidden": false,
|
||||
"id": "text1061856600",
|
||||
"max": 0,
|
||||
"min": 0,
|
||||
"name": "muxPlaybackId",
|
||||
"pattern": "",
|
||||
"presentable": false,
|
||||
"primaryKey": false,
|
||||
"required": false,
|
||||
"system": false,
|
||||
"type": "text"
|
||||
}))
|
||||
|
||||
// add field
|
||||
collection.fields.addAt(13, new Field({
|
||||
"autogeneratePattern": "",
|
||||
"hidden": false,
|
||||
"id": "text1805914144",
|
||||
"max": 0,
|
||||
"min": 0,
|
||||
"name": "ipfsCid",
|
||||
"pattern": "",
|
||||
"presentable": false,
|
||||
"primaryKey": false,
|
||||
"required": false,
|
||||
"system": false,
|
||||
"type": "text"
|
||||
}))
|
||||
|
||||
return app.save(collection)
|
||||
}, (app) => {
|
||||
const collection = app.findCollectionByNameOrId("pbc_144770472")
|
||||
|
||||
// remove field
|
||||
collection.fields.removeById("text3889096196")
|
||||
|
||||
// remove field
|
||||
collection.fields.removeById("text1061856600")
|
||||
|
||||
// remove field
|
||||
collection.fields.removeById("text1805914144")
|
||||
|
||||
return app.save(collection)
|
||||
})
|
||||
29
services/pocketbase/pb_migrations/1761925981_updated_vods.js
Normal file
29
services/pocketbase/pb_migrations/1761925981_updated_vods.js
Normal file
@ -0,0 +1,29 @@
|
||||
/// <reference path="../pb_data/types.d.ts" />
|
||||
migrate((app) => {
|
||||
const collection = app.findCollectionByNameOrId("pbc_144770472")
|
||||
|
||||
// add field
|
||||
collection.fields.addAt(14, new Field({
|
||||
"autogeneratePattern": "",
|
||||
"hidden": false,
|
||||
"id": "text1646005928",
|
||||
"max": 0,
|
||||
"min": 0,
|
||||
"name": "videoSrcB2",
|
||||
"pattern": "",
|
||||
"presentable": false,
|
||||
"primaryKey": false,
|
||||
"required": false,
|
||||
"system": false,
|
||||
"type": "text"
|
||||
}))
|
||||
|
||||
return app.save(collection)
|
||||
}, (app) => {
|
||||
const collection = app.findCollectionByNameOrId("pbc_144770472")
|
||||
|
||||
// remove field
|
||||
collection.fields.removeById("text1646005928")
|
||||
|
||||
return app.save(collection)
|
||||
})
|
||||
29
services/pocketbase/pb_migrations/1762063470_updated_vods.js
Normal file
29
services/pocketbase/pb_migrations/1762063470_updated_vods.js
Normal file
@ -0,0 +1,29 @@
|
||||
/// <reference path="../pb_data/types.d.ts" />
|
||||
migrate((app) => {
|
||||
const collection = app.findCollectionByNameOrId("pbc_144770472")
|
||||
|
||||
// add field
|
||||
collection.fields.addAt(15, new Field({
|
||||
"autogeneratePattern": "",
|
||||
"hidden": false,
|
||||
"id": "text1642358089",
|
||||
"max": 0,
|
||||
"min": 0,
|
||||
"name": "muxPlaybackToken",
|
||||
"pattern": "",
|
||||
"presentable": false,
|
||||
"primaryKey": false,
|
||||
"required": false,
|
||||
"system": false,
|
||||
"type": "text"
|
||||
}))
|
||||
|
||||
return app.save(collection)
|
||||
}, (app) => {
|
||||
const collection = app.findCollectionByNameOrId("pbc_144770472")
|
||||
|
||||
// remove field
|
||||
collection.fields.removeById("text1642358089")
|
||||
|
||||
return app.save(collection)
|
||||
})
|
||||
@ -0,0 +1,24 @@
|
||||
/// <reference path="../pb_data/types.d.ts" />
|
||||
migrate((app) => {
|
||||
const collection = app.findCollectionByNameOrId("_pb_users_auth_")
|
||||
|
||||
// update collection data
|
||||
unmarshal({
|
||||
"oauth2": {
|
||||
"enabled": true
|
||||
}
|
||||
}, collection)
|
||||
|
||||
return app.save(collection)
|
||||
}, (app) => {
|
||||
const collection = app.findCollectionByNameOrId("_pb_users_auth_")
|
||||
|
||||
// update collection data
|
||||
unmarshal({
|
||||
"oauth2": {
|
||||
"enabled": false
|
||||
}
|
||||
}, collection)
|
||||
|
||||
return app.save(collection)
|
||||
})
|
||||
@ -0,0 +1,34 @@
|
||||
/// <reference path="../pb_data/types.d.ts" />
|
||||
migrate((app) => {
|
||||
const collection = app.findCollectionByNameOrId("_pb_users_auth_")
|
||||
|
||||
// add field
|
||||
collection.fields.addAt(8, new Field({
|
||||
"hidden": false,
|
||||
"id": "select66088533",
|
||||
"maxSelect": 1,
|
||||
"name": "supporter",
|
||||
"presentable": false,
|
||||
"required": false,
|
||||
"system": false,
|
||||
"type": "select",
|
||||
"values": [
|
||||
"free",
|
||||
"tier1",
|
||||
"tier2",
|
||||
"tier3",
|
||||
"tier4",
|
||||
"tier5",
|
||||
"tier6"
|
||||
]
|
||||
}))
|
||||
|
||||
return app.save(collection)
|
||||
}, (app) => {
|
||||
const collection = app.findCollectionByNameOrId("_pb_users_auth_")
|
||||
|
||||
// remove field
|
||||
collection.fields.removeById("select66088533")
|
||||
|
||||
return app.save(collection)
|
||||
})
|
||||
@ -0,0 +1,48 @@
|
||||
/// <reference path="../pb_data/types.d.ts" />
|
||||
migrate((app) => {
|
||||
const collection = app.findCollectionByNameOrId("_pb_users_auth_")
|
||||
|
||||
// remove field
|
||||
collection.fields.removeById("select66088533")
|
||||
|
||||
// add field
|
||||
collection.fields.addAt(8, new Field({
|
||||
"hidden": false,
|
||||
"id": "bool66088533",
|
||||
"name": "supporter",
|
||||
"presentable": false,
|
||||
"required": false,
|
||||
"system": false,
|
||||
"type": "bool"
|
||||
}))
|
||||
|
||||
return app.save(collection)
|
||||
}, (app) => {
|
||||
const collection = app.findCollectionByNameOrId("_pb_users_auth_")
|
||||
|
||||
// add field
|
||||
collection.fields.addAt(8, new Field({
|
||||
"hidden": false,
|
||||
"id": "select66088533",
|
||||
"maxSelect": 1,
|
||||
"name": "supporter",
|
||||
"presentable": false,
|
||||
"required": false,
|
||||
"system": false,
|
||||
"type": "select",
|
||||
"values": [
|
||||
"free",
|
||||
"tier1",
|
||||
"tier2",
|
||||
"tier3",
|
||||
"tier4",
|
||||
"tier5",
|
||||
"tier6"
|
||||
]
|
||||
}))
|
||||
|
||||
// remove field
|
||||
collection.fields.removeById("bool66088533")
|
||||
|
||||
return app.save(collection)
|
||||
})
|
||||
@ -0,0 +1,38 @@
|
||||
/// <reference path="../pb_data/types.d.ts" />
|
||||
migrate((app) => {
|
||||
const collection = app.findCollectionByNameOrId("_pb_users_auth_")
|
||||
|
||||
// remove field
|
||||
collection.fields.removeById("bool66088533")
|
||||
|
||||
// add field
|
||||
collection.fields.addAt(8, new Field({
|
||||
"hidden": false,
|
||||
"id": "bool3858055773",
|
||||
"name": "patron",
|
||||
"presentable": false,
|
||||
"required": false,
|
||||
"system": false,
|
||||
"type": "bool"
|
||||
}))
|
||||
|
||||
return app.save(collection)
|
||||
}, (app) => {
|
||||
const collection = app.findCollectionByNameOrId("_pb_users_auth_")
|
||||
|
||||
// add field
|
||||
collection.fields.addAt(8, new Field({
|
||||
"hidden": false,
|
||||
"id": "bool66088533",
|
||||
"name": "supporter",
|
||||
"presentable": false,
|
||||
"required": false,
|
||||
"system": false,
|
||||
"type": "bool"
|
||||
}))
|
||||
|
||||
// remove field
|
||||
collection.fields.removeById("bool3858055773")
|
||||
|
||||
return app.save(collection)
|
||||
})
|
||||
@ -0,0 +1,29 @@
|
||||
/// <reference path="../pb_data/types.d.ts" />
|
||||
migrate((app) => {
|
||||
const collection = app.findCollectionByNameOrId("_pb_users_auth_")
|
||||
|
||||
// add field
|
||||
collection.fields.addAt(9, new Field({
|
||||
"autogeneratePattern": "",
|
||||
"hidden": false,
|
||||
"id": "text1335658467",
|
||||
"max": 0,
|
||||
"min": 0,
|
||||
"name": "patreonId",
|
||||
"pattern": "",
|
||||
"presentable": false,
|
||||
"primaryKey": false,
|
||||
"required": false,
|
||||
"system": false,
|
||||
"type": "text"
|
||||
}))
|
||||
|
||||
return app.save(collection)
|
||||
}, (app) => {
|
||||
const collection = app.findCollectionByNameOrId("_pb_users_auth_")
|
||||
|
||||
// remove field
|
||||
collection.fields.removeById("text1335658467")
|
||||
|
||||
return app.save(collection)
|
||||
})
|
||||
@ -0,0 +1,58 @@
|
||||
/// <reference path="../pb_data/types.d.ts" />
|
||||
migrate((app) => {
|
||||
const collection = app.findCollectionByNameOrId("pbc_4199263681");
|
||||
|
||||
return app.delete(collection);
|
||||
}, (app) => {
|
||||
const collection = new Collection({
|
||||
"createRule": null,
|
||||
"deleteRule": null,
|
||||
"fields": [
|
||||
{
|
||||
"autogeneratePattern": "",
|
||||
"hidden": false,
|
||||
"id": "text3208210256",
|
||||
"max": 0,
|
||||
"min": 0,
|
||||
"name": "id",
|
||||
"pattern": "^[a-z0-9]+$",
|
||||
"presentable": false,
|
||||
"primaryKey": true,
|
||||
"required": true,
|
||||
"system": true,
|
||||
"type": "text"
|
||||
},
|
||||
{
|
||||
"hidden": false,
|
||||
"id": "json3486377887",
|
||||
"maxSize": 1,
|
||||
"name": "pending_tasks",
|
||||
"presentable": false,
|
||||
"required": false,
|
||||
"system": false,
|
||||
"type": "json"
|
||||
},
|
||||
{
|
||||
"hidden": false,
|
||||
"id": "json907408884",
|
||||
"maxSize": 1,
|
||||
"name": "failed_tasks",
|
||||
"presentable": false,
|
||||
"required": false,
|
||||
"system": false,
|
||||
"type": "json"
|
||||
}
|
||||
],
|
||||
"id": "pbc_4199263681",
|
||||
"indexes": [],
|
||||
"listRule": null,
|
||||
"name": "queue_stats",
|
||||
"system": false,
|
||||
"type": "view",
|
||||
"updateRule": null,
|
||||
"viewQuery": "SELECT queue as id,\n SUM(CASE WHEN failed IS '' THEN 1 ELSE 0 END) as pending_tasks,\n SUM(CASE WHEN failed IS NOT '' THEN 1 ELSE 0 END) as failed_tasks\n FROM queue_tasks\n GROUP BY queue;",
|
||||
"viewRule": null
|
||||
});
|
||||
|
||||
return app.save(collection);
|
||||
})
|
||||
@ -0,0 +1,87 @@
|
||||
/// <reference path="../pb_data/types.d.ts" />
|
||||
migrate((app) => {
|
||||
const collection = app.findCollectionByNameOrId("pbc_1488669058");
|
||||
|
||||
return app.delete(collection);
|
||||
}, (app) => {
|
||||
const collection = new Collection({
|
||||
"createRule": null,
|
||||
"deleteRule": null,
|
||||
"fields": [
|
||||
{
|
||||
"autogeneratePattern": "[a-z0-9]{15}",
|
||||
"hidden": false,
|
||||
"id": "text3208210256",
|
||||
"max": 15,
|
||||
"min": 15,
|
||||
"name": "id",
|
||||
"pattern": "^[a-z0-9]+$",
|
||||
"presentable": false,
|
||||
"primaryKey": true,
|
||||
"required": true,
|
||||
"system": true,
|
||||
"type": "text"
|
||||
},
|
||||
{
|
||||
"autogeneratePattern": "",
|
||||
"hidden": false,
|
||||
"id": "text1797306934",
|
||||
"max": 0,
|
||||
"min": 0,
|
||||
"name": "worker_id",
|
||||
"pattern": "",
|
||||
"presentable": false,
|
||||
"primaryKey": false,
|
||||
"required": true,
|
||||
"system": false,
|
||||
"type": "text"
|
||||
},
|
||||
{
|
||||
"cascadeDelete": false,
|
||||
"collectionId": "pbc_4107420034",
|
||||
"hidden": false,
|
||||
"id": "relation1384045349",
|
||||
"maxSelect": 1,
|
||||
"minSelect": 0,
|
||||
"name": "task",
|
||||
"presentable": false,
|
||||
"required": true,
|
||||
"system": false,
|
||||
"type": "relation"
|
||||
},
|
||||
{
|
||||
"hidden": false,
|
||||
"id": "autodate2990389176",
|
||||
"name": "created",
|
||||
"onCreate": true,
|
||||
"onUpdate": false,
|
||||
"presentable": false,
|
||||
"system": false,
|
||||
"type": "autodate"
|
||||
},
|
||||
{
|
||||
"hidden": false,
|
||||
"id": "autodate3332085495",
|
||||
"name": "updated",
|
||||
"onCreate": true,
|
||||
"onUpdate": true,
|
||||
"presentable": false,
|
||||
"system": false,
|
||||
"type": "autodate"
|
||||
}
|
||||
],
|
||||
"id": "pbc_1488669058",
|
||||
"indexes": [
|
||||
"CREATE UNIQUE INDEX idx_HSFtKfUArr ON queue_locks (task)",
|
||||
"CREATE INDEX idx_bn5iw0BzOm ON queue_locks (created)"
|
||||
],
|
||||
"listRule": null,
|
||||
"name": "queue_locks",
|
||||
"system": false,
|
||||
"type": "base",
|
||||
"updateRule": null,
|
||||
"viewRule": null
|
||||
});
|
||||
|
||||
return app.save(collection);
|
||||
})
|
||||
@ -0,0 +1,109 @@
|
||||
/// <reference path="../pb_data/types.d.ts" />
|
||||
migrate((app) => {
|
||||
const collection = app.findCollectionByNameOrId("pbc_4107420034");
|
||||
|
||||
return app.delete(collection);
|
||||
}, (app) => {
|
||||
const collection = new Collection({
|
||||
"createRule": null,
|
||||
"deleteRule": null,
|
||||
"fields": [
|
||||
{
|
||||
"autogeneratePattern": "[a-z0-9]{15}",
|
||||
"hidden": false,
|
||||
"id": "text3208210256",
|
||||
"max": 15,
|
||||
"min": 15,
|
||||
"name": "id",
|
||||
"pattern": "^[a-z0-9]+$",
|
||||
"presentable": false,
|
||||
"primaryKey": true,
|
||||
"required": true,
|
||||
"system": true,
|
||||
"type": "text"
|
||||
},
|
||||
{
|
||||
"autogeneratePattern": "",
|
||||
"hidden": false,
|
||||
"id": "text2147319651",
|
||||
"max": 0,
|
||||
"min": 0,
|
||||
"name": "queue",
|
||||
"pattern": "",
|
||||
"presentable": false,
|
||||
"primaryKey": false,
|
||||
"required": true,
|
||||
"system": false,
|
||||
"type": "text"
|
||||
},
|
||||
{
|
||||
"hidden": false,
|
||||
"id": "json1384045349",
|
||||
"maxSize": 2000000,
|
||||
"name": "task",
|
||||
"presentable": false,
|
||||
"required": false,
|
||||
"system": false,
|
||||
"type": "json"
|
||||
},
|
||||
{
|
||||
"hidden": false,
|
||||
"id": "date2659951479",
|
||||
"max": "",
|
||||
"min": "",
|
||||
"name": "failed",
|
||||
"presentable": false,
|
||||
"required": false,
|
||||
"system": false,
|
||||
"type": "date"
|
||||
},
|
||||
{
|
||||
"autogeneratePattern": "",
|
||||
"hidden": false,
|
||||
"id": "text4016436606",
|
||||
"max": 0,
|
||||
"min": 0,
|
||||
"name": "failed_reason",
|
||||
"pattern": "",
|
||||
"presentable": false,
|
||||
"primaryKey": false,
|
||||
"required": false,
|
||||
"system": false,
|
||||
"type": "text"
|
||||
},
|
||||
{
|
||||
"hidden": false,
|
||||
"id": "autodate2990389176",
|
||||
"name": "created",
|
||||
"onCreate": true,
|
||||
"onUpdate": false,
|
||||
"presentable": false,
|
||||
"system": false,
|
||||
"type": "autodate"
|
||||
},
|
||||
{
|
||||
"hidden": false,
|
||||
"id": "autodate3332085495",
|
||||
"name": "updated",
|
||||
"onCreate": true,
|
||||
"onUpdate": true,
|
||||
"presentable": false,
|
||||
"system": false,
|
||||
"type": "autodate"
|
||||
}
|
||||
],
|
||||
"id": "pbc_4107420034",
|
||||
"indexes": [
|
||||
"CREATE INDEX idx_DjQFazUd5h ON queue_tasks (\n queue,\n failed,\n created\n)",
|
||||
"CREATE INDEX idx_pUcaFfpCFF ON queue_tasks (\n failed,\n updated\n)"
|
||||
],
|
||||
"listRule": null,
|
||||
"name": "queue_tasks",
|
||||
"system": false,
|
||||
"type": "base",
|
||||
"updateRule": null,
|
||||
"viewRule": null
|
||||
});
|
||||
|
||||
return app.save(collection);
|
||||
})
|
||||
@ -0,0 +1,30 @@
|
||||
/// <reference path="../pb_data/types.d.ts" />
|
||||
migrate((app) => {
|
||||
const collection = app.findCollectionByNameOrId("_pb_users_auth_")
|
||||
|
||||
// update collection data
|
||||
unmarshal({
|
||||
"oauth2": {
|
||||
"mappedFields": {
|
||||
"avatarURL": "",
|
||||
"id": "patreonId"
|
||||
}
|
||||
}
|
||||
}, collection)
|
||||
|
||||
return app.save(collection)
|
||||
}, (app) => {
|
||||
const collection = app.findCollectionByNameOrId("_pb_users_auth_")
|
||||
|
||||
// update collection data
|
||||
unmarshal({
|
||||
"oauth2": {
|
||||
"mappedFields": {
|
||||
"avatarURL": "avatar",
|
||||
"id": ""
|
||||
}
|
||||
}
|
||||
}, collection)
|
||||
|
||||
return app.save(collection)
|
||||
})
|
||||
@ -0,0 +1,29 @@
|
||||
/// <reference path="../pb_data/types.d.ts" />
|
||||
migrate((app) => {
|
||||
const collection = app.findCollectionByNameOrId("_pb_users_auth_")
|
||||
|
||||
// add field
|
||||
collection.fields.addAt(10, new Field({
|
||||
"autogeneratePattern": "",
|
||||
"hidden": false,
|
||||
"id": "text3341984971",
|
||||
"max": 0,
|
||||
"min": 0,
|
||||
"name": "patreonAccessToken",
|
||||
"pattern": "",
|
||||
"presentable": false,
|
||||
"primaryKey": false,
|
||||
"required": false,
|
||||
"system": false,
|
||||
"type": "text"
|
||||
}))
|
||||
|
||||
return app.save(collection)
|
||||
}, (app) => {
|
||||
const collection = app.findCollectionByNameOrId("_pb_users_auth_")
|
||||
|
||||
// remove field
|
||||
collection.fields.removeById("text3341984971")
|
||||
|
||||
return app.save(collection)
|
||||
})
|
||||
BIN
services/pocketbase/pb_public/favicon.ico
Normal file
BIN
services/pocketbase/pb_public/favicon.ico
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 323 B |
1
services/pocketbase/pb_public/service-worker.js
Normal file
1
services/pocketbase/pb_public/service-worker.js
Normal file
@ -0,0 +1 @@
|
||||
// hello
|
||||
957
services/pocketbase/src/plugins/patreon/package-lock.json
generated
Normal file
957
services/pocketbase/src/plugins/patreon/package-lock.json
generated
Normal file
@ -0,0 +1,957 @@
|
||||
{
|
||||
"name": "pocketpages-plugin-patreon",
|
||||
"version": "0.0.1",
|
||||
"lockfileVersion": 3,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "pocketpages-plugin-patreon",
|
||||
"version": "0.0.1",
|
||||
"license": "Unlicense",
|
||||
"dependencies": {
|
||||
"pocketpages-plugin-js-sdk": "0.2.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"tsdown": "^0.15.12",
|
||||
"typescript": "^5.7.3"
|
||||
}
|
||||
},
|
||||
"node_modules/@babel/generator": {
|
||||
"version": "7.28.5",
|
||||
"resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.28.5.tgz",
|
||||
"integrity": "sha512-3EwLFhZ38J4VyIP6WNtt2kUdW9dokXA9Cr4IVIFHuCpZ3H8/YFOl5JjZHisrn1fATPBmKKqXzDFvh9fUwHz6CQ==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@babel/parser": "^7.28.5",
|
||||
"@babel/types": "^7.28.5",
|
||||
"@jridgewell/gen-mapping": "^0.3.12",
|
||||
"@jridgewell/trace-mapping": "^0.3.28",
|
||||
"jsesc": "^3.0.2"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=6.9.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@babel/helper-string-parser": {
|
||||
"version": "7.27.1",
|
||||
"resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.27.1.tgz",
|
||||
"integrity": "sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=6.9.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@babel/helper-validator-identifier": {
|
||||
"version": "7.28.5",
|
||||
"resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.28.5.tgz",
|
||||
"integrity": "sha512-qSs4ifwzKJSV39ucNjsvc6WVHs6b7S03sOh2OcHF9UHfVPqWWALUsNUVzhSBiItjRZoLHx7nIarVjqKVusUZ1Q==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=6.9.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@babel/parser": {
|
||||
"version": "7.28.5",
|
||||
"resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.28.5.tgz",
|
||||
"integrity": "sha512-KKBU1VGYR7ORr3At5HAtUQ+TV3SzRCXmA/8OdDZiLDBIZxVyzXuztPjfLd3BV1PRAQGCMWWSHYhL0F8d5uHBDQ==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@babel/types": "^7.28.5"
|
||||
},
|
||||
"bin": {
|
||||
"parser": "bin/babel-parser.js"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=6.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@babel/types": {
|
||||
"version": "7.28.5",
|
||||
"resolved": "https://registry.npmjs.org/@babel/types/-/types-7.28.5.tgz",
|
||||
"integrity": "sha512-qQ5m48eI/MFLQ5PxQj4PFaprjyCTLI37ElWMmNs0K8Lk3dVeOdNpB3ks8jc7yM5CDmVC73eMVk/trk3fgmrUpA==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@babel/helper-string-parser": "^7.27.1",
|
||||
"@babel/helper-validator-identifier": "^7.28.5"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=6.9.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@emnapi/core": {
|
||||
"version": "1.7.0",
|
||||
"resolved": "https://registry.npmjs.org/@emnapi/core/-/core-1.7.0.tgz",
|
||||
"integrity": "sha512-pJdKGq/1iquWYtv1RRSljZklxHCOCAJFJrImO5ZLKPJVJlVUcs8yFwNQlqS0Lo8xT1VAXXTCZocF9n26FWEKsw==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"dependencies": {
|
||||
"@emnapi/wasi-threads": "1.1.0",
|
||||
"tslib": "^2.4.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@emnapi/runtime": {
|
||||
"version": "1.7.0",
|
||||
"resolved": "https://registry.npmjs.org/@emnapi/runtime/-/runtime-1.7.0.tgz",
|
||||
"integrity": "sha512-oAYoQnCYaQZKVS53Fq23ceWMRxq5EhQsE0x0RdQ55jT7wagMu5k+fS39v1fiSLrtrLQlXwVINenqhLMtTrV/1Q==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"dependencies": {
|
||||
"tslib": "^2.4.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@emnapi/wasi-threads": {
|
||||
"version": "1.1.0",
|
||||
"resolved": "https://registry.npmjs.org/@emnapi/wasi-threads/-/wasi-threads-1.1.0.tgz",
|
||||
"integrity": "sha512-WI0DdZ8xFSbgMjR1sFsKABJ/C5OnRrjT06JXbZKexJGrDuPTzZdDYfFlsgcCXCyf+suG5QU2e/y1Wo2V/OapLQ==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"dependencies": {
|
||||
"tslib": "^2.4.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@jridgewell/gen-mapping": {
|
||||
"version": "0.3.13",
|
||||
"resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.13.tgz",
|
||||
"integrity": "sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@jridgewell/sourcemap-codec": "^1.5.0",
|
||||
"@jridgewell/trace-mapping": "^0.3.24"
|
||||
}
|
||||
},
|
||||
"node_modules/@jridgewell/resolve-uri": {
|
||||
"version": "3.1.2",
|
||||
"resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz",
|
||||
"integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=6.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@jridgewell/sourcemap-codec": {
|
||||
"version": "1.5.5",
|
||||
"resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.5.tgz",
|
||||
"integrity": "sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==",
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/@jridgewell/trace-mapping": {
|
||||
"version": "0.3.31",
|
||||
"resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.31.tgz",
|
||||
"integrity": "sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@jridgewell/resolve-uri": "^3.1.0",
|
||||
"@jridgewell/sourcemap-codec": "^1.4.14"
|
||||
}
|
||||
},
|
||||
"node_modules/@napi-rs/wasm-runtime": {
|
||||
"version": "1.0.7",
|
||||
"resolved": "https://registry.npmjs.org/@napi-rs/wasm-runtime/-/wasm-runtime-1.0.7.tgz",
|
||||
"integrity": "sha512-SeDnOO0Tk7Okiq6DbXmmBODgOAb9dp9gjlphokTUxmt8U3liIP1ZsozBahH69j/RJv+Rfs6IwUKHTgQYJ/HBAw==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"dependencies": {
|
||||
"@emnapi/core": "^1.5.0",
|
||||
"@emnapi/runtime": "^1.5.0",
|
||||
"@tybys/wasm-util": "^0.10.1"
|
||||
}
|
||||
},
|
||||
"node_modules/@oxc-project/types": {
|
||||
"version": "0.95.0",
|
||||
"resolved": "https://registry.npmjs.org/@oxc-project/types/-/types-0.95.0.tgz",
|
||||
"integrity": "sha512-vACy7vhpMPhjEJhULNxrdR0D943TkA/MigMpJCHmBHvMXxRStRi/dPtTlfQ3uDwWSzRpT8z+7ImjZVf8JWBocQ==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/Boshen"
|
||||
}
|
||||
},
|
||||
"node_modules/@quansync/fs": {
|
||||
"version": "0.1.5",
|
||||
"resolved": "https://registry.npmjs.org/@quansync/fs/-/fs-0.1.5.tgz",
|
||||
"integrity": "sha512-lNS9hL2aS2NZgNW7BBj+6EBl4rOf8l+tQ0eRY6JWCI8jI2kc53gSoqbjojU0OnAWhzoXiOjFyGsHcDGePB3lhA==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"quansync": "^0.2.11"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/sxzz"
|
||||
}
|
||||
},
|
||||
"node_modules/@rolldown/binding-android-arm64": {
|
||||
"version": "1.0.0-beta.45",
|
||||
"resolved": "https://registry.npmjs.org/@rolldown/binding-android-arm64/-/binding-android-arm64-1.0.0-beta.45.tgz",
|
||||
"integrity": "sha512-bfgKYhFiXJALeA/riil908+2vlyWGdwa7Ju5S+JgWZYdR4jtiPOGdM6WLfso1dojCh+4ZWeiTwPeV9IKQEX+4g==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"android"
|
||||
],
|
||||
"engines": {
|
||||
"node": "^20.19.0 || >=22.12.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@rolldown/binding-darwin-arm64": {
|
||||
"version": "1.0.0-beta.45",
|
||||
"resolved": "https://registry.npmjs.org/@rolldown/binding-darwin-arm64/-/binding-darwin-arm64-1.0.0-beta.45.tgz",
|
||||
"integrity": "sha512-xjCv4CRVsSnnIxTuyH1RDJl5OEQ1c9JYOwfDAHddjJDxCw46ZX9q80+xq7Eok7KC4bRSZudMJllkvOKv0T9SeA==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"darwin"
|
||||
],
|
||||
"engines": {
|
||||
"node": "^20.19.0 || >=22.12.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@rolldown/binding-darwin-x64": {
|
||||
"version": "1.0.0-beta.45",
|
||||
"resolved": "https://registry.npmjs.org/@rolldown/binding-darwin-x64/-/binding-darwin-x64-1.0.0-beta.45.tgz",
|
||||
"integrity": "sha512-ddcO9TD3D/CLUa/l8GO8LHzBOaZqWg5ClMy3jICoxwCuoz47h9dtqPsIeTiB6yR501LQTeDsjA4lIFd7u3Ljfw==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"darwin"
|
||||
],
|
||||
"engines": {
|
||||
"node": "^20.19.0 || >=22.12.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@rolldown/binding-freebsd-x64": {
|
||||
"version": "1.0.0-beta.45",
|
||||
"resolved": "https://registry.npmjs.org/@rolldown/binding-freebsd-x64/-/binding-freebsd-x64-1.0.0-beta.45.tgz",
|
||||
"integrity": "sha512-MBTWdrzW9w+UMYDUvnEuh0pQvLENkl2Sis15fHTfHVW7ClbGuez+RWopZudIDEGkpZXdeI4CkRXk+vdIIebrmg==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"freebsd"
|
||||
],
|
||||
"engines": {
|
||||
"node": "^20.19.0 || >=22.12.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@rolldown/binding-linux-arm-gnueabihf": {
|
||||
"version": "1.0.0-beta.45",
|
||||
"resolved": "https://registry.npmjs.org/@rolldown/binding-linux-arm-gnueabihf/-/binding-linux-arm-gnueabihf-1.0.0-beta.45.tgz",
|
||||
"integrity": "sha512-4YgoCFiki1HR6oSg+GxxfzfnVCesQxLF1LEnw9uXS/MpBmuog0EOO2rYfy69rWP4tFZL9IWp6KEfGZLrZ7aUog==",
|
||||
"cpu": [
|
||||
"arm"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"linux"
|
||||
],
|
||||
"engines": {
|
||||
"node": "^20.19.0 || >=22.12.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@rolldown/binding-linux-arm64-gnu": {
|
||||
"version": "1.0.0-beta.45",
|
||||
"resolved": "https://registry.npmjs.org/@rolldown/binding-linux-arm64-gnu/-/binding-linux-arm64-gnu-1.0.0-beta.45.tgz",
|
||||
"integrity": "sha512-LE1gjAwQRrbCOorJJ7LFr10s5vqYf5a00V5Ea9wXcT2+56n5YosJkcp8eQ12FxRBv2YX8dsdQJb+ZTtYJwb6XQ==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"linux"
|
||||
],
|
||||
"engines": {
|
||||
"node": "^20.19.0 || >=22.12.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@rolldown/binding-linux-arm64-musl": {
|
||||
"version": "1.0.0-beta.45",
|
||||
"resolved": "https://registry.npmjs.org/@rolldown/binding-linux-arm64-musl/-/binding-linux-arm64-musl-1.0.0-beta.45.tgz",
|
||||
"integrity": "sha512-tdy8ThO/fPp40B81v0YK3QC+KODOmzJzSUOO37DinQxzlTJ026gqUSOM8tzlVixRbQJltgVDCTYF8HNPRErQTA==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"linux"
|
||||
],
|
||||
"engines": {
|
||||
"node": "^20.19.0 || >=22.12.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@rolldown/binding-linux-x64-gnu": {
|
||||
"version": "1.0.0-beta.45",
|
||||
"resolved": "https://registry.npmjs.org/@rolldown/binding-linux-x64-gnu/-/binding-linux-x64-gnu-1.0.0-beta.45.tgz",
|
||||
"integrity": "sha512-lS082ROBWdmOyVY/0YB3JmsiClaWoxvC+dA8/rbhyB9VLkvVEaihLEOr4CYmrMse151C4+S6hCw6oa1iewox7g==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"linux"
|
||||
],
|
||||
"engines": {
|
||||
"node": "^20.19.0 || >=22.12.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@rolldown/binding-linux-x64-musl": {
|
||||
"version": "1.0.0-beta.45",
|
||||
"resolved": "https://registry.npmjs.org/@rolldown/binding-linux-x64-musl/-/binding-linux-x64-musl-1.0.0-beta.45.tgz",
|
||||
"integrity": "sha512-Hi73aYY0cBkr1/SvNQqH8Cd+rSV6S9RB5izCv0ySBcRnd/Wfn5plguUoGYwBnhHgFbh6cPw9m2dUVBR6BG1gxA==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"linux"
|
||||
],
|
||||
"engines": {
|
||||
"node": "^20.19.0 || >=22.12.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@rolldown/binding-openharmony-arm64": {
|
||||
"version": "1.0.0-beta.45",
|
||||
"resolved": "https://registry.npmjs.org/@rolldown/binding-openharmony-arm64/-/binding-openharmony-arm64-1.0.0-beta.45.tgz",
|
||||
"integrity": "sha512-fljEqbO7RHHogNDxYtTzr+GNjlfOx21RUyGmF+NrkebZ8emYYiIqzPxsaMZuRx0rgZmVmliOzEp86/CQFDKhJQ==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"openharmony"
|
||||
],
|
||||
"engines": {
|
||||
"node": "^20.19.0 || >=22.12.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@rolldown/binding-wasm32-wasi": {
|
||||
"version": "1.0.0-beta.45",
|
||||
"resolved": "https://registry.npmjs.org/@rolldown/binding-wasm32-wasi/-/binding-wasm32-wasi-1.0.0-beta.45.tgz",
|
||||
"integrity": "sha512-ZJDB7lkuZE9XUnWQSYrBObZxczut+8FZ5pdanm8nNS1DAo8zsrPuvGwn+U3fwU98WaiFsNrA4XHngesCGr8tEQ==",
|
||||
"cpu": [
|
||||
"wasm32"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"dependencies": {
|
||||
"@napi-rs/wasm-runtime": "^1.0.7"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=14.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@rolldown/binding-win32-arm64-msvc": {
|
||||
"version": "1.0.0-beta.45",
|
||||
"resolved": "https://registry.npmjs.org/@rolldown/binding-win32-arm64-msvc/-/binding-win32-arm64-msvc-1.0.0-beta.45.tgz",
|
||||
"integrity": "sha512-zyzAjItHPUmxg6Z8SyRhLdXlJn3/D9KL5b9mObUrBHhWS/GwRH4665xCiFqeuktAhhWutqfc+rOV2LjK4VYQGQ==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"win32"
|
||||
],
|
||||
"engines": {
|
||||
"node": "^20.19.0 || >=22.12.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@rolldown/binding-win32-ia32-msvc": {
|
||||
"version": "1.0.0-beta.45",
|
||||
"resolved": "https://registry.npmjs.org/@rolldown/binding-win32-ia32-msvc/-/binding-win32-ia32-msvc-1.0.0-beta.45.tgz",
|
||||
"integrity": "sha512-wODcGzlfxqS6D7BR0srkJk3drPwXYLu7jPHN27ce2c4PUnVVmJnp9mJzUQGT4LpmHmmVdMZ+P6hKvyTGBzc1CA==",
|
||||
"cpu": [
|
||||
"ia32"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"win32"
|
||||
],
|
||||
"engines": {
|
||||
"node": "^20.19.0 || >=22.12.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@rolldown/binding-win32-x64-msvc": {
|
||||
"version": "1.0.0-beta.45",
|
||||
"resolved": "https://registry.npmjs.org/@rolldown/binding-win32-x64-msvc/-/binding-win32-x64-msvc-1.0.0-beta.45.tgz",
|
||||
"integrity": "sha512-wiU40G1nQo9rtfvF9jLbl79lUgjfaD/LTyUEw2Wg/gdF5OhjzpKMVugZQngO+RNdwYaNj+Fs+kWBWfp4VXPMHA==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"win32"
|
||||
],
|
||||
"engines": {
|
||||
"node": "^20.19.0 || >=22.12.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@rolldown/pluginutils": {
|
||||
"version": "1.0.0-beta.45",
|
||||
"resolved": "https://registry.npmjs.org/@rolldown/pluginutils/-/pluginutils-1.0.0-beta.45.tgz",
|
||||
"integrity": "sha512-Le9ulGCrD8ggInzWw/k2J8QcbPz7eGIOWqfJ2L+1R0Opm7n6J37s2hiDWlh6LJN0Lk9L5sUzMvRHKW7UxBZsQA==",
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/@tybys/wasm-util": {
|
||||
"version": "0.10.1",
|
||||
"resolved": "https://registry.npmjs.org/@tybys/wasm-util/-/wasm-util-0.10.1.tgz",
|
||||
"integrity": "sha512-9tTaPJLSiejZKx+Bmog4uSubteqTvFrVrURwkmHixBo0G4seD0zUxp98E1DzUBJxLQ3NPwXrGKDiVjwx/DpPsg==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"dependencies": {
|
||||
"tslib": "^2.4.0"
|
||||
}
|
||||
},
|
||||
"node_modules/ansis": {
|
||||
"version": "4.2.0",
|
||||
"resolved": "https://registry.npmjs.org/ansis/-/ansis-4.2.0.tgz",
|
||||
"integrity": "sha512-HqZ5rWlFjGiV0tDm3UxxgNRqsOTniqoKZu0pIAfh7TZQMGuZK+hH0drySty0si0QXj1ieop4+SkSfPZBPPkHig==",
|
||||
"dev": true,
|
||||
"license": "ISC",
|
||||
"engines": {
|
||||
"node": ">=14"
|
||||
}
|
||||
},
|
||||
"node_modules/ast-kit": {
|
||||
"version": "2.1.3",
|
||||
"resolved": "https://registry.npmjs.org/ast-kit/-/ast-kit-2.1.3.tgz",
|
||||
"integrity": "sha512-TH+b3Lv6pUjy/Nu0m6A2JULtdzLpmqF9x1Dhj00ZoEiML8qvVA9j1flkzTKNYgdEhWrjDwtWNpyyCUbfQe514g==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@babel/parser": "^7.28.4",
|
||||
"pathe": "^2.0.3"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=20.19.0"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/sxzz"
|
||||
}
|
||||
},
|
||||
"node_modules/birpc": {
|
||||
"version": "2.6.1",
|
||||
"resolved": "https://registry.npmjs.org/birpc/-/birpc-2.6.1.tgz",
|
||||
"integrity": "sha512-LPnFhlDpdSH6FJhJyn4M0kFO7vtQ5iPw24FnG0y21q09xC7e8+1LeR31S1MAIrDAHp4m7aas4bEkTDTvMAtebQ==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/antfu"
|
||||
}
|
||||
},
|
||||
"node_modules/cac": {
|
||||
"version": "6.7.14",
|
||||
"resolved": "https://registry.npmjs.org/cac/-/cac-6.7.14.tgz",
|
||||
"integrity": "sha512-b6Ilus+c3RrdDk+JhLKUAQfzzgLEPy6wcXqS7f/xe1EETvsDP6GORG7SFuOs6cID5YkqchW/LXZbX5bc8j7ZcQ==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=8"
|
||||
}
|
||||
},
|
||||
"node_modules/chokidar": {
|
||||
"version": "4.0.3",
|
||||
"resolved": "https://registry.npmjs.org/chokidar/-/chokidar-4.0.3.tgz",
|
||||
"integrity": "sha512-Qgzu8kfBvo+cA4962jnP1KkS6Dop5NS6g7R5LFYJr4b8Ub94PPQXUksCw9PvXoeXPRRddRNC5C1JQUR2SMGtnA==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"readdirp": "^4.0.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 14.16.0"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://paulmillr.com/funding/"
|
||||
}
|
||||
},
|
||||
"node_modules/debug": {
|
||||
"version": "4.4.3",
|
||||
"resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz",
|
||||
"integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"ms": "^2.1.3"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=6.0"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"supports-color": {
|
||||
"optional": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/defu": {
|
||||
"version": "6.1.4",
|
||||
"resolved": "https://registry.npmjs.org/defu/-/defu-6.1.4.tgz",
|
||||
"integrity": "sha512-mEQCMmwJu317oSz8CwdIOdwf3xMif1ttiM8LTufzc3g6kR+9Pe236twL8j3IYT1F7GfRgGcW6MWxzZjLIkuHIg==",
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/diff": {
|
||||
"version": "8.0.2",
|
||||
"resolved": "https://registry.npmjs.org/diff/-/diff-8.0.2.tgz",
|
||||
"integrity": "sha512-sSuxWU5j5SR9QQji/o2qMvqRNYRDOcBTgsJ/DeCf4iSN4gW+gNMXM7wFIP+fdXZxoNiAnHUTGjCr+TSWXdRDKg==",
|
||||
"dev": true,
|
||||
"license": "BSD-3-Clause",
|
||||
"engines": {
|
||||
"node": ">=0.3.1"
|
||||
}
|
||||
},
|
||||
"node_modules/dts-resolver": {
|
||||
"version": "2.1.2",
|
||||
"resolved": "https://registry.npmjs.org/dts-resolver/-/dts-resolver-2.1.2.tgz",
|
||||
"integrity": "sha512-xeXHBQkn2ISSXxbJWD828PFjtyg+/UrMDo7W4Ffcs7+YWCquxU8YjV1KoxuiL+eJ5pg3ll+bC6flVv61L3LKZg==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=20.18.0"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/sxzz"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"oxc-resolver": ">=11.0.0"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"oxc-resolver": {
|
||||
"optional": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/empathic": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/empathic/-/empathic-2.0.0.tgz",
|
||||
"integrity": "sha512-i6UzDscO/XfAcNYD75CfICkmfLedpyPDdozrLMmQc5ORaQcdMoc21OnlEylMIqI7U8eniKrPMxxtj8k0vhmJhA==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=14"
|
||||
}
|
||||
},
|
||||
"node_modules/fdir": {
|
||||
"version": "6.5.0",
|
||||
"resolved": "https://registry.npmjs.org/fdir/-/fdir-6.5.0.tgz",
|
||||
"integrity": "sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=12.0.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"picomatch": "^3 || ^4"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"picomatch": {
|
||||
"optional": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/get-tsconfig": {
|
||||
"version": "4.13.0",
|
||||
"resolved": "https://registry.npmjs.org/get-tsconfig/-/get-tsconfig-4.13.0.tgz",
|
||||
"integrity": "sha512-1VKTZJCwBrvbd+Wn3AOgQP/2Av+TfTCOlE4AcRJE72W1ksZXbAx8PPBR9RzgTeSPzlPMHrbANMH3LbltH73wxQ==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"resolve-pkg-maps": "^1.0.0"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/privatenumber/get-tsconfig?sponsor=1"
|
||||
}
|
||||
},
|
||||
"node_modules/hookable": {
|
||||
"version": "5.5.3",
|
||||
"resolved": "https://registry.npmjs.org/hookable/-/hookable-5.5.3.tgz",
|
||||
"integrity": "sha512-Yc+BQe8SvoXH1643Qez1zqLRmbA5rCL+sSmk6TVos0LWVfNIB7PGncdlId77WzLGSIB5KaWgTaNTs2lNVEI6VQ==",
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/jiti": {
|
||||
"version": "2.6.1",
|
||||
"resolved": "https://registry.npmjs.org/jiti/-/jiti-2.6.1.tgz",
|
||||
"integrity": "sha512-ekilCSN1jwRvIbgeg/57YFh8qQDNbwDb9xT/qu2DAHbFFZUicIl4ygVaAvzveMhMVr3LnpSKTNnwt8PoOfmKhQ==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"bin": {
|
||||
"jiti": "lib/jiti-cli.mjs"
|
||||
}
|
||||
},
|
||||
"node_modules/jsesc": {
|
||||
"version": "3.1.0",
|
||||
"resolved": "https://registry.npmjs.org/jsesc/-/jsesc-3.1.0.tgz",
|
||||
"integrity": "sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"bin": {
|
||||
"jsesc": "bin/jsesc"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=6"
|
||||
}
|
||||
},
|
||||
"node_modules/magic-string": {
|
||||
"version": "0.30.21",
|
||||
"resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.21.tgz",
|
||||
"integrity": "sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@jridgewell/sourcemap-codec": "^1.5.5"
|
||||
}
|
||||
},
|
||||
"node_modules/ms": {
|
||||
"version": "2.1.3",
|
||||
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
|
||||
"integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==",
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/pathe": {
|
||||
"version": "2.0.3",
|
||||
"resolved": "https://registry.npmjs.org/pathe/-/pathe-2.0.3.tgz",
|
||||
"integrity": "sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w==",
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/picomatch": {
|
||||
"version": "4.0.3",
|
||||
"resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.3.tgz",
|
||||
"integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/jonschlinkert"
|
||||
}
|
||||
},
|
||||
"node_modules/pocketbase-js-sdk-jsvm": {
|
||||
"version": "0.25.10004",
|
||||
"resolved": "https://registry.npmjs.org/pocketbase-js-sdk-jsvm/-/pocketbase-js-sdk-jsvm-0.25.10004.tgz",
|
||||
"integrity": "sha512-/0RkFa6X4LeKMdv4KCXhC5i2cvpG0elvXInRyk8bApjG8jyyPiNDL6o9VBvgxjl6j8/HcQYf3oKYXmZteqAFvQ==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/pocketpages-plugin-js-sdk": {
|
||||
"version": "0.2.0",
|
||||
"resolved": "https://registry.npmjs.org/pocketpages-plugin-js-sdk/-/pocketpages-plugin-js-sdk-0.2.0.tgz",
|
||||
"integrity": "sha512-/uY1nCz7Zt19C/kyoOraH5ekTZa4PLPpHd0qIEoyf1XBPtEpHL4k7jZE0IPEMu1dH/8RfsKb/YzN52GR+9DdzQ==",
|
||||
"dependencies": {
|
||||
"pocketbase-js-sdk-jsvm": "^0.25.10004"
|
||||
}
|
||||
},
|
||||
"node_modules/quansync": {
|
||||
"version": "0.2.11",
|
||||
"resolved": "https://registry.npmjs.org/quansync/-/quansync-0.2.11.tgz",
|
||||
"integrity": "sha512-AifT7QEbW9Nri4tAwR5M/uzpBuqfZf+zwaEM/QkzEjj7NBuFD2rBuy0K3dE+8wltbezDV7JMA0WfnCPYRSYbXA==",
|
||||
"dev": true,
|
||||
"funding": [
|
||||
{
|
||||
"type": "individual",
|
||||
"url": "https://github.com/sponsors/antfu"
|
||||
},
|
||||
{
|
||||
"type": "individual",
|
||||
"url": "https://github.com/sponsors/sxzz"
|
||||
}
|
||||
],
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/readdirp": {
|
||||
"version": "4.1.2",
|
||||
"resolved": "https://registry.npmjs.org/readdirp/-/readdirp-4.1.2.tgz",
|
||||
"integrity": "sha512-GDhwkLfywWL2s6vEjyhri+eXmfH6j1L7JE27WhqLeYzoh/A3DBaYGEj2H/HFZCn/kMfim73FXxEJTw06WtxQwg==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">= 14.18.0"
|
||||
},
|
||||
"funding": {
|
||||
"type": "individual",
|
||||
"url": "https://paulmillr.com/funding/"
|
||||
}
|
||||
},
|
||||
"node_modules/resolve-pkg-maps": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/resolve-pkg-maps/-/resolve-pkg-maps-1.0.0.tgz",
|
||||
"integrity": "sha512-seS2Tj26TBVOC2NIc2rOe2y2ZO7efxITtLZcGSOnHHNOQ7CkiUBfw0Iw2ck6xkIhPwLhKNLS8BO+hEpngQlqzw==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"funding": {
|
||||
"url": "https://github.com/privatenumber/resolve-pkg-maps?sponsor=1"
|
||||
}
|
||||
},
|
||||
"node_modules/rolldown": {
|
||||
"version": "1.0.0-beta.45",
|
||||
"resolved": "https://registry.npmjs.org/rolldown/-/rolldown-1.0.0-beta.45.tgz",
|
||||
"integrity": "sha512-iMmuD72XXLf26Tqrv1cryNYLX6NNPLhZ3AmNkSf8+xda0H+yijjGJ+wVT9UdBUHOpKzq9RjKtQKRCWoEKQQBZQ==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@oxc-project/types": "=0.95.0",
|
||||
"@rolldown/pluginutils": "1.0.0-beta.45"
|
||||
},
|
||||
"bin": {
|
||||
"rolldown": "bin/cli.mjs"
|
||||
},
|
||||
"engines": {
|
||||
"node": "^20.19.0 || >=22.12.0"
|
||||
},
|
||||
"optionalDependencies": {
|
||||
"@rolldown/binding-android-arm64": "1.0.0-beta.45",
|
||||
"@rolldown/binding-darwin-arm64": "1.0.0-beta.45",
|
||||
"@rolldown/binding-darwin-x64": "1.0.0-beta.45",
|
||||
"@rolldown/binding-freebsd-x64": "1.0.0-beta.45",
|
||||
"@rolldown/binding-linux-arm-gnueabihf": "1.0.0-beta.45",
|
||||
"@rolldown/binding-linux-arm64-gnu": "1.0.0-beta.45",
|
||||
"@rolldown/binding-linux-arm64-musl": "1.0.0-beta.45",
|
||||
"@rolldown/binding-linux-x64-gnu": "1.0.0-beta.45",
|
||||
"@rolldown/binding-linux-x64-musl": "1.0.0-beta.45",
|
||||
"@rolldown/binding-openharmony-arm64": "1.0.0-beta.45",
|
||||
"@rolldown/binding-wasm32-wasi": "1.0.0-beta.45",
|
||||
"@rolldown/binding-win32-arm64-msvc": "1.0.0-beta.45",
|
||||
"@rolldown/binding-win32-ia32-msvc": "1.0.0-beta.45",
|
||||
"@rolldown/binding-win32-x64-msvc": "1.0.0-beta.45"
|
||||
}
|
||||
},
|
||||
"node_modules/rolldown-plugin-dts": {
|
||||
"version": "0.17.3",
|
||||
"resolved": "https://registry.npmjs.org/rolldown-plugin-dts/-/rolldown-plugin-dts-0.17.3.tgz",
|
||||
"integrity": "sha512-8mGnNUVNrqEdTnrlcaDxs4sAZg0No6njO+FuhQd4L56nUbJO1tHxOoKDH3mmMJg7f/BhEj/1KjU5W9kZ9zM/kQ==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@babel/generator": "^7.28.5",
|
||||
"@babel/parser": "^7.28.5",
|
||||
"@babel/types": "^7.28.5",
|
||||
"ast-kit": "^2.1.3",
|
||||
"birpc": "^2.6.1",
|
||||
"debug": "^4.4.3",
|
||||
"dts-resolver": "^2.1.2",
|
||||
"get-tsconfig": "^4.13.0",
|
||||
"magic-string": "^0.30.21"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=20.18.0"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/sxzz"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@ts-macro/tsc": "^0.3.6",
|
||||
"@typescript/native-preview": ">=7.0.0-dev.20250601.1",
|
||||
"rolldown": "^1.0.0-beta.44",
|
||||
"typescript": "^5.0.0",
|
||||
"vue-tsc": "~3.1.0"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"@ts-macro/tsc": {
|
||||
"optional": true
|
||||
},
|
||||
"@typescript/native-preview": {
|
||||
"optional": true
|
||||
},
|
||||
"typescript": {
|
||||
"optional": true
|
||||
},
|
||||
"vue-tsc": {
|
||||
"optional": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/semver": {
|
||||
"version": "7.7.3",
|
||||
"resolved": "https://registry.npmjs.org/semver/-/semver-7.7.3.tgz",
|
||||
"integrity": "sha512-SdsKMrI9TdgjdweUSR9MweHA4EJ8YxHn8DFaDisvhVlUOe4BF1tLD7GAj0lIqWVl+dPb/rExr0Btby5loQm20Q==",
|
||||
"dev": true,
|
||||
"license": "ISC",
|
||||
"bin": {
|
||||
"semver": "bin/semver.js"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=10"
|
||||
}
|
||||
},
|
||||
"node_modules/tinyexec": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/tinyexec/-/tinyexec-1.0.1.tgz",
|
||||
"integrity": "sha512-5uC6DDlmeqiOwCPmK9jMSdOuZTh8bU39Ys6yidB+UTt5hfZUPGAypSgFRiEp+jbi9qH40BLDvy85jIU88wKSqw==",
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/tinyglobby": {
|
||||
"version": "0.2.15",
|
||||
"resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.15.tgz",
|
||||
"integrity": "sha512-j2Zq4NyQYG5XMST4cbs02Ak8iJUdxRM0XI5QyxXuZOzKOINmWurp3smXu3y5wDcJrptwpSjgXHzIQxR0omXljQ==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"fdir": "^6.5.0",
|
||||
"picomatch": "^4.0.3"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=12.0.0"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/SuperchupuDev"
|
||||
}
|
||||
},
|
||||
"node_modules/tree-kill": {
|
||||
"version": "1.2.2",
|
||||
"resolved": "https://registry.npmjs.org/tree-kill/-/tree-kill-1.2.2.tgz",
|
||||
"integrity": "sha512-L0Orpi8qGpRG//Nd+H90vFB+3iHnue1zSSGmNOOCh1GLJ7rUKVwV2HvijphGQS2UmhUZewS9VgvxYIdgr+fG1A==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"bin": {
|
||||
"tree-kill": "cli.js"
|
||||
}
|
||||
},
|
||||
"node_modules/tsdown": {
|
||||
"version": "0.15.12",
|
||||
"resolved": "https://registry.npmjs.org/tsdown/-/tsdown-0.15.12.tgz",
|
||||
"integrity": "sha512-c8VLlQm8/lFrOAg5VMVeN4NAbejZyVQkzd+ErjuaQgJFI/9MhR9ivr0H/CM7UlOF1+ELlF6YaI7sU/4itgGQ8w==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"ansis": "^4.2.0",
|
||||
"cac": "^6.7.14",
|
||||
"chokidar": "^4.0.3",
|
||||
"debug": "^4.4.3",
|
||||
"diff": "^8.0.2",
|
||||
"empathic": "^2.0.0",
|
||||
"hookable": "^5.5.3",
|
||||
"rolldown": "1.0.0-beta.45",
|
||||
"rolldown-plugin-dts": "^0.17.2",
|
||||
"semver": "^7.7.3",
|
||||
"tinyexec": "^1.0.1",
|
||||
"tinyglobby": "^0.2.15",
|
||||
"tree-kill": "^1.2.2",
|
||||
"unconfig": "^7.3.3"
|
||||
},
|
||||
"bin": {
|
||||
"tsdown": "dist/run.mjs"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=20.19.0"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/sxzz"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@arethetypeswrong/core": "^0.18.1",
|
||||
"publint": "^0.3.0",
|
||||
"typescript": "^5.0.0",
|
||||
"unplugin-lightningcss": "^0.4.0",
|
||||
"unplugin-unused": "^0.5.0",
|
||||
"unrun": "^0.2.1"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"@arethetypeswrong/core": {
|
||||
"optional": true
|
||||
},
|
||||
"publint": {
|
||||
"optional": true
|
||||
},
|
||||
"typescript": {
|
||||
"optional": true
|
||||
},
|
||||
"unplugin-lightningcss": {
|
||||
"optional": true
|
||||
},
|
||||
"unplugin-unused": {
|
||||
"optional": true
|
||||
},
|
||||
"unrun": {
|
||||
"optional": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/tslib": {
|
||||
"version": "2.8.1",
|
||||
"resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz",
|
||||
"integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==",
|
||||
"dev": true,
|
||||
"license": "0BSD",
|
||||
"optional": true
|
||||
},
|
||||
"node_modules/typescript": {
|
||||
"version": "5.9.3",
|
||||
"resolved": "https://registry.npmjs.org/typescript/-/typescript-5.9.3.tgz",
|
||||
"integrity": "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==",
|
||||
"dev": true,
|
||||
"license": "Apache-2.0",
|
||||
"bin": {
|
||||
"tsc": "bin/tsc",
|
||||
"tsserver": "bin/tsserver"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=14.17"
|
||||
}
|
||||
},
|
||||
"node_modules/unconfig": {
|
||||
"version": "7.3.3",
|
||||
"resolved": "https://registry.npmjs.org/unconfig/-/unconfig-7.3.3.tgz",
|
||||
"integrity": "sha512-QCkQoOnJF8L107gxfHL0uavn7WD9b3dpBcFX6HtfQYmjw2YzWxGuFQ0N0J6tE9oguCBJn9KOvfqYDCMPHIZrBA==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@quansync/fs": "^0.1.5",
|
||||
"defu": "^6.1.4",
|
||||
"jiti": "^2.5.1",
|
||||
"quansync": "^0.2.11"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/antfu"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
19
services/pocketbase/src/plugins/patreon/package.json
Normal file
19
services/pocketbase/src/plugins/patreon/package.json
Normal file
@ -0,0 +1,19 @@
|
||||
{
|
||||
"name": "pocketpages-plugin-patreon",
|
||||
"version": "0.0.1",
|
||||
"description": "",
|
||||
"main": "dist/index.js",
|
||||
"scripts": {
|
||||
"test": "echo \"Error: no test specified\" && exit 1",
|
||||
"build": "tsdown",
|
||||
"dev": "tsdown --watch"
|
||||
},
|
||||
"dependencies": {
|
||||
"pocketpages-plugin-js-sdk": "0.2.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"tsdown": "^0.15.12",
|
||||
"typescript": "^5.7.3"
|
||||
},
|
||||
"license": "Unlicense"
|
||||
}
|
||||
40
services/pocketbase/src/plugins/patreon/src/index.ts
Normal file
40
services/pocketbase/src/plugins/patreon/src/index.ts
Normal file
@ -0,0 +1,40 @@
|
||||
import { type ExtendContextApiContext } from 'pocketpages'
|
||||
import PocketBase, {
|
||||
AuthModel,
|
||||
RecordAuthResponse,
|
||||
} from 'pocketbase-js-sdk-jsvm'
|
||||
import { type OAuth2SignInOptions } from 'pocketpages-plugin-auth'
|
||||
import { PluginFactory } from 'pocketpages'
|
||||
import { OAuth2ProviderInfo } from 'pocketpages-plugin-auth'
|
||||
|
||||
const authPluginFactory: PluginFactory = (config) => {
|
||||
return {
|
||||
name: 'patreon',
|
||||
onExtendContextApi(context: ExtendContextApiContext) {
|
||||
const { api } = context;
|
||||
const pb = () => api.pb() as PocketBase
|
||||
|
||||
|
||||
api.savePatreonData = (
|
||||
authData: AuthModel
|
||||
) => {
|
||||
pb.collection('users')
|
||||
},
|
||||
|
||||
api.getPatreonUser = (
|
||||
authData: AuthModel,
|
||||
) => {
|
||||
|
||||
|
||||
console.log("AYO we got authData as follo");
|
||||
console.log(JSON.stringify(authData, null, 2));
|
||||
|
||||
// make a request to Patreon
|
||||
|
||||
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
export default authPluginFactory;
|
||||
19
services/pocketbase/src/plugins/patreon/tsconfig.json
Normal file
19
services/pocketbase/src/plugins/patreon/tsconfig.json
Normal file
@ -0,0 +1,19 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"types": [
|
||||
"pocketbase-jsvm"
|
||||
],
|
||||
"strict": true,
|
||||
"strictNullChecks": true,
|
||||
"noUncheckedIndexedAccess": true,
|
||||
"noImplicitAny": true,
|
||||
"target": "ES6",
|
||||
"module": "CommonJS",
|
||||
"moduleResolution": "node",
|
||||
"esModuleInterop": true,
|
||||
"resolveJsonModule": true
|
||||
},
|
||||
"include": [
|
||||
"src/**/*.ts"
|
||||
]
|
||||
}
|
||||
10
services/pocketbase/src/plugins/patreon/tsdown.config.ts
Normal file
10
services/pocketbase/src/plugins/patreon/tsdown.config.ts
Normal file
@ -0,0 +1,10 @@
|
||||
import { defineConfig } from 'tsdown'
|
||||
|
||||
export default defineConfig({
|
||||
entry: {
|
||||
index: 'src/index.ts',
|
||||
},
|
||||
format: ['cjs'],
|
||||
clean: true,
|
||||
outDir: 'dist',
|
||||
})
|
||||
14
services/pocketbase/systemd/pocketbase.service
Normal file
14
services/pocketbase/systemd/pocketbase.service
Normal file
@ -0,0 +1,14 @@
|
||||
[Service]
|
||||
Type = simple
|
||||
User = pb
|
||||
Group = pb
|
||||
LimitNOFILE = 4096
|
||||
Restart = always
|
||||
RestartSec = 5s
|
||||
StandardOutput = append:/home/pb/pb/std.log
|
||||
StandardError = append:/home/pb/pb/std.log
|
||||
WorkingDirectory = /home/pb/pb
|
||||
ExecStart = /home/pb/pb/pocketbase serve
|
||||
|
||||
[Install]
|
||||
WantedBy = multi-user.target
|
||||
@ -0,0 +1,8 @@
|
||||
#!/bin/bash
|
||||
|
||||
# This script must run from project root
|
||||
|
||||
|
||||
npx @dotenvx/dotenvx run -f ./.env.development.local -- node ./utils/data_migrations/2025-10-30-v1-export.js ./utils/data_migrations
|
||||
pocketbase import ./utils/data_migrations/vtubers.json vtubers
|
||||
pocketbase import ./utils/data_migrations/vods.json vods
|
||||
@ -0,0 +1,172 @@
|
||||
|
||||
|
||||
/**
|
||||
* Migration Script: V1 → json
|
||||
* -----------------------------------
|
||||
* This script migrates VTuber and VOD data from an old Postgres database (V1) into JSON files
|
||||
* One JSON file per collection, suitable for importing using pocketbase import script
|
||||
*
|
||||
* Usage:
|
||||
* - Ensure environment variables are configured for both databases:
|
||||
* V1_DB_HOST Hostname of the V1 database (default: "localhost")
|
||||
* V1_DB_PORT Port of the V1 database (default: "5444")
|
||||
* V1_DB_USER Username for the V1 database (default: "postgres")
|
||||
* V1_DB_PASS Password for the V1 database (default: "password")
|
||||
* V1_DB_NAME Database name for V1 (default: "restoredb")
|
||||
* DEFAULT_UPLOADER_ID
|
||||
* An existing user ID in the V2 database that will be set as the uploader for all migrated records.
|
||||
*
|
||||
* Usage:
|
||||
* Run with Node.js:
|
||||
* $ npx @dotenvx/dotenvx run -f ./.env.local -- node ./2025-10-30-v1-export.js ../pb_data/
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
import pg from 'pg';
|
||||
import fs from 'fs';
|
||||
import path from 'path';
|
||||
|
||||
const dataDir = process.argv[2]; // e.g., "../../pb_data/"
|
||||
if (!dataDir) {
|
||||
console.error("Please provide the output data directory as the first argument.");
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
|
||||
const v1 = new pg.Pool({
|
||||
host: process.env.V1_DB_HOST || 'localhost',
|
||||
port: +(process.env.V1_DB_PORT || '5444'),
|
||||
user: process.env.V1_DB_USER || 'postgres',
|
||||
password: process.env.V1_DB_PASS || 'password',
|
||||
database: process.env.V1_DB_NAME || 'restoredb'
|
||||
});
|
||||
|
||||
async function migrateVtubers() {
|
||||
console.log('Migrating vtubers...');
|
||||
const res = await v1.query(`SELECT * FROM vtubers`);
|
||||
const vtubers = res.rows.map(vt => ({
|
||||
slug: vt.slug,
|
||||
displayName: vt.display_name,
|
||||
chaturbate: vt.chaturbate,
|
||||
twitter: vt.twitter,
|
||||
patreon: vt.patreon,
|
||||
twitch: vt.twitch,
|
||||
tiktok: vt.tiktok,
|
||||
onlyfans: vt.onlyfans,
|
||||
youtube: vt.youtube,
|
||||
linktree: vt.linktree,
|
||||
carrd: vt.carrd,
|
||||
fansly: vt.fansly,
|
||||
pornhub: vt.pornhub,
|
||||
discord: vt.discord,
|
||||
reddit: vt.reddit,
|
||||
throne: vt.throne,
|
||||
instagram: vt.instagram,
|
||||
facebook: vt.facebook,
|
||||
merch: vt.merch,
|
||||
description: `${vt.description_1 ?? ''}\n${vt.description_2 ?? ''}`.trim() || null,
|
||||
themeColor: vt.theme_color,
|
||||
}));
|
||||
|
||||
console.log('vtubers sample', vtubers.at(0))
|
||||
|
||||
const outPath = path.join(dataDir, 'vtubers.json');
|
||||
fs.writeFileSync(outPath, JSON.stringify(vtubers, null, 2), 'utf-8');
|
||||
console.log(`Migrated ${res.rows.length} vtubers → ${outPath}`);
|
||||
}
|
||||
|
||||
async function migrateVods() {
|
||||
console.log('Migrating vods...');
|
||||
const res = await v1.query(`SELECT * FROM vods`);
|
||||
const vods = [];
|
||||
|
||||
for (const vod of res.rows) {
|
||||
// Get linked vtubers
|
||||
const vtuberLinks = await v1.query(
|
||||
`SELECT vtuber_id FROM vods_vtuber_links WHERE vod_id = $1`,
|
||||
[vod.id]
|
||||
);
|
||||
|
||||
let vtuberIds = [];
|
||||
if (vtuberLinks.rows.length > 0) {
|
||||
const vtuberRes = await v1.query(
|
||||
`SELECT id FROM vtubers WHERE id = ANY($1)`,
|
||||
[vtuberLinks.rows.map(r => r.vtuber_id)]
|
||||
);
|
||||
vtuberIds = vtuberRes.rows.map(v => v.id).filter(Boolean);
|
||||
}
|
||||
|
||||
// Get thumbnail
|
||||
const thumbLink = await v1.query(
|
||||
`SELECT b2.cdn_url, b2.url FROM vods_thumbnail_links vtl
|
||||
JOIN b2_files b2 ON vtl.b_2_file_id = b2.id
|
||||
WHERE vtl.vod_id = $1 LIMIT 1`,
|
||||
[vod.id]
|
||||
);
|
||||
|
||||
// Get source video
|
||||
const videoSrcLink = await v1.query(
|
||||
`SELECT b2.cdn_url, b2.url FROM vods_video_src_b_2_links vsl
|
||||
JOIN b2_files b2 ON vsl.b_2_file_id = b2.id
|
||||
WHERE vsl.vod_id = $1 LIMIT 1`,
|
||||
[vod.id]
|
||||
);
|
||||
|
||||
// Get Mux asset and playback ID
|
||||
const muxLink = await v1.query(
|
||||
`SELECT m.asset_id, m.playback_id
|
||||
FROM vods_mux_asset_links vmal
|
||||
JOIN mux_assets m ON vmal.mux_asset_id = m.id
|
||||
WHERE vmal.vod_id = $1 LIMIT 1`,
|
||||
[vod.id]
|
||||
);
|
||||
|
||||
|
||||
const muxAssetId = muxLink.rows[0]?.asset_id || null;
|
||||
const muxPlaybackId = muxLink.rows[0]?.playback_id || null;
|
||||
|
||||
|
||||
// @chatgpt we need one more
|
||||
// we need to populate videoSrcB2
|
||||
// we want the cdn_url from b2_files
|
||||
// we have to get the link from the vods_video_src_b_2_links table
|
||||
|
||||
|
||||
vods.push({
|
||||
streamDate: vod.date ?? new Date(),
|
||||
notes: vod.note,
|
||||
sourceVideo: (() => {
|
||||
const u = videoSrcLink.rows[0]?.cdn_url || videoSrcLink.rows[0]?.url || null;
|
||||
return u ? 'content' + new URL(u).pathname : null;
|
||||
})(),
|
||||
thumbnail: (() => {
|
||||
const u = thumbLink.rows[0]?.cdn_url || thumbLink.rows[0]?.url || null;
|
||||
return u ? 'content' + new URL(u).pathname : null;
|
||||
})(),
|
||||
ipfsCid: vod.video_src_hash,
|
||||
videoSrcB2: videoSrcLink.rows[0]?.cdn_url || null,
|
||||
muxAssetId,
|
||||
muxPlaybackId,
|
||||
});
|
||||
}
|
||||
|
||||
console.log(vods.at(0))
|
||||
const outPath = path.join(dataDir, 'vods.json');
|
||||
fs.writeFileSync(outPath, JSON.stringify(vods, null, 2), 'utf-8');
|
||||
console.log(`Migrated ${res.rows.length} vods → ${outPath}`);
|
||||
}
|
||||
|
||||
async function main() {
|
||||
try {
|
||||
await migrateVtubers();
|
||||
await migrateVods();
|
||||
} catch (err) {
|
||||
console.error(err);
|
||||
} finally {
|
||||
await v1.end();
|
||||
}
|
||||
}
|
||||
|
||||
main();
|
||||
|
||||
4172
services/pocketbase/utils/data_migrations/vods.json
Normal file
4172
services/pocketbase/utils/data_migrations/vods.json
Normal file
File diff suppressed because it is too large
Load Diff
94
services/pocketbase/utils/data_migrations/vtubers.json
Normal file
94
services/pocketbase/utils/data_migrations/vtubers.json
Normal file
@ -0,0 +1,94 @@
|
||||
[
|
||||
{
|
||||
"slug": "projektmelody",
|
||||
"displayName": "ProjektMelody",
|
||||
"chaturbate": "https://chaturbate.com/projektmelody",
|
||||
"twitter": "https://twitter.com/projektmelody",
|
||||
"patreon": "https://www.patreon.com/projektmelody",
|
||||
"twitch": "https://twitch.tv/projektmelody",
|
||||
"tiktok": "https://www.tiktok.com/@realprojektmelody",
|
||||
"onlyfans": "https://onlyfans.com/projektbutt",
|
||||
"youtube": "https://www.youtube.com/projektmelodyofficial",
|
||||
"linktree": "https://linktr.ee/projektmelody",
|
||||
"carrd": null,
|
||||
"fansly": "https://fansly.com/r/scienceteam",
|
||||
"pornhub": "https://www.pornhub.com/model/projekt-melody",
|
||||
"discord": null,
|
||||
"reddit": "https://www.reddit.com/r/projektmelody/",
|
||||
"throne": "https://throne.com/realprojektmelody",
|
||||
"instagram": null,
|
||||
"facebook": null,
|
||||
"merch": "https://melody.vshojo.com/",
|
||||
"description": "Also known as, \"Daddy's little grandpa,\" ProjektMelody is the pioneering hentai cam model who embodies a unique blend of sweetness and perversion. She engages with her audience with remarkable patience and politeness, demonstrating her commitment to fostering an inclusive environment.\nOn her livestreams, ProjektMelody's demeanor can range from overtly sexual to adorably reserved and self-censored. Alongside her captivating presence, she actively promotes pro-social behavior, advocates for sexual education, and emphasizes the importance of kindness.",
|
||||
"themeColor": "#5C23C0"
|
||||
},
|
||||
{
|
||||
"slug": "el_xox",
|
||||
"displayName": "el_XoX",
|
||||
"chaturbate": "https://chaturbate.com/el_xox/",
|
||||
"twitter": "https://twitter.com/el_XoX34",
|
||||
"patreon": null,
|
||||
"twitch": "https://www.twitch.tv/el_xox",
|
||||
"tiktok": null,
|
||||
"onlyfans": null,
|
||||
"youtube": null,
|
||||
"linktree": null,
|
||||
"carrd": "https://elxox.carrd.co/",
|
||||
"fansly": null,
|
||||
"pornhub": null,
|
||||
"discord": null,
|
||||
"reddit": null,
|
||||
"throne": null,
|
||||
"instagram": null,
|
||||
"facebook": null,
|
||||
"merch": "https://elxox34.com/pages/limited-merch",
|
||||
"description": null,
|
||||
"themeColor": "#353FFF"
|
||||
},
|
||||
{
|
||||
"slug": "vexruby",
|
||||
"displayName": "Vexruby",
|
||||
"chaturbate": "https://chaturbate.com/vexruby",
|
||||
"twitter": "https://x.com/vexxxruby",
|
||||
"patreon": "https://www.patreon.com/ViRoClub",
|
||||
"twitch": null,
|
||||
"tiktok": null,
|
||||
"onlyfans": null,
|
||||
"youtube": null,
|
||||
"linktree": null,
|
||||
"carrd": null,
|
||||
"fansly": null,
|
||||
"pornhub": null,
|
||||
"discord": null,
|
||||
"reddit": null,
|
||||
"throne": null,
|
||||
"instagram": null,
|
||||
"facebook": null,
|
||||
"merch": null,
|
||||
"description": null,
|
||||
"themeColor": "#f882f5"
|
||||
},
|
||||
{
|
||||
"slug": "athena_airis",
|
||||
"displayName": "AIRIS ATHENA",
|
||||
"chaturbate": "https://chaturbate.com/athena_airis/",
|
||||
"twitter": "https://twitter.com/Athena_Airis",
|
||||
"patreon": null,
|
||||
"twitch": "https://www.twitch.tv/athena_airis",
|
||||
"tiktok": "https://tiktok.com/@athena_airis",
|
||||
"onlyfans": null,
|
||||
"youtube": "https://www.youtube.com/channel/UClizqUqSuy26sO01qsPh5bw",
|
||||
"linktree": "https://linktr.ee/athenaairis",
|
||||
"carrd": null,
|
||||
"fansly": "https://fansly.com/Athena-Airis",
|
||||
"pornhub": null,
|
||||
"discord": "https://discord.gg/eXPTgua",
|
||||
"reddit": null,
|
||||
"throne": null,
|
||||
"instagram": "https://instagram.com/theathenaairis",
|
||||
"facebook": null,
|
||||
"merch": null,
|
||||
"description": null,
|
||||
"themeColor": "#dde1ec"
|
||||
}
|
||||
]
|
||||
43
services/pocketbase/utils/deploy.js
Normal file
43
services/pocketbase/utils/deploy.js
Normal file
@ -0,0 +1,43 @@
|
||||
#!/usr/bin/env node
|
||||
|
||||
import PocketBase from 'pocketbase';
|
||||
import { spawn } from 'node:child_process';
|
||||
import util from 'node:util';
|
||||
const spawnAsync = util.promisify(spawn);
|
||||
|
||||
if (!process.env.POCKETBASE_PASSWORD) throw new Error('POCKETBASE_PASSWORD missing in env');
|
||||
if (!process.env.POCKETBASE_USERNAME) throw new Error('POCKETBASE_USERNAME missing in env');
|
||||
if (!process.env.APPURL) throw new Error('APPURL missing in env');
|
||||
|
||||
const pb = new PocketBase('http://localhost:8090');
|
||||
|
||||
await pb
|
||||
.collection("_superusers")
|
||||
.authWithPassword(process.env.POCKETBASE_USERNAME, process.env.POCKETBASE_PASSWORD);
|
||||
|
||||
// change to the production APPURL
|
||||
await pb.settings.update({
|
||||
meta: {
|
||||
appName: 'Futureporn',
|
||||
appUrl: 'https://futureporn.net',
|
||||
},
|
||||
});
|
||||
|
||||
// upload the site
|
||||
spawnAsync('rsync', [
|
||||
'-avz',
|
||||
'-e',
|
||||
'ssh',
|
||||
'.',
|
||||
'root@fp:/home/pb/pb'
|
||||
]);
|
||||
|
||||
// @see https://pocketbase.io/docs/api-settings/#update-settings
|
||||
|
||||
// put it back to dev app url
|
||||
await pb.settings.update({
|
||||
meta: {
|
||||
appName: 'Futureporn',
|
||||
appUrl: process.env.APPURL,
|
||||
},
|
||||
});
|
||||
Loading…
x
Reference in New Issue
Block a user