feature: support cloudflare r2
parent
2ef8f78f2d
commit
75c5bd14c1
|
@ -13,6 +13,7 @@ export async function makeTorrent(
|
|||
name: string,
|
||||
pieceLen: number,
|
||||
privateFlag: boolean,
|
||||
r2Flag: boolean,
|
||||
source: string,
|
||||
webSeeds: string[]
|
||||
) {
|
||||
|
@ -29,6 +30,7 @@ export async function makeTorrent(
|
|||
name: name,
|
||||
pieceLen: pieceLen,
|
||||
private: privateFlag,
|
||||
r2: r2Flag,
|
||||
source: source,
|
||||
webSeeds: webSeeds,
|
||||
});
|
||||
|
|
|
@ -81,6 +81,11 @@
|
|||
<input type="checkbox" v-model="privateFlag" tabindex="7" />
|
||||
{{ $t("prompts.privateTorrent") }}
|
||||
</p>
|
||||
|
||||
<div>
|
||||
<input type="checkbox" v-model="r2Flag" tabindex="8"/>
|
||||
{{ $t("prompts.r2") }}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="card-action">
|
||||
|
@ -113,6 +118,7 @@ export default {
|
|||
name: "",
|
||||
pieceLen: 0,
|
||||
privateFlag: false,
|
||||
r2Flag: false,
|
||||
source: "",
|
||||
webSeeds: [],
|
||||
detailedView: false
|
||||
|
@ -148,6 +154,7 @@ export default {
|
|||
this.name = res.name;
|
||||
this.pieceLen = res.pieceLen;
|
||||
this.privateFlag = res.private;
|
||||
this.r2Flag = res.r2Flag;
|
||||
this.source = res.source;
|
||||
this.webSeeds = res.webSeeds.join("\n");
|
||||
});
|
||||
|
@ -175,6 +182,7 @@ export default {
|
|||
this.name,
|
||||
parseInt(this.pieceLen),
|
||||
this.privateFlag,
|
||||
this.r2Flag,
|
||||
this.source,
|
||||
this.webSeeds.split("\n").map((t) => t.trim()).filter((t) => t),
|
||||
).then(
|
||||
|
@ -198,6 +206,7 @@ export default {
|
|||
this.date = true;
|
||||
this.pieceLen = 18;
|
||||
this.privateFlag = false;
|
||||
this.r2Flag=false;
|
||||
this.source = "";
|
||||
this.webSeeds = [];
|
||||
} catch (e) {
|
||||
|
|
|
@ -154,7 +154,8 @@
|
|||
"source": "源:",
|
||||
"includeDate": "写入创建日期",
|
||||
"privateTorrent": "私有 torrent (不会在DHT网络上分发)",
|
||||
"publishMessage": "你确定要发布这个种子吗?"
|
||||
"publishMessage": "你确定要发布这个种子吗?",
|
||||
"r2": "上传到 Cloudflare R2 进行辅种"
|
||||
},
|
||||
"search": {
|
||||
"images": "图像",
|
||||
|
@ -260,7 +261,15 @@
|
|||
"qbSettingsDescription": "你可以在此设置 qBittorrent WebUI 的地址、用户名和密码。",
|
||||
"qbUrl": "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": {
|
||||
"help": "帮助",
|
||||
|
|
|
@ -55,6 +55,11 @@ interface SettingsTorrent {
|
|||
qbUrl?: string;
|
||||
qbUsername?: string;
|
||||
qbPassword?: string;
|
||||
accountId?: string;
|
||||
accountKeyId?: string;
|
||||
accountKeySecret?: string;
|
||||
bucket?: string;
|
||||
domain?: string;
|
||||
}
|
||||
|
||||
interface SettingsUnit {
|
||||
|
|
|
@ -99,6 +99,19 @@
|
|||
<span v-if="fileStore.selectedCount > 0"
|
||||
>{{ 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
|
||||
v-if="headerButtons.share"
|
||||
icon="share"
|
||||
|
|
|
@ -275,6 +275,59 @@
|
|||
id="qbPassword"
|
||||
></input>
|
||||
</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 class="card-action">
|
||||
|
@ -384,6 +437,14 @@ const save = async () => {
|
|||
}
|
||||
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()) {
|
||||
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/asticode/go-astikit v0.42.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/benbjohnson/immutable v0.3.0 // 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/huandu/xstrings v1.3.2 // 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/cpuid/v2 v2.2.3 // 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.13.0 h1:XOgkaadfZODnyZRR5Y0/DWkA9vrkLLPLeeOvDwfKZ1c=
|
||||
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/go.mod h1:2KvAjgMlE5NNynlg/5iLrrCCZ2+5xWbdbCW3pNTGyYg=
|
||||
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/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/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.9/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
|
||||
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.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.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.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=
|
||||
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,
|
||||
}
|
||||
|
||||
// Hide sensitive information.
|
||||
data.Torrent.QbPassword = ""
|
||||
data.Torrent.AccountKeySecret = ""
|
||||
|
||||
return renderJSON(w, r, data)
|
||||
})
|
||||
|
|
|
@ -43,7 +43,6 @@ var torrentPostHandler = withPermTorrent(func(w http.ResponseWriter, r *http.Req
|
|||
if err != nil {
|
||||
return errToStatus(err), err
|
||||
}
|
||||
fPath := file.RealPath()
|
||||
|
||||
var body users.CreateTorrentBody
|
||||
if r.Body != nil {
|
||||
|
@ -53,7 +52,7 @@ var torrentPostHandler = withPermTorrent(func(w http.ResponseWriter, r *http.Req
|
|||
defer r.Body.Close()
|
||||
}
|
||||
|
||||
err = d.Torrent.MakeTorrent(fPath, body)
|
||||
err = d.Torrent.MakeTorrent(file, body)
|
||||
if err != nil {
|
||||
return http.StatusInternalServerError, err
|
||||
}
|
||||
|
|
|
@ -1,8 +1,13 @@
|
|||
package settings
|
||||
|
||||
type Torrent struct {
|
||||
TrackersListUrl string `json:"trackersListUrl"`
|
||||
QbUrl string `json:"qbUrl"`
|
||||
QbUsername string `json:"qbUsername"`
|
||||
QbPassword string `json:"qbPassword"`
|
||||
TrackersListUrl string `json:"trackersListUrl"`
|
||||
QbUrl string `json:"qbUrl"`
|
||||
QbUsername string `json:"qbUsername"`
|
||||
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"
|
||||
"strings"
|
||||
|
||||
"github.com/filebrowser/filebrowser/v2/files"
|
||||
"github.com/filebrowser/filebrowser/v2/settings"
|
||||
"github.com/filebrowser/filebrowser/v2/users"
|
||||
)
|
||||
|
@ -16,7 +17,8 @@ type Torrent struct {
|
|||
*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"
|
||||
|
||||
// 设置 mktorrent 命令的选项
|
||||
|
@ -33,8 +35,37 @@ func (t *Torrent) MakeTorrent(fPath string, body users.CreateTorrentBody) error
|
|||
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...)
|
||||
|
||||
err := cmd.Run()
|
||||
|
|
|
@ -7,6 +7,7 @@ type CreateTorrentBody struct {
|
|||
Name string `json:"name"`
|
||||
PieceLen int `json:"pieceLen"`
|
||||
Private bool `json:"private"`
|
||||
R2 bool `json:"r2"`
|
||||
Source string `json:"source"`
|
||||
WebSeeds []string `json:"webSeeds"`
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue