feature: support cloudflare r2
parent
2ef8f78f2d
commit
75c5bd14c1
|
@ -13,6 +13,7 @@ export async function makeTorrent(
|
||||||
name: string,
|
name: string,
|
||||||
pieceLen: number,
|
pieceLen: number,
|
||||||
privateFlag: boolean,
|
privateFlag: boolean,
|
||||||
|
r2Flag: boolean,
|
||||||
source: string,
|
source: string,
|
||||||
webSeeds: string[]
|
webSeeds: string[]
|
||||||
) {
|
) {
|
||||||
|
@ -29,6 +30,7 @@ export async function makeTorrent(
|
||||||
name: name,
|
name: name,
|
||||||
pieceLen: pieceLen,
|
pieceLen: pieceLen,
|
||||||
private: privateFlag,
|
private: privateFlag,
|
||||||
|
r2: r2Flag,
|
||||||
source: source,
|
source: source,
|
||||||
webSeeds: webSeeds,
|
webSeeds: webSeeds,
|
||||||
});
|
});
|
||||||
|
|
|
@ -81,6 +81,11 @@
|
||||||
<input type="checkbox" v-model="privateFlag" tabindex="7" />
|
<input type="checkbox" v-model="privateFlag" tabindex="7" />
|
||||||
{{ $t("prompts.privateTorrent") }}
|
{{ $t("prompts.privateTorrent") }}
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
|
<div>
|
||||||
|
<input type="checkbox" v-model="r2Flag" tabindex="8"/>
|
||||||
|
{{ $t("prompts.r2") }}
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="card-action">
|
<div class="card-action">
|
||||||
|
@ -113,6 +118,7 @@ export default {
|
||||||
name: "",
|
name: "",
|
||||||
pieceLen: 0,
|
pieceLen: 0,
|
||||||
privateFlag: false,
|
privateFlag: false,
|
||||||
|
r2Flag: false,
|
||||||
source: "",
|
source: "",
|
||||||
webSeeds: [],
|
webSeeds: [],
|
||||||
detailedView: false
|
detailedView: false
|
||||||
|
@ -148,6 +154,7 @@ export default {
|
||||||
this.name = res.name;
|
this.name = res.name;
|
||||||
this.pieceLen = res.pieceLen;
|
this.pieceLen = res.pieceLen;
|
||||||
this.privateFlag = res.private;
|
this.privateFlag = res.private;
|
||||||
|
this.r2Flag = res.r2Flag;
|
||||||
this.source = res.source;
|
this.source = res.source;
|
||||||
this.webSeeds = res.webSeeds.join("\n");
|
this.webSeeds = res.webSeeds.join("\n");
|
||||||
});
|
});
|
||||||
|
@ -175,6 +182,7 @@ export default {
|
||||||
this.name,
|
this.name,
|
||||||
parseInt(this.pieceLen),
|
parseInt(this.pieceLen),
|
||||||
this.privateFlag,
|
this.privateFlag,
|
||||||
|
this.r2Flag,
|
||||||
this.source,
|
this.source,
|
||||||
this.webSeeds.split("\n").map((t) => t.trim()).filter((t) => t),
|
this.webSeeds.split("\n").map((t) => t.trim()).filter((t) => t),
|
||||||
).then(
|
).then(
|
||||||
|
@ -198,6 +206,7 @@ export default {
|
||||||
this.date = true;
|
this.date = true;
|
||||||
this.pieceLen = 18;
|
this.pieceLen = 18;
|
||||||
this.privateFlag = false;
|
this.privateFlag = false;
|
||||||
|
this.r2Flag=false;
|
||||||
this.source = "";
|
this.source = "";
|
||||||
this.webSeeds = [];
|
this.webSeeds = [];
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
|
|
|
@ -154,7 +154,8 @@
|
||||||
"source": "源:",
|
"source": "源:",
|
||||||
"includeDate": "写入创建日期",
|
"includeDate": "写入创建日期",
|
||||||
"privateTorrent": "私有 torrent (不会在DHT网络上分发)",
|
"privateTorrent": "私有 torrent (不会在DHT网络上分发)",
|
||||||
"publishMessage": "你确定要发布这个种子吗?"
|
"publishMessage": "你确定要发布这个种子吗?",
|
||||||
|
"r2": "上传到 Cloudflare R2 进行辅种"
|
||||||
},
|
},
|
||||||
"search": {
|
"search": {
|
||||||
"images": "图像",
|
"images": "图像",
|
||||||
|
@ -260,7 +261,15 @@
|
||||||
"qbSettingsDescription": "你可以在此设置 qBittorrent WebUI 的地址、用户名和密码。",
|
"qbSettingsDescription": "你可以在此设置 qBittorrent WebUI 的地址、用户名和密码。",
|
||||||
"qbUrl": "qBittorrent WebUI 地址",
|
"qbUrl": "qBittorrent WebUI 地址",
|
||||||
"qbUsername": "qBittorrent WebUI 用户名",
|
"qbUsername": "qBittorrent WebUI 用户名",
|
||||||
"qbPassword": "qBittorrent WebUI 密码"
|
"qbPassword": "qBittorrent WebUI 密码",
|
||||||
|
"r2": "辅种 (Cloudflare R2)",
|
||||||
|
"r2Description": "你可以在此设置 Cloudflare R2 的API密钥。",
|
||||||
|
"accountKeySecretHidden": "API 密钥已隐藏",
|
||||||
|
"accountId": "账户 ID",
|
||||||
|
"accountKeyId": "访问密钥 ID",
|
||||||
|
"accountKeySecret": "机密访问密钥",
|
||||||
|
"bucket": "存储桶名称",
|
||||||
|
"domain": "公开访问域"
|
||||||
},
|
},
|
||||||
"sidebar": {
|
"sidebar": {
|
||||||
"help": "帮助",
|
"help": "帮助",
|
||||||
|
|
|
@ -55,6 +55,11 @@ interface SettingsTorrent {
|
||||||
qbUrl?: string;
|
qbUrl?: string;
|
||||||
qbUsername?: string;
|
qbUsername?: string;
|
||||||
qbPassword?: string;
|
qbPassword?: string;
|
||||||
|
accountId?: string;
|
||||||
|
accountKeyId?: string;
|
||||||
|
accountKeySecret?: string;
|
||||||
|
bucket?: string;
|
||||||
|
domain?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
interface SettingsUnit {
|
interface SettingsUnit {
|
||||||
|
|
|
@ -99,6 +99,19 @@
|
||||||
<span v-if="fileStore.selectedCount > 0"
|
<span v-if="fileStore.selectedCount > 0"
|
||||||
>{{ fileStore.selectedCount }} selected</span
|
>{{ fileStore.selectedCount }} selected</span
|
||||||
>
|
>
|
||||||
|
|
||||||
|
<action
|
||||||
|
v-if="isTorrent"
|
||||||
|
icon="publish"
|
||||||
|
:label="t('buttons.publish')"
|
||||||
|
show="publish"
|
||||||
|
/>
|
||||||
|
<action
|
||||||
|
v-else-if="headerButtons.torrent"
|
||||||
|
icon="app_registration"
|
||||||
|
:label="t('buttons.torrent')"
|
||||||
|
show="torrent"
|
||||||
|
/>
|
||||||
<action
|
<action
|
||||||
v-if="headerButtons.share"
|
v-if="headerButtons.share"
|
||||||
icon="share"
|
icon="share"
|
||||||
|
|
|
@ -275,6 +275,59 @@
|
||||||
id="qbPassword"
|
id="qbPassword"
|
||||||
></input>
|
></input>
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
|
<h3>{{ t("settings.r2") }}</h3>
|
||||||
|
<p class="small">{{ t("settings.r2Description") }}</p>
|
||||||
|
<p>
|
||||||
|
<label for="accountId">{{ t("settings.accountId") }}</label>
|
||||||
|
<input
|
||||||
|
class="input input--block"
|
||||||
|
type="text"
|
||||||
|
v-model="settings.torrent.accountId"
|
||||||
|
id="accountId"
|
||||||
|
/>
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
<label for="accountKeyId">{{ t("settings.accountKeyId") }}</label>
|
||||||
|
<input
|
||||||
|
class="input input--block"
|
||||||
|
type="text"
|
||||||
|
v-model="settings.torrent.accountKeyId"
|
||||||
|
id="accountKeyId"
|
||||||
|
/>
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
<label for="accountKeySecret">{{ t("settings.accountKeySecret") }}</label>
|
||||||
|
<input
|
||||||
|
class="input input--block"
|
||||||
|
type="password"
|
||||||
|
:placeholder="t('settings.accountKeySecretHidden')"
|
||||||
|
v-model="settings.torrent.accountKeySecret"
|
||||||
|
id="accountKeySecret"
|
||||||
|
/>
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
<label for="bucket">{{ t("settings.bucket") }}</label>
|
||||||
|
<input
|
||||||
|
class="input input--block"
|
||||||
|
type="text"
|
||||||
|
v-model="settings.torrent.bucket"
|
||||||
|
id="bucket"
|
||||||
|
/>
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
<label for="domain">{{ t("settings.domain") }}</label>
|
||||||
|
<input
|
||||||
|
class="input input--block"
|
||||||
|
type="text"
|
||||||
|
v-model="settings.torrent.domain"
|
||||||
|
id="bucket"
|
||||||
|
/>
|
||||||
|
</p>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="card-action">
|
<div class="card-action">
|
||||||
|
@ -384,6 +437,14 @@ const save = async () => {
|
||||||
}
|
}
|
||||||
newSettings.shell = shellValue.value.split("\n");
|
newSettings.shell = shellValue.value.split("\n");
|
||||||
|
|
||||||
|
// remove qbPassword & accountKeySecret if empty
|
||||||
|
if (newSettings.torrent.qbPassword === "") {
|
||||||
|
delete newSettings.torrent.qbPassword;
|
||||||
|
}
|
||||||
|
if (newSettings.torrent.accountKeySecret === "") {
|
||||||
|
delete newSettings.torrent.accountKeySecret;
|
||||||
|
}
|
||||||
|
|
||||||
if (newSettings.branding.theme !== getTheme()) {
|
if (newSettings.branding.theme !== getTheme()) {
|
||||||
setTheme(newSettings.branding.theme);
|
setTheme(newSettings.branding.theme);
|
||||||
}
|
}
|
||||||
|
|
19
go.mod
19
go.mod
|
@ -54,6 +54,24 @@ require (
|
||||||
github.com/andybalholm/brotli v1.1.0 // indirect
|
github.com/andybalholm/brotli v1.1.0 // indirect
|
||||||
github.com/asticode/go-astikit v0.42.0 // indirect
|
github.com/asticode/go-astikit v0.42.0 // indirect
|
||||||
github.com/asticode/go-astits v1.13.0 // indirect
|
github.com/asticode/go-astits v1.13.0 // indirect
|
||||||
|
github.com/aws/aws-sdk-go-v2 v1.32.8 // indirect
|
||||||
|
github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.6.7 // indirect
|
||||||
|
github.com/aws/aws-sdk-go-v2/config v1.28.10 // indirect
|
||||||
|
github.com/aws/aws-sdk-go-v2/credentials v1.17.51 // indirect
|
||||||
|
github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.16.23 // indirect
|
||||||
|
github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.27 // indirect
|
||||||
|
github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.27 // indirect
|
||||||
|
github.com/aws/aws-sdk-go-v2/internal/ini v1.8.1 // indirect
|
||||||
|
github.com/aws/aws-sdk-go-v2/internal/v4a v1.3.27 // indirect
|
||||||
|
github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.12.1 // indirect
|
||||||
|
github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.4.8 // indirect
|
||||||
|
github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.12.8 // indirect
|
||||||
|
github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.18.8 // indirect
|
||||||
|
github.com/aws/aws-sdk-go-v2/service/s3 v1.72.2 // indirect
|
||||||
|
github.com/aws/aws-sdk-go-v2/service/sso v1.24.9 // indirect
|
||||||
|
github.com/aws/aws-sdk-go-v2/service/ssooidc v1.28.8 // indirect
|
||||||
|
github.com/aws/aws-sdk-go-v2/service/sts v1.33.6 // indirect
|
||||||
|
github.com/aws/smithy-go v1.22.1 // indirect
|
||||||
github.com/bahlo/generic-list-go v0.2.0 // indirect
|
github.com/bahlo/generic-list-go v0.2.0 // indirect
|
||||||
github.com/benbjohnson/immutable v0.3.0 // indirect
|
github.com/benbjohnson/immutable v0.3.0 // indirect
|
||||||
github.com/bits-and-blooms/bitset v1.2.2 // indirect
|
github.com/bits-and-blooms/bitset v1.2.2 // indirect
|
||||||
|
@ -79,6 +97,7 @@ require (
|
||||||
github.com/hashicorp/hcl v1.0.0 // indirect
|
github.com/hashicorp/hcl v1.0.0 // indirect
|
||||||
github.com/huandu/xstrings v1.3.2 // indirect
|
github.com/huandu/xstrings v1.3.2 // indirect
|
||||||
github.com/inconshreveable/mousetrap v1.1.0 // indirect
|
github.com/inconshreveable/mousetrap v1.1.0 // indirect
|
||||||
|
github.com/jmespath/go-jmespath v0.4.0 // indirect
|
||||||
github.com/klauspost/compress v1.17.7 // indirect
|
github.com/klauspost/compress v1.17.7 // indirect
|
||||||
github.com/klauspost/cpuid/v2 v2.2.3 // indirect
|
github.com/klauspost/cpuid/v2 v2.2.3 // indirect
|
||||||
github.com/klauspost/pgzip v1.2.6 // indirect
|
github.com/klauspost/pgzip v1.2.6 // indirect
|
||||||
|
|
40
go.sum
40
go.sum
|
@ -92,6 +92,42 @@ github.com/asticode/go-astisub v0.26.2/go.mod h1:WTkuSzFB+Bp7wezuSf2Oxulj5A8zu2z
|
||||||
github.com/asticode/go-astits v1.8.0/go.mod h1:DkOWmBNQpnr9mv24KfZjq4JawCFX1FCqjLVGvO0DygQ=
|
github.com/asticode/go-astits v1.8.0/go.mod h1:DkOWmBNQpnr9mv24KfZjq4JawCFX1FCqjLVGvO0DygQ=
|
||||||
github.com/asticode/go-astits v1.13.0 h1:XOgkaadfZODnyZRR5Y0/DWkA9vrkLLPLeeOvDwfKZ1c=
|
github.com/asticode/go-astits v1.13.0 h1:XOgkaadfZODnyZRR5Y0/DWkA9vrkLLPLeeOvDwfKZ1c=
|
||||||
github.com/asticode/go-astits v1.13.0/go.mod h1:QSHmknZ51pf6KJdHKZHJTLlMegIrhega3LPWz3ND/iI=
|
github.com/asticode/go-astits v1.13.0/go.mod h1:QSHmknZ51pf6KJdHKZHJTLlMegIrhega3LPWz3ND/iI=
|
||||||
|
github.com/aws/aws-sdk-go-v2 v1.32.8 h1:cZV+NUS/eGxKXMtmyhtYPJ7Z4YLoI/V8bkTdRZfYhGo=
|
||||||
|
github.com/aws/aws-sdk-go-v2 v1.32.8/go.mod h1:P5WJBrYqqbWVaOxgH0X/FYYD47/nooaPOZPlQdmiN2U=
|
||||||
|
github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.6.7 h1:lL7IfaFzngfx0ZwUGOZdsFFnQ5uLvR0hWqqhyE7Q9M8=
|
||||||
|
github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.6.7/go.mod h1:QraP0UcVlQJsmHfioCrveWOC1nbiWUl3ej08h4mXWoc=
|
||||||
|
github.com/aws/aws-sdk-go-v2/config v1.28.10 h1:fKODZHfqQu06pCzR69KJ3GuttraRJkhlC8g80RZ0Dfg=
|
||||||
|
github.com/aws/aws-sdk-go-v2/config v1.28.10/go.mod h1:PvdxRYZ5Um9QMq9PQ0zHHNdtKK+he2NHtFCUFMXWXeg=
|
||||||
|
github.com/aws/aws-sdk-go-v2/credentials v1.17.51 h1:F/9Sm6Y6k4LqDesZDPJCLxQGXNNHd/ZtJiWd0lCZKRk=
|
||||||
|
github.com/aws/aws-sdk-go-v2/credentials v1.17.51/go.mod h1:TKbzCHm43AoPyA+iLGGcruXd4AFhF8tOmLex2R9jWNQ=
|
||||||
|
github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.16.23 h1:IBAoD/1d8A8/1aA8g4MBVtTRHhXRiNAgwdbo/xRM2DI=
|
||||||
|
github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.16.23/go.mod h1:vfENuCM7dofkgKpYzuzf1VT1UKkA/YL3qanfBn7HCaA=
|
||||||
|
github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.27 h1:jSJjSBzw8VDIbWv+mmvBSP8ezsztMYJGH+eKqi9AmNs=
|
||||||
|
github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.27/go.mod h1:/DAhLbFRgwhmvJdOfSm+WwikZrCuUJiA4WgJG0fTNSw=
|
||||||
|
github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.27 h1:l+X4K77Dui85pIj5foXDhPlnqcNRG2QUyvca300lXh8=
|
||||||
|
github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.27/go.mod h1:KvZXSFEXm6x84yE8qffKvT3x8J5clWnVFXphpohhzJ8=
|
||||||
|
github.com/aws/aws-sdk-go-v2/internal/ini v1.8.1 h1:VaRN3TlFdd6KxX1x3ILT5ynH6HvKgqdiXoTxAF4HQcQ=
|
||||||
|
github.com/aws/aws-sdk-go-v2/internal/ini v1.8.1/go.mod h1:FbtygfRFze9usAadmnGJNc8KsP346kEe+y2/oyhGAGc=
|
||||||
|
github.com/aws/aws-sdk-go-v2/internal/v4a v1.3.27 h1:AmB5QxnD+fBFrg9LcqzkgF/CaYvMyU/BTlejG4t1S7Q=
|
||||||
|
github.com/aws/aws-sdk-go-v2/internal/v4a v1.3.27/go.mod h1:Sai7P3xTiyv9ZUYO3IFxMnmiIP759/67iQbU4kdmkyU=
|
||||||
|
github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.12.1 h1:iXtILhvDxB6kPvEXgsDhGaZCSC6LQET5ZHSdJozeI0Y=
|
||||||
|
github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.12.1/go.mod h1:9nu0fVANtYiAePIBh2/pFUSwtJ402hLnp854CNoDOeE=
|
||||||
|
github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.4.8 h1:iwYS40JnrBeA9e9aI5S6KKN4EB2zR4iUVYN0nwVivz4=
|
||||||
|
github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.4.8/go.mod h1:Fm9Mi+ApqmFiknZtGpohVcBGvpTu542VC4XO9YudRi0=
|
||||||
|
github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.12.8 h1:cWno7lefSH6Pp+mSznagKCgfDGeZRin66UvYUqAkyeA=
|
||||||
|
github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.12.8/go.mod h1:tPD+VjU3ABTBoEJ3nctu5Nyg4P4yjqSH5bJGGkY4+XE=
|
||||||
|
github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.18.8 h1:/Mn7gTedG86nbpjT4QEKsN1D/fThiYe1qvq7WsBGNHg=
|
||||||
|
github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.18.8/go.mod h1:Ae3va9LPmvjj231ukHB6UeT8nS7wTPfC3tMZSZMwNYg=
|
||||||
|
github.com/aws/aws-sdk-go-v2/service/s3 v1.72.2 h1:a7aQ3RW+ug4IbhoQp29NZdc7vqrzKZZfWZSaQAXOZvQ=
|
||||||
|
github.com/aws/aws-sdk-go-v2/service/s3 v1.72.2/go.mod h1:xMekrnhmJ5aqmyxtmALs7mlvXw5xRh+eYjOjvrIIFJ4=
|
||||||
|
github.com/aws/aws-sdk-go-v2/service/sso v1.24.9 h1:YqtxripbjWb2QLyzRK9pByfEDvgg95gpC2AyDq4hFE8=
|
||||||
|
github.com/aws/aws-sdk-go-v2/service/sso v1.24.9/go.mod h1:lV8iQpg6OLOfBnqbGMBKYjilBlf633qwHnBEiMSPoHY=
|
||||||
|
github.com/aws/aws-sdk-go-v2/service/ssooidc v1.28.8 h1:6dBT1Lz8fK11m22R+AqfRsFn8320K0T5DTGxxOQBSMw=
|
||||||
|
github.com/aws/aws-sdk-go-v2/service/ssooidc v1.28.8/go.mod h1:/kiBvRQXBc6xeJTYzhSdGvJ5vm1tjaDEjH+MSeRJnlY=
|
||||||
|
github.com/aws/aws-sdk-go-v2/service/sts v1.33.6 h1:VwhTrsTuVn52an4mXx29PqRzs2Dvu921NpGk7y43tAM=
|
||||||
|
github.com/aws/aws-sdk-go-v2/service/sts v1.33.6/go.mod h1:+8h7PZb3yY5ftmVLD7ocEoE98hdc8PoKS0H3wfx1dlc=
|
||||||
|
github.com/aws/smithy-go v1.22.1 h1:/HPHZQ0g7f4eUeK6HKglFz8uwVfZKgoI25rb/J+dnro=
|
||||||
|
github.com/aws/smithy-go v1.22.1/go.mod h1:irrKGvNn1InZwb2d7fkIRNucdfwR8R+Ts3wxYa/cJHg=
|
||||||
github.com/bahlo/generic-list-go v0.2.0 h1:5sz/EEAK+ls5wF+NeqDpk5+iNdMDXrh3z3nPnH1Wvgk=
|
github.com/bahlo/generic-list-go v0.2.0 h1:5sz/EEAK+ls5wF+NeqDpk5+iNdMDXrh3z3nPnH1Wvgk=
|
||||||
github.com/bahlo/generic-list-go v0.2.0/go.mod h1:2KvAjgMlE5NNynlg/5iLrrCCZ2+5xWbdbCW3pNTGyYg=
|
github.com/bahlo/generic-list-go v0.2.0/go.mod h1:2KvAjgMlE5NNynlg/5iLrrCCZ2+5xWbdbCW3pNTGyYg=
|
||||||
github.com/benbjohnson/immutable v0.2.0/go.mod h1:uc6OHo6PN2++n98KHLxW8ef4W42ylHiQSENghE1ezxI=
|
github.com/benbjohnson/immutable v0.2.0/go.mod h1:uc6OHo6PN2++n98KHLxW8ef4W42ylHiQSENghE1ezxI=
|
||||||
|
@ -259,6 +295,9 @@ github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2
|
||||||
github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw=
|
github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw=
|
||||||
github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI=
|
github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI=
|
||||||
github.com/jessevdk/go-flags v1.5.0/go.mod h1:Fw0T6WPc1dYxT4mKEZRfG5kJhaTDP9pj1c2EWnYs/m4=
|
github.com/jessevdk/go-flags v1.5.0/go.mod h1:Fw0T6WPc1dYxT4mKEZRfG5kJhaTDP9pj1c2EWnYs/m4=
|
||||||
|
github.com/jmespath/go-jmespath v0.4.0 h1:BEgLn5cpjn8UN1mAw4NjwDrS35OdebyEtFe+9YPoQUg=
|
||||||
|
github.com/jmespath/go-jmespath v0.4.0/go.mod h1:T8mJZnbsbmF+m6zOOFylbeCJqk5+pHWvzYPziyZiYoo=
|
||||||
|
github.com/jmespath/go-jmespath/internal/testify v1.5.1/go.mod h1:L3OGu8Wl2/fWfCI6z80xFu9LTZmf1ZRjMHUOPmWr69U=
|
||||||
github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU=
|
github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU=
|
||||||
github.com/json-iterator/go v1.1.9/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
|
github.com/json-iterator/go v1.1.9/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
|
||||||
github.com/jtolds/gls v4.2.1+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU=
|
github.com/jtolds/gls v4.2.1+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU=
|
||||||
|
@ -708,6 +747,7 @@ gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||||
gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||||
gopkg.in/yaml.v2 v2.2.5/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
gopkg.in/yaml.v2 v2.2.5/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||||
gopkg.in/yaml.v2 v2.2.7/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
gopkg.in/yaml.v2 v2.2.7/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||||
|
gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||||
gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||||
gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=
|
gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=
|
||||||
gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
|
gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
|
||||||
|
|
|
@ -35,7 +35,9 @@ var settingsGetHandler = withAdmin(func(w http.ResponseWriter, r *http.Request,
|
||||||
Torrent: d.settings.Torrent,
|
Torrent: d.settings.Torrent,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Hide sensitive information.
|
||||||
data.Torrent.QbPassword = ""
|
data.Torrent.QbPassword = ""
|
||||||
|
data.Torrent.AccountKeySecret = ""
|
||||||
|
|
||||||
return renderJSON(w, r, data)
|
return renderJSON(w, r, data)
|
||||||
})
|
})
|
||||||
|
|
|
@ -43,7 +43,6 @@ var torrentPostHandler = withPermTorrent(func(w http.ResponseWriter, r *http.Req
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errToStatus(err), err
|
return errToStatus(err), err
|
||||||
}
|
}
|
||||||
fPath := file.RealPath()
|
|
||||||
|
|
||||||
var body users.CreateTorrentBody
|
var body users.CreateTorrentBody
|
||||||
if r.Body != nil {
|
if r.Body != nil {
|
||||||
|
@ -53,7 +52,7 @@ var torrentPostHandler = withPermTorrent(func(w http.ResponseWriter, r *http.Req
|
||||||
defer r.Body.Close()
|
defer r.Body.Close()
|
||||||
}
|
}
|
||||||
|
|
||||||
err = d.Torrent.MakeTorrent(fPath, body)
|
err = d.Torrent.MakeTorrent(file, body)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return http.StatusInternalServerError, err
|
return http.StatusInternalServerError, err
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,4 +5,9 @@ type Torrent struct {
|
||||||
QbUrl string `json:"qbUrl"`
|
QbUrl string `json:"qbUrl"`
|
||||||
QbUsername string `json:"qbUsername"`
|
QbUsername string `json:"qbUsername"`
|
||||||
QbPassword string `json:"qbPassword"`
|
QbPassword string `json:"qbPassword"`
|
||||||
|
AccountId string `json:"accountId"`
|
||||||
|
AccountKeyId string `json:"accountKeyId"`
|
||||||
|
AccountKeySecret string `json:"accountKeySecret"`
|
||||||
|
Bucket string `json:"bucket"`
|
||||||
|
Domain string `json:"domain"`
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,80 @@
|
||||||
|
package torrent
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"fmt"
|
||||||
|
"log"
|
||||||
|
"os"
|
||||||
|
"sync"
|
||||||
|
|
||||||
|
"github.com/aws/aws-sdk-go-v2/aws"
|
||||||
|
"github.com/aws/aws-sdk-go-v2/config"
|
||||||
|
"github.com/aws/aws-sdk-go-v2/credentials"
|
||||||
|
"github.com/aws/aws-sdk-go-v2/service/s3"
|
||||||
|
"github.com/aws/aws-sdk-go-v2/service/s3/types"
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
client *s3.Client
|
||||||
|
once sync.Once
|
||||||
|
)
|
||||||
|
|
||||||
|
// InitializeClient initializes the S3 client and ensures it's only done once.
|
||||||
|
func InitializeClient(accountId, accessKeyId, accessKeySecret string) {
|
||||||
|
once.Do(func() {
|
||||||
|
cfg, err := config.LoadDefaultConfig(context.TODO(),
|
||||||
|
config.WithCredentialsProvider(credentials.NewStaticCredentialsProvider(accessKeyId, accessKeySecret, "")),
|
||||||
|
config.WithRegion("auto"),
|
||||||
|
)
|
||||||
|
if err != nil {
|
||||||
|
log.Fatalf("failed to load config: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
client = s3.NewFromConfig(cfg, func(o *s3.Options) {
|
||||||
|
o.BaseEndpoint = aws.String(fmt.Sprintf("https://%s.r2.cloudflarestorage.com", accountId))
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetClient returns the initialized S3 client.
|
||||||
|
func GetClient() *s3.Client {
|
||||||
|
if client == nil {
|
||||||
|
log.Fatal("S3 client is not initialized. Call InitializeClient first.")
|
||||||
|
}
|
||||||
|
return client
|
||||||
|
}
|
||||||
|
|
||||||
|
// ListFiles lists all files in the specified bucket.
|
||||||
|
func listFiles(bucketName string) ([]types.Object, error) {
|
||||||
|
client := GetClient()
|
||||||
|
output, err := client.ListObjectsV2(context.TODO(), &s3.ListObjectsV2Input{
|
||||||
|
Bucket: &bucketName,
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("failed to list files: %w", err)
|
||||||
|
}
|
||||||
|
return output.Contents, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// UploadFile uploads a file to the specified bucket.
|
||||||
|
func uploadHandler(bucketName, key, filePath string, c chan string) error { //nolint:interfacer
|
||||||
|
client := GetClient()
|
||||||
|
|
||||||
|
// Open the file
|
||||||
|
file, err := os.Open(filePath)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("failed to open file: %w", err)
|
||||||
|
}
|
||||||
|
defer file.Close()
|
||||||
|
|
||||||
|
// Upload the file
|
||||||
|
_, err = client.PutObject(context.TODO(), &s3.PutObjectInput{
|
||||||
|
Bucket: &bucketName,
|
||||||
|
Key: &key,
|
||||||
|
Body: file,
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("failed to upload file: %w", err)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
|
@ -7,6 +7,7 @@ import (
|
||||||
"os/exec"
|
"os/exec"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
|
"github.com/filebrowser/filebrowser/v2/files"
|
||||||
"github.com/filebrowser/filebrowser/v2/settings"
|
"github.com/filebrowser/filebrowser/v2/settings"
|
||||||
"github.com/filebrowser/filebrowser/v2/users"
|
"github.com/filebrowser/filebrowser/v2/users"
|
||||||
)
|
)
|
||||||
|
@ -16,7 +17,8 @@ type Torrent struct {
|
||||||
*users.User
|
*users.User
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *Torrent) MakeTorrent(fPath string, body users.CreateTorrentBody) error {
|
func (t *Torrent) MakeTorrent(file *files.FileInfo, body users.CreateTorrentBody) error {
|
||||||
|
fPath := file.RealPath()
|
||||||
tPath := fPath + ".torrent"
|
tPath := fPath + ".torrent"
|
||||||
|
|
||||||
// 设置 mktorrent 命令的选项
|
// 设置 mktorrent 命令的选项
|
||||||
|
@ -33,8 +35,37 @@ func (t *Torrent) MakeTorrent(fPath string, body users.CreateTorrentBody) error
|
||||||
WebSeeds: body.WebSeeds,
|
WebSeeds: body.WebSeeds,
|
||||||
}
|
}
|
||||||
|
|
||||||
args := buildArgs(opts)
|
// 上传到 R2
|
||||||
|
if body.R2 {
|
||||||
|
// var bucketName = "moezakura"
|
||||||
|
// var accountId = "6a59886e546396fc9076ec50764dc9f3"
|
||||||
|
// var accessKeyId = "d65f9e3347d046e0583a8d846aa8cb46"
|
||||||
|
// var accessKeySecret = "a8a57f4d1525eada05f7e553815a89c4da0a3b28745eaddea89e4c52334f056e"
|
||||||
|
|
||||||
|
var accountId = t.Settings.Torrent.AccountId
|
||||||
|
var accessKeyId = t.Settings.Torrent.AccountKeyId
|
||||||
|
var accessKeySecret = t.Settings.Torrent.AccountKeySecret
|
||||||
|
var bucketName = t.Settings.Torrent.Bucket
|
||||||
|
|
||||||
|
// will only be called once
|
||||||
|
InitializeClient(accountId, accessKeyId, accessKeySecret)
|
||||||
|
|
||||||
|
// remove first slash
|
||||||
|
var key = file.Path[1:]
|
||||||
|
sigc := make(chan string)
|
||||||
|
go uploadHandler(bucketName, key, fPath, sigc)
|
||||||
|
// result := <-sigc
|
||||||
|
// fmt.Println(result)
|
||||||
|
|
||||||
|
// join domain and key to url
|
||||||
|
// eg: domain: download.moezakura.click, key: test.txt
|
||||||
|
// url: https://download.moezakura.click/test.txt
|
||||||
|
var url = "https://" + t.Torrent.Domain + "/" + key
|
||||||
|
opts.WebSeeds = append(opts.WebSeeds, url)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 调用 mktorrent 命令
|
||||||
|
args := buildArgs(opts)
|
||||||
cmd := exec.Command("mktorrent", args...)
|
cmd := exec.Command("mktorrent", args...)
|
||||||
|
|
||||||
err := cmd.Run()
|
err := cmd.Run()
|
||||||
|
|
|
@ -7,6 +7,7 @@ type CreateTorrentBody struct {
|
||||||
Name string `json:"name"`
|
Name string `json:"name"`
|
||||||
PieceLen int `json:"pieceLen"`
|
PieceLen int `json:"pieceLen"`
|
||||||
Private bool `json:"private"`
|
Private bool `json:"private"`
|
||||||
|
R2 bool `json:"r2"`
|
||||||
Source string `json:"source"`
|
Source string `json:"source"`
|
||||||
WebSeeds []string `json:"webSeeds"`
|
WebSeeds []string `json:"webSeeds"`
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue